Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 623af59

Browse filesBrowse files
committed
resolve form type's FQCN in suggestions
1 parent e8ae846 commit 623af59
Copy full SHA for 623af59

File tree

4 files changed

+171
-19
lines changed
Filter options

4 files changed

+171
-19
lines changed

‎src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
+3-2Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,13 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti
139139
{
140140
if ($input->mustSuggestArgumentValuesFor('name')) {
141141
$suggestions->suggestValues(array_keys($this->router->getRouteCollection()->all()));
142+
143+
return;
142144
}
143145

144146
if ($input->mustSuggestOptionValuesFor('format')) {
145147
$helper = new DescriptorHelper();
146-
// @todo wait for getFormats() method to be implemented
147-
//$suggestions->suggestValues($helper->getFormats());
148+
$suggestions->suggestValues($helper->getFormats());
148149
}
149150
}
150151
}

‎src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/Functional/RouterDebugCommandTest.php
+28Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
1313

1414
use Symfony\Bundle\FrameworkBundle\Console\Application;
15+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1516
use Symfony\Component\Console\Tester\CommandTester;
1617

1718
/**
@@ -69,6 +70,33 @@ public function testSearchWithThrow()
6970
$tester->execute(['name' => 'gerard'], ['interactive' => true]);
7071
}
7172

73+
/**
74+
* @dataProvider provideCompletionSuggestions
75+
*/
76+
public function testComplete(array $input, array $expectedSuggestions)
77+
{
78+
$tester = new CommandCompletionTester($this->application->get('debug:router'));
79+
$this->assertSame($expectedSuggestions, $tester->complete($input));
80+
}
81+
82+
public function provideCompletionSuggestions()
83+
{
84+
yield 'option --format' => [
85+
['--format', ''],
86+
['txt', 'xml', 'json', 'md'],
87+
];
88+
89+
yield 'route_name' => [
90+
[''],
91+
[
92+
'routerdebug_session_welcome',
93+
'routerdebug_session_welcome_name',
94+
'routerdebug_session_logout',
95+
'routerdebug_test',
96+
],
97+
];
98+
}
99+
72100
private function createCommandTester(): CommandTester
73101
{
74102
$command = $this->application->get('debug:router');

‎src/Symfony/Component/Form/Command/DebugCommand.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Command/DebugCommand.php
+50-17Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -162,19 +162,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
162162

163163
private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, string $shortClassName): string
164164
{
165-
$classes = [];
166-
sort($this->namespaces);
167-
foreach ($this->namespaces as $namespace) {
168-
if (class_exists($fqcn = $namespace.'\\'.$shortClassName)) {
169-
$classes[] = $fqcn;
170-
} elseif (class_exists($fqcn = $namespace.'\\'.ucfirst($shortClassName))) {
171-
$classes[] = $fqcn;
172-
} elseif (class_exists($fqcn = $namespace.'\\'.ucfirst($shortClassName).'Type')) {
173-
$classes[] = $fqcn;
174-
} elseif (str_ends_with($shortClassName, 'type') && class_exists($fqcn = $namespace.'\\'.ucfirst(substr($shortClassName, 0, -4).'Type'))) {
175-
$classes[] = $fqcn;
176-
}
177-
}
165+
$classes = $this->getFqcnTypeClasses($shortClassName);
178166

179167
if (0 === $count = \count($classes)) {
180168
$message = sprintf("Could not find type \"%s\" into the following namespaces:\n %s", $shortClassName, implode("\n ", $this->namespaces));
@@ -201,6 +189,25 @@ private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, strin
201189
return $io->choice(sprintf("The type \"%s\" is ambiguous.\n\nSelect one of the following form types to display its information:", $shortClassName), $classes, $classes[0]);
202190
}
203191

192+
private function getFqcnTypeClasses(string $shortClassName): array
193+
{
194+
$classes = [];
195+
sort($this->namespaces);
196+
foreach ($this->namespaces as $namespace) {
197+
if (class_exists($fqcn = $namespace.'\\'.$shortClassName)) {
198+
$classes[] = $fqcn;
199+
} elseif (class_exists($fqcn = $namespace.'\\'.ucfirst($shortClassName))) {
200+
$classes[] = $fqcn;
201+
} elseif (class_exists($fqcn = $namespace.'\\'.ucfirst($shortClassName).'Type')) {
202+
$classes[] = $fqcn;
203+
} elseif (str_ends_with($shortClassName, 'type') && class_exists($fqcn = $namespace.'\\'.ucfirst(substr($shortClassName, 0, -4).'Type'))) {
204+
$classes[] = $fqcn;
205+
}
206+
}
207+
208+
return $classes;
209+
}
210+
204211
private function getCoreTypes(): array
205212
{
206213
$coreExtension = new CoreExtension();
@@ -249,12 +256,38 @@ private function findAlternatives(string $name, array $collection): array
249256
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
250257
{
251258
if ($input->mustSuggestArgumentValuesFor('class')) {
252-
$suggestions->suggestValues(array_keys($this->types));
259+
$suggestions->suggestValues(array_merge($this->getCoreTypes(), $this->types));
260+
261+
return;
253262
}
254263

255-
if ($input->mustSuggestOptionValuesFor('option') && null !== $class = $input->getArgument('class')) {
256-
$resolvedType = $this->formRegistry->getType($class);
257-
$suggestions->suggestValues($resolvedType->getOptionsResolver()->getDefinedOptions());
264+
if ($input->mustSuggestArgumentValuesFor('option') && null !== $class = $input->getArgument('class')) {
265+
$this->completeOptions($class, $suggestions);
266+
267+
return;
258268
}
269+
270+
if ($input->mustSuggestOptionValuesFor('format')) {
271+
$helper = new DescriptorHelper();
272+
$suggestions->suggestValues($helper->getFormats());
273+
}
274+
}
275+
276+
private function completeOptions(string $class, CompletionSuggestions $suggestions): void
277+
{
278+
if (!class_exists($class) || !is_subclass_of($class, FormTypeInterface::class)) {
279+
$classes = $this->getFqcnTypeClasses($class);
280+
281+
if (1 === count($classes)) {
282+
$class = $classes[0];
283+
}
284+
}
285+
286+
if (!$this->formRegistry->hasType($class)) {
287+
return;
288+
}
289+
290+
$resolvedType = $this->formRegistry->getType($class);
291+
$suggestions->suggestValues($resolvedType->getOptionsResolver()->getDefinedOptions());
259292
}
260293
}

‎src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php
+90Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,15 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Console\Application;
1616
use Symfony\Component\Console\Exception\InvalidArgumentException;
17+
use Symfony\Component\Console\Tester\CommandCompletionTester;
1718
use Symfony\Component\Console\Tester\CommandTester;
1819
use Symfony\Component\Form\AbstractType;
1920
use Symfony\Component\Form\Command\DebugCommand;
21+
use Symfony\Component\Form\Extension\Core\CoreExtension;
22+
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
2023
use Symfony\Component\Form\Extension\Core\Type\TextType;
2124
use Symfony\Component\Form\FormRegistry;
25+
use Symfony\Component\Form\FormTypeInterface;
2226
use Symfony\Component\Form\ResolvedFormTypeFactory;
2327
use Symfony\Component\OptionsResolver\Options;
2428
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -186,6 +190,92 @@ class:%s
186190
, $tester->getDisplay(true));
187191
}
188192

193+
/**
194+
* @dataProvider provideCompletionSuggestions
195+
*/
196+
public function testComplete(array $input, array $expectedSuggestions)
197+
{
198+
$formRegistry = new FormRegistry([], new ResolvedFormTypeFactory());
199+
$command = new DebugCommand($formRegistry);
200+
$application = new Application();
201+
$application->add($command);
202+
$tester = new CommandCompletionTester($application->get('debug:form'));
203+
$this->assertSame($expectedSuggestions, $tester->complete($input));
204+
}
205+
206+
public function provideCompletionSuggestions(): iterable
207+
{
208+
yield 'option --format' => [
209+
['--format', ''],
210+
['txt', 'json'],
211+
];
212+
213+
yield 'form_type' => [
214+
[''],
215+
$this->getCoreTypes(),
216+
];
217+
218+
yield 'option for short name' => [
219+
['Symfony\\Component\\Form\\Extension\\Core\Type\\ButtonType', ''],
220+
[
221+
'block_name',
222+
'block_prefix',
223+
'disabled',
224+
'label',
225+
'label_format',
226+
'row_attr',
227+
'label_html',
228+
'label_translation_parameters',
229+
'attr_translation_parameters',
230+
'attr',
231+
'translation_domain',
232+
'auto_initialize',
233+
'priority',
234+
],
235+
];
236+
237+
yield 'option for FQCN' => [
238+
['ButtonType', ''],
239+
[
240+
'block_name',
241+
'block_prefix',
242+
'disabled',
243+
'label',
244+
'label_format',
245+
'row_attr',
246+
'label_html',
247+
'label_translation_parameters',
248+
'attr_translation_parameters',
249+
'attr',
250+
'translation_domain',
251+
'auto_initialize',
252+
'priority',
253+
],
254+
];
255+
256+
yield 'option for ambiguous form type' => [
257+
['Type', ''],
258+
[],
259+
];
260+
261+
yield 'option for invalid form type' => [
262+
['NotExistingFormType', ''],
263+
[],
264+
];
265+
}
266+
267+
private function getCoreTypes(): array
268+
{
269+
$coreExtension = new CoreExtension();
270+
$loadTypesRefMethod = (new \ReflectionObject($coreExtension))->getMethod('loadTypes');
271+
$loadTypesRefMethod->setAccessible(true);
272+
$coreTypes = $loadTypesRefMethod->invoke($coreExtension);
273+
$coreTypes = array_map(function (FormTypeInterface $type) { return \get_class($type); }, $coreTypes);
274+
sort($coreTypes);
275+
276+
return $coreTypes;
277+
}
278+
189279
private function createCommandTester(array $namespaces = ['Symfony\Component\Form\Extension\Core\Type'], array $types = [])
190280
{
191281
$formRegistry = new FormRegistry([], new ResolvedFormTypeFactory());

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.