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 b749204

Browse filesBrowse files
committed
feature #24185 [Form] Display general forms information on debug:form (yceruto)
This PR was merged into the 3.4 branch. Discussion ---------- [Form] Display general forms information on debug:form | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - ![debug-form-defaults](https://user-images.githubusercontent.com/2028198/30436620-998103ca-993a-11e7-9873-31f042327374.png) When we run `bin/console debug:form` (without argument) all possible Form Component information is displayed. Commits ------- 12d1a7f Display form defaults on debug:form
2 parents c7e84cc + 12d1a7f commit b749204
Copy full SHA for b749204

File tree

11 files changed

+213
-14
lines changed
Filter options

11 files changed

+213
-14
lines changed

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@
100100
<service id="Symfony\Component\Form\Command\DebugCommand">
101101
<argument type="service" id="form.registry" />
102102
<argument type="collection" /> <!-- All form types namespaces are stored here by FormPass -->
103+
<argument type="collection" /> <!-- All services form types are stored here by FormPass -->
104+
<argument type="collection" /> <!-- All type extensions are stored here by FormPass -->
105+
<argument type="collection" /> <!-- All type guessers are stored here by FormPass -->
103106
<tag name="console.command" command="debug:form" />
104107
</service>
105108
</services>

‎src/Symfony/Component/Form/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/CHANGELOG.md
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
3.4.0
5+
-----
6+
7+
* added `DebugCommand`
8+
49
3.3.0
510
-----
611

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Command/DebugCommand.php
+30-10Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Form\Command;
1313

1414
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Exception\InvalidArgumentException;
1516
use Symfony\Component\Console\Input\InputArgument;
1617
use Symfony\Component\Console\Input\InputInterface;
1718
use Symfony\Component\Console\Input\InputOption;
@@ -31,13 +32,19 @@ class DebugCommand extends Command
3132

3233
private $formRegistry;
3334
private $namespaces;
35+
private $types;
36+
private $extensions;
37+
private $guessers;
3438

35-
public function __construct(FormRegistryInterface $formRegistry, array $namespaces = array('Symfony\Component\Form\Extension\Core\Type'))
39+
public function __construct(FormRegistryInterface $formRegistry, array $namespaces = array('Symfony\Component\Form\Extension\Core\Type'), array $types = array(), array $extensions = array(), array $guessers = array())
3640
{
3741
parent::__construct();
3842

3943
$this->formRegistry = $formRegistry;
4044
$this->namespaces = $namespaces;
45+
$this->types = $types;
46+
$this->extensions = $extensions;
47+
$this->guessers = $guessers;
4148
}
4249

4350
/**
@@ -47,18 +54,25 @@ protected function configure()
4754
{
4855
$this
4956
->setDefinition(array(
50-
new InputArgument('class', InputArgument::REQUIRED, 'The form type class'),
57+
new InputArgument('class', InputArgument::OPTIONAL, 'The form type class'),
5158
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt or json)', 'txt'),
5259
))
5360
->setDescription('Displays form type information')
5461
->setHelp(<<<'EOF'
55-
The <info>%command.name%</info> command displays information about a form type.
62+
The <info>%command.name%</info> command displays information about form types.
5663
57-
Either the fully-qualified class name or the short class name can be used:
64+
<info>php %command.full_name%</info>
65+
66+
The command lists all built-in types, services types, type extensions and guessers currently available.
5867
5968
<info>php %command.full_name% Symfony\Component\Form\Extension\Core\Type\ChoiceType</info>
6069
<info>php %command.full_name% ChoiceType</info>
6170
71+
The command lists all defined options that contains the given form type, as well as their parents and type extensions.
72+
73+
<info>php %command.full_name% --format=json</info>
74+
75+
The command lists everything in a machine readable json format.
6276
EOF
6377
)
6478
;
@@ -71,12 +85,18 @@ protected function execute(InputInterface $input, OutputInterface $output)
7185
{
7286
$io = new SymfonyStyle($input, $output);
7387

74-
if (!class_exists($class = $input->getArgument('class'))) {
75-
$class = $this->getFqcnTypeClass($input, $io, $class);
88+
if (null === $class = $input->getArgument('class')) {
89+
$object = null;
90+
$options['types'] = $this->types;
91+
$options['extensions'] = $this->extensions;
92+
$options['guessers'] = $this->guessers;
93+
} else {
94+
if (!class_exists($class)) {
95+
$class = $this->getFqcnTypeClass($input, $io, $class);
96+
}
97+
$object = $this->formRegistry->getType($class);
7698
}
7799

78-
$object = $this->formRegistry->getType($class);
79-
80100
$helper = new DescriptorHelper();
81101
$options['format'] = $input->getOption('format');
82102
$helper->describe($io, $object, $options);
@@ -92,13 +112,13 @@ private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, $shor
92112
}
93113

94114
if (0 === $count = count($classes)) {
95-
throw new \InvalidArgumentException(sprintf("Could not find type \"%s\" into the following namespaces:\n %s", $shortClassName, implode("\n ", $this->namespaces)));
115+
throw new InvalidArgumentException(sprintf("Could not find type \"%s\" into the following namespaces:\n %s", $shortClassName, implode("\n ", $this->namespaces)));
96116
}
97117
if (1 === $count) {
98118
return $classes[0];
99119
}
100120
if (!$input->isInteractive()) {
101-
throw new \InvalidArgumentException(sprintf("The type \"%s\" is ambiguous.\nDid you mean one of these?\n %s", $shortClassName, implode("\n ", $classes)));
121+
throw new InvalidArgumentException(sprintf("The type \"%s\" is ambiguous.\nDid you mean one of these?\n %s", $shortClassName, implode("\n ", $classes)));
102122
}
103123

104124
return $io->choice(sprintf("The type \"%s\" is ambiguous.\n\n Select one of the following form types to display its information:", $shortClassName), $classes, $classes[0]);

‎src/Symfony/Component/Form/Console/Descriptor/Descriptor.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Console/Descriptor/Descriptor.php
+25-4Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
namespace Symfony\Component\Form\Console\Descriptor;
1313

1414
use Symfony\Component\Console\Descriptor\DescriptorInterface;
15+
use Symfony\Component\Console\Input\ArrayInput;
1516
use Symfony\Component\Console\Output\OutputInterface;
17+
use Symfony\Component\Console\Style\StyleInterface;
1618
use Symfony\Component\Console\Style\SymfonyStyle;
19+
use Symfony\Component\Form\Extension\Core\CoreExtension;
20+
use Symfony\Component\Form\FormTypeInterface;
1721
use Symfony\Component\Form\ResolvedFormTypeInterface;
1822
use Symfony\Component\Form\Util\OptionsResolverWrapper;
1923
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -25,9 +29,7 @@
2529
*/
2630
abstract class Descriptor implements DescriptorInterface
2731
{
28-
/**
29-
* @var SymfonyStyle
30-
*/
32+
/** @var StyleInterface */
3133
protected $output;
3234
protected $type;
3335
protected $ownOptions = array();
@@ -43,9 +45,12 @@ abstract class Descriptor implements DescriptorInterface
4345
*/
4446
public function describe(OutputInterface $output, $object, array $options = array())
4547
{
46-
$this->output = $output;
48+
$this->output = $output instanceof StyleInterface ? $output : new SymfonyStyle(new ArrayInput(array()), $output);
4749

4850
switch (true) {
51+
case null === $object:
52+
$this->describeDefaults($options);
53+
break;
4954
case $object instanceof ResolvedFormTypeInterface:
5055
$this->describeResolvedFormType($object, $options);
5156
break;
@@ -54,8 +59,24 @@ public function describe(OutputInterface $output, $object, array $options = arra
5459
}
5560
}
5661

62+
abstract protected function describeDefaults(array $options = array());
63+
5764
abstract protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array());
5865

66+
protected function getCoreTypes()
67+
{
68+
$coreExtension = new CoreExtension();
69+
$coreExtensionRefObject = new \ReflectionObject($coreExtension);
70+
$loadTypesRefMethod = $coreExtensionRefObject->getMethod('loadTypes');
71+
$loadTypesRefMethod->setAccessible(true);
72+
$coreTypes = $loadTypesRefMethod->invoke($coreExtension);
73+
74+
$coreTypes = array_map(function (FormTypeInterface $type) { return get_class($type); }, $coreTypes);
75+
sort($coreTypes);
76+
77+
return $coreTypes;
78+
}
79+
5980
protected function collectOptions(ResolvedFormTypeInterface $type)
6081
{
6182
$this->parents = array();

‎src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@
2020
*/
2121
class JsonDescriptor extends Descriptor
2222
{
23+
protected function describeDefaults(array $options = array())
24+
{
25+
$data['builtin_form_types'] = $this->getCoreTypes();
26+
$data['service_form_types'] = array_values(array_diff($options['types'], $data['builtin_form_types']));
27+
$data['type_extensions'] = $options['extensions'];
28+
$data['type_guessers'] = $options['guessers'];
29+
30+
$this->writeData($data, $options);
31+
}
32+
2333
protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array())
2434
{
2535
$this->collectOptions($resolvedFormType);

‎src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,26 @@
2121
*/
2222
class TextDescriptor extends Descriptor
2323
{
24+
protected function describeDefaults(array $options = array())
25+
{
26+
$coreTypes = $this->getCoreTypes();
27+
28+
$this->output->section('Built-in form types (Symfony\Component\Form\Extension\Core\Type)');
29+
$shortClassNames = array_map(function ($fqcn) { return array_slice(explode('\\', $fqcn), -1)[0]; }, $coreTypes);
30+
for ($i = 0; $i * 5 < count($shortClassNames); ++$i) {
31+
$this->output->writeln(' '.implode(', ', array_slice($shortClassNames, $i * 5, 5)));
32+
}
33+
34+
$this->output->section('Service form types');
35+
$this->output->listing(array_diff($options['types'], $coreTypes));
36+
37+
$this->output->section('Type extensions');
38+
$this->output->listing($options['extensions']);
39+
40+
$this->output->section('Type guessers');
41+
$this->output->listing($options['guessers']);
42+
}
43+
2444
protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array())
2545
{
2646
$this->collectOptions($resolvedFormType);

‎src/Symfony/Component/Form/DependencyInjection/FormPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/DependencyInjection/FormPass.php
+17Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ private function processFormTypes(ContainerBuilder $container)
7777
if ($container->hasDefinition($this->formDebugCommandService)) {
7878
$commandDefinition = $container->getDefinition($this->formDebugCommandService);
7979
$commandDefinition->setArgument(1, array_keys($namespaces));
80+
$commandDefinition->setArgument(2, array_keys($servicesMap));
8081
}
8182

8283
return ServiceLocatorTagPass::register($container, $servicesMap);
@@ -85,6 +86,7 @@ private function processFormTypes(ContainerBuilder $container)
8586
private function processFormTypeExtensions(ContainerBuilder $container)
8687
{
8788
$typeExtensions = array();
89+
$typeExtensionsClasses = array();
8890
foreach ($this->findAndSortTaggedServices($this->formTypeExtensionTag, $container) as $reference) {
8991
$serviceId = (string) $reference;
9092
$serviceDefinition = $container->getDefinition($serviceId);
@@ -97,20 +99,35 @@ private function processFormTypeExtensions(ContainerBuilder $container)
9799
}
98100

99101
$typeExtensions[$extendedType][] = new Reference($serviceId);
102+
$typeExtensionsClasses[] = $serviceDefinition->getClass();
100103
}
101104

102105
foreach ($typeExtensions as $extendedType => $extensions) {
103106
$typeExtensions[$extendedType] = new IteratorArgument($extensions);
104107
}
105108

109+
if ($container->hasDefinition($this->formDebugCommandService)) {
110+
$commandDefinition = $container->getDefinition($this->formDebugCommandService);
111+
$commandDefinition->setArgument(3, $typeExtensionsClasses);
112+
}
113+
106114
return $typeExtensions;
107115
}
108116

109117
private function processFormTypeGuessers(ContainerBuilder $container)
110118
{
111119
$guessers = array();
120+
$guessersClasses = array();
112121
foreach ($container->findTaggedServiceIds($this->formTypeGuesserTag, true) as $serviceId => $tags) {
113122
$guessers[] = new Reference($serviceId);
123+
124+
$serviceDefinition = $container->getDefinition($serviceId);
125+
$guessersClasses[] = $serviceDefinition->getClass();
126+
}
127+
128+
if ($container->hasDefinition($this->formDebugCommandService)) {
129+
$commandDefinition = $container->getDefinition($this->formDebugCommandService);
130+
$commandDefinition->setArgument(4, $guessersClasses);
114131
}
115132

116133
return new IteratorArgument($guessers);

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@
2121

2222
class DebugCommandTest extends TestCase
2323
{
24+
public function testDebugDefaults()
25+
{
26+
$tester = $this->createCommandTester();
27+
$ret = $tester->execute(array(), array('decorated' => false));
28+
29+
$this->assertEquals(0, $ret, 'Returns 0 in case of success');
30+
$this->assertContains('Built-in form types', $tester->getDisplay());
31+
}
32+
2433
public function testDebugSingleFormType()
2534
{
2635
$tester = $this->createCommandTester();

‎src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,19 @@
2424

2525
abstract class AbstractDescriptorTest extends TestCase
2626
{
27+
/** @dataProvider getDescribeDefaultsTestData */
28+
public function testDescribeDefaults($object, array $options, $fixtureName)
29+
{
30+
$expectedDescription = $this->getExpectedDescription($fixtureName);
31+
$describedObject = $this->getObjectDescription($object, $options);
32+
33+
if ('json' === $this->getFormat()) {
34+
$this->assertEquals(json_encode(json_decode($expectedDescription), JSON_PRETTY_PRINT), json_encode(json_decode($describedObject), JSON_PRETTY_PRINT));
35+
} else {
36+
$this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $describedObject)));
37+
}
38+
}
39+
2740
/** @dataProvider getDescribeResolvedFormTypeTestData */
2841
public function testDescribeResolvedFormType(ResolvedFormTypeInterface $type, array $options, $fixtureName)
2942
{
@@ -37,6 +50,15 @@ public function testDescribeResolvedFormType(ResolvedFormTypeInterface $type, ar
3750
}
3851
}
3952

53+
public function getDescribeDefaultsTestData()
54+
{
55+
$options['types'] = array('Symfony\Bridge\Doctrine\Form\Type\EntityType');
56+
$options['extensions'] = array('Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension');
57+
$options['guessers'] = array('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser');
58+
59+
yield array(null, $options, 'defaults_1');
60+
}
61+
4062
public function getDescribeResolvedFormTypeTestData()
4163
{
4264
$typeExtensions = array(
+45Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"builtin_form_types": [
3+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\BirthdayType",
4+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\ButtonType",
5+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType",
6+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\ChoiceType",
7+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\CollectionType",
8+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\CountryType",
9+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\CurrencyType",
10+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\DateIntervalType",
11+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\DateTimeType",
12+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\DateType",
13+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\EmailType",
14+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\FileType",
15+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType",
16+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\HiddenType",
17+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\IntegerType",
18+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\LanguageType",
19+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\LocaleType",
20+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\MoneyType",
21+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\NumberType",
22+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\PasswordType",
23+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\PercentType",
24+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\RadioType",
25+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\RangeType",
26+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\RepeatedType",
27+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\ResetType",
28+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\SearchType",
29+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\SubmitType",
30+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\TextType",
31+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\TextareaType",
32+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\TimeType",
33+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\TimezoneType",
34+
"Symfony\\Component\\Form\\Extension\\Core\\Type\\UrlType"
35+
],
36+
"service_form_types": [
37+
"Symfony\\Bridge\\Doctrine\\Form\\Type\\EntityType"
38+
],
39+
"type_extensions": [
40+
"Symfony\\Component\\Form\\Extension\\Csrf\\Type\\FormTypeCsrfExtension"
41+
],
42+
"type_guessers": [
43+
"Symfony\\Component\\Form\\Extension\\Validator\\ValidatorTypeGuesser"
44+
]
45+
}

0 commit comments

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