Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Form][OptionsResolver] Show deprecated options definition on debug:form command #27667

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions src/Symfony/Component/Form/Command/DebugCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ protected function configure()
->setDefinition(array(
new InputArgument('class', InputArgument::OPTIONAL, 'The form type class'),
new InputArgument('option', InputArgument::OPTIONAL, 'The form type option'),
new InputOption('show-deprecated', null, InputOption::VALUE_NONE, 'Display deprecated options in form types'),
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt or json)', 'txt'),
))
->setDescription('Displays form type information')
Expand All @@ -66,15 +67,23 @@ protected function configure()

<info>php %command.full_name%</info>

The command lists all built-in types, services types, type extensions and guessers currently available.
The command lists all built-in types, services types, type extensions and
guessers currently available.

<info>php %command.full_name% Symfony\Component\Form\Extension\Core\Type\ChoiceType</info>
<info>php %command.full_name% ChoiceType</info>

The command lists all defined options that contains the given form type, as well as their parents and type extensions.
The command lists all defined options that contains the given form type,
as well as their parents and type extensions.

<info>php %command.full_name% ChoiceType choice_value</info>

Use the <info>--show-deprecated</info> option to display form types with
deprecated options or the deprecated options of the given form type:

<info>php %command.full_name% --show-deprecated</info>
<info>php %command.full_name% ChoiceType --show-deprecated</info>

The command displays the definition of the given option name.

<info>php %command.full_name% --format=json</info>
Expand All @@ -96,6 +105,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
$object = null;
$options['core_types'] = $this->getCoreTypes();
$options['service_types'] = array_values(array_diff($this->types, $options['core_types']));
if ($input->getOption('show-deprecated')) {
$options['core_types'] = $this->filterTypesByDeprecated($options['core_types']);
$options['service_types'] = $this->filterTypesByDeprecated($options['service_types']);
}
$options['extensions'] = $this->extensions;
$options['guessers'] = $this->guessers;
foreach ($options as $k => $list) {
Expand All @@ -114,7 +127,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$message = sprintf('Option "%s" is not defined in "%s".', $option, \get_class($resolvedType->getInnerType()));

if ($alternatives = $this->findAlternatives($option, $object->getDefinedOptions())) {
if (1 == \count($alternatives)) {
if (1 === \count($alternatives)) {
$message .= "\n\nDid you mean this?\n ";
} else {
$message .= "\n\nDid you mean one of these?\n ";
Expand All @@ -134,6 +147,7 @@ protected function execute(InputInterface $input, OutputInterface $output)

$helper = new DescriptorHelper();
$options['format'] = $input->getOption('format');
$options['show_deprecated'] = $input->getOption('show-deprecated');
$helper->describe($io, $object, $options);
}

Expand All @@ -152,7 +166,7 @@ private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, $shor

$allTypes = array_merge($this->getCoreTypes(), $this->types);
if ($alternatives = $this->findAlternatives($shortClassName, $allTypes)) {
if (1 == \count($alternatives)) {
if (1 === \count($alternatives)) {
$message .= "\n\nDid you mean this?\n ";
} else {
$message .= "\n\nDid you mean one of these?\n ";
Expand Down Expand Up @@ -184,6 +198,22 @@ private function getCoreTypes()
return $coreTypes;
}

private function filterTypesByDeprecated(array $types): array
{
$typesWithDeprecatedOptions = array();
foreach ($types as $class) {
$optionsResolver = $this->formRegistry->getType($class)->getOptionsResolver();
foreach ($optionsResolver->getDefinedOptions() as $option) {
if ($optionsResolver->isDeprecated($option)) {
$typesWithDeprecatedOptions[] = $class;
break;
}
}
}

return $typesWithDeprecatedOptions;
}

private function findAlternatives($name, array $collection)
{
$alternatives = array();
Expand Down
38 changes: 37 additions & 1 deletion src/Symfony/Component/Form/Console/Descriptor/Descriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ protected function collectOptions(ResolvedFormTypeInterface $type)

protected function getOptionDefinition(OptionsResolver $optionsResolver, $option)
{
$definition = array('required' => $optionsResolver->isRequired($option));
$definition = array(
'required' => $optionsResolver->isRequired($option),
'deprecated' => $optionsResolver->isDeprecated($option),
);

$introspector = new OptionsResolverIntrospector($optionsResolver);

Expand All @@ -118,6 +121,7 @@ protected function getOptionDefinition(OptionsResolver $optionsResolver, $option
'allowedTypes' => 'getAllowedTypes',
'allowedValues' => 'getAllowedValues',
'normalizer' => 'getNormalizer',
'deprecationMessage' => 'getDeprecationMessage',
);

foreach ($map as $key => $method) {
Expand All @@ -128,9 +132,41 @@ protected function getOptionDefinition(OptionsResolver $optionsResolver, $option
}
}

if (isset($definition['deprecationMessage']) && \is_string($definition['deprecationMessage'])) {
$definition['deprecationMessage'] = strtr($definition['deprecationMessage'], array('%name%' => $option));
}

return $definition;
}

protected function filterOptionsByDeprecated(ResolvedFormTypeInterface $type)
{
$deprecatedOptions = array();
$resolver = $type->getOptionsResolver();
foreach ($resolver->getDefinedOptions() as $option) {
if ($resolver->isDeprecated($option)) {
$deprecatedOptions[] = $option;
}
}

$filterByDeprecated = function (array $options) use ($deprecatedOptions) {
foreach ($options as $class => $opts) {
if ($deprecated = array_intersect($deprecatedOptions, $opts)) {
$options[$class] = $deprecated;
} else {
unset($options[$class]);
}
}

return $options;
};

$this->ownOptions = array_intersect($deprecatedOptions, $this->ownOptions);
$this->overriddenOptions = $filterByDeprecated($this->overriddenOptions);
$this->parentOptions = $filterByDeprecated($this->parentOptions);
$this->extensionOptions = $filterByDeprecated($this->extensionOptions);
}

private function getParentOptionsResolver(ResolvedFormTypeInterface $type)
{
$this->parents[$class = \get_class($type->getInnerType())] = array();
Expand Down
21 changes: 17 additions & 4 deletions src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ protected function describeDefaults(array $options)
{
$data['builtin_form_types'] = $options['core_types'];
$data['service_form_types'] = $options['service_types'];
$data['type_extensions'] = $options['extensions'];
$data['type_guessers'] = $options['guessers'];
if (!$options['show_deprecated']) {
$data['type_extensions'] = $options['extensions'];
$data['type_guessers'] = $options['guessers'];
}

$this->writeData($data, $options);
}
Expand All @@ -35,6 +37,10 @@ protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedF
{
$this->collectOptions($resolvedFormType);

if ($options['show_deprecated']) {
$this->filterOptionsByDeprecated($resolvedFormType);
}

$formOptions = array(
'own' => $this->ownOptions,
'overridden' => $this->overriddenOptions,
Expand All @@ -59,7 +65,14 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio
{
$definition = $this->getOptionDefinition($optionsResolver, $options['option']);

$map = array(
$map = array();
if ($definition['deprecated']) {
$map['deprecated'] = 'deprecated';
if (\is_string($definition['deprecationMessage'])) {
$map['deprecation_message'] = 'deprecationMessage';
}
}
$map += array(
'required' => 'required',
'default' => 'default',
'allowed_types' => 'allowedTypes',
Expand All @@ -81,7 +94,7 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio

private function writeData(array $data, array $options)
{
$flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0;
$flags = $options['json_encoding'] ?? 0;
$this->output->write(json_encode($data, $flags | JSON_PRETTY_PRINT)."\n");
}

Expand Down
85 changes: 54 additions & 31 deletions src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,40 @@ class TextDescriptor extends Descriptor
{
protected function describeDefaults(array $options)
{
$this->output->section('Built-in form types (Symfony\Component\Form\Extension\Core\Type)');
$shortClassNames = array_map(function ($fqcn) { return \array_slice(explode('\\', $fqcn), -1)[0]; }, $options['core_types']);
for ($i = 0; $i * 5 < \count($shortClassNames); ++$i) {
$this->output->writeln(' '.implode(', ', \array_slice($shortClassNames, $i * 5, 5)));
if ($options['core_types']) {
$this->output->section('Built-in form types (Symfony\Component\Form\Extension\Core\Type)');
$shortClassNames = array_map(function ($fqcn) { return \array_slice(explode('\\', $fqcn), -1)[0]; }, $options['core_types']);
for ($i = 0, $loopsMax = \count($shortClassNames); $i * 5 < $loopsMax; ++$i) {
$this->output->writeln(' '.implode(', ', \array_slice($shortClassNames, $i * 5, 5)));
}
}

$this->output->section('Service form types');
$this->output->listing($options['service_types']);
if ($options['service_types']) {
$this->output->section('Service form types');
$this->output->listing($options['service_types']);
}

$this->output->section('Type extensions');
$this->output->listing($options['extensions']);
if (!$options['show_deprecated']) {
if ($options['extensions']) {
$this->output->section('Type extensions');
$this->output->listing($options['extensions']);
}

$this->output->section('Type guessers');
$this->output->listing($options['guessers']);
if ($options['guessers']) {
$this->output->section('Type guessers');
$this->output->listing($options['guessers']);
}
}
}

protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array())
{
$this->collectOptions($resolvedFormType);

if ($options['show_deprecated']) {
$this->filterOptionsByDeprecated($resolvedFormType);
}

$formOptions = $this->normalizeAndSortOptionsColumns(array_filter(array(
'own' => $this->ownOptions,
'overridden' => $this->overriddenOptions,
Expand All @@ -62,29 +76,12 @@ protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedF
'extension' => 'Extension options',
), $formOptions);

$tableRows = array();
$count = \count(max($formOptions));
for ($i = 0; $i < $count; ++$i) {
$cells = array();
foreach (array_keys($tableHeaders) as $group) {
if (isset($formOptions[$group][$i])) {
$option = $formOptions[$group][$i];

if (\is_string($option) && \in_array($option, $this->requiredOptions)) {
$option .= ' <info>(required)</info>';
}
$this->output->title(sprintf('%s (Block prefix: "%s")', \get_class($resolvedFormType->getInnerType()), $resolvedFormType->getInnerType()->getBlockPrefix()));

$cells[] = $option;
} else {
$cells[] = null;
}
}
$tableRows[] = $cells;
if ($formOptions) {
$this->output->table($tableHeaders, $this->buildTableRows($tableHeaders, $formOptions));
}

$this->output->title(sprintf('%s (Block prefix: "%s")', \get_class($resolvedFormType->getInnerType()), $resolvedFormType->getInnerType()->getBlockPrefix()));
$this->output->table($tableHeaders, $tableRows);

if ($this->parents) {
$this->output->section('Parent types');
$this->output->listing($this->parents);
Expand All @@ -101,7 +98,14 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio
$definition = $this->getOptionDefinition($optionsResolver, $options['option']);

$dump = $this->getDumpFunction();
$map = array(
$map = array();
if ($definition['deprecated']) {
$map = array(
'Deprecated' => 'deprecated',
'Deprecation message' => 'deprecationMessage',
);
}
$map += array(
'Required' => 'required',
'Default' => 'default',
'Allowed types' => 'allowedTypes',
Expand All @@ -124,6 +128,25 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio
$this->output->table(array(), $rows);
}

private function buildTableRows(array $headers, array $options): array
{
$tableRows = array();
$count = \count(max($options));
for ($i = 0; $i < $count; ++$i) {
$cells = array();
foreach (array_keys($headers) as $group) {
$option = $options[$group][$i] ?? null;
if (\is_string($option) && \in_array($option, $this->requiredOptions, true)) {
$option .= ' <info>(required)</info>';
}
$cells[] = $option;
}
$tableRows[] = $cells;
}

return $tableRows;
}

private function normalizeAndSortOptionsColumns(array $options)
{
foreach ($options as $group => $opts) {
Expand Down
24 changes: 22 additions & 2 deletions src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
use Symfony\Component\Console\Exception\InvalidArgumentException;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Component\Form\Command\DebugCommand;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormRegistry;
use Symfony\Component\Form\ResolvedFormTypeFactory;
use Symfony\Component\Form\Tests\Console\Descriptor\FooType;

class DebugCommandTest extends TestCase
{
Expand All @@ -30,6 +32,24 @@ public function testDebugDefaults()
$this->assertContains('Built-in form types', $tester->getDisplay());
}

public function testDebugDeprecatedDefaults()
{
$tester = $this->createCommandTester(array('Symfony\Component\Form\Tests\Console\Descriptor'), array(TextType::class, FooType::class));
$ret = $tester->execute(array('--show-deprecated' => true), array('decorated' => false));

$this->assertEquals(0, $ret, 'Returns 0 in case of success');
$this->assertSame(<<<TXT

Service form types
------------------

* Symfony\Component\Form\Tests\Console\Descriptor\FooType


TXT
, $tester->getDisplay(true));
}

public function testDebugSingleFormType()
{
$tester = $this->createCommandTester();
Expand Down Expand Up @@ -117,10 +137,10 @@ public function testDebugInvalidFormType()
$this->createCommandTester()->execute(array('class' => 'test'));
}

private function createCommandTester(array $namespaces = null)
private function createCommandTester(array $namespaces = array('Symfony\Component\Form\Extension\Core\Type'), array $types = array())
{
$formRegistry = new FormRegistry(array(), new ResolvedFormTypeFactory());
$command = null === $namespaces ? new DebugCommand($formRegistry) : new DebugCommand($formRegistry, $namespaces);
$command = new DebugCommand($formRegistry, $namespaces, $types);
$application = new Application();
$application->add($command);

Expand Down
Loading