Skip to content

Commit b76529c

Browse files
committed
Allow setting one info message per option
1 parent 4e659ca commit b76529c

12 files changed

+137
-4
lines changed

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,15 @@ protected function collectOptions(ResolvedFormTypeInterface $type)
108108

109109
protected function getOptionDefinition(OptionsResolver $optionsResolver, string $option)
110110
{
111-
$definition = [
111+
$definition = [];
112+
113+
if ($info = $optionsResolver->getInfo($option)) {
114+
$definition = [
115+
'info' => $info,
116+
];
117+
}
118+
119+
$definition += [
112120
'required' => $optionsResolver->isRequired($option),
113121
'deprecated' => $optionsResolver->isDeprecated($option),
114122
];

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

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio
7373
}
7474
}
7575
$map += [
76+
'info' => 'info',
7677
'required' => 'required',
7778
'default' => 'default',
7879
'allowed_types' => 'allowedTypes',

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

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio
114114
];
115115
}
116116
$map += [
117+
'Info' => 'info',
117118
'Required' => 'required',
118119
'Default' => 'default',
119120
'Allowed types' => 'allowedTypes',

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

+3
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ public function testDebugCustomFormTypeOption()
151151
Symfony\Component\Form\Tests\Command\FooType (foo)
152152
==================================================
153153
154+
---------------- -----------%s
155+
Info "Info" %s
154156
---------------- -----------%s
155157
Required true %s
156158
---------------- -----------%s
@@ -209,5 +211,6 @@ public function configureOptions(OptionsResolver $resolver)
209211
$resolver->setNormalizer('foo', function (Options $options, $value) {
210212
return (string) $value;
211213
});
214+
$resolver->setInfo('foo', 'Info');
212215
}
213216
}

src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Symfony\Component\Form\Extension\Core\Type\ChoiceType (choice_translation_domain)
33
=================================================================================
44

5+
---------------- -----------%s
6+
Info - %s
57
---------------- -----------%s
68
Required false %s
79
---------------- -----------%s

src/Symfony/Component/Form/Tests/Fixtures/Descriptor/deprecated_option.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (bar)
55
Deprecated true
66
--------------------- -----------------------------------
77
Deprecation message "The option "bar" is deprecated."
8+
--------------------- -----------------------------------
9+
Info -
810
--------------------- -----------------------------------
911
Required false
1012
--------------------- -----------------------------------
@@ -15,4 +17,4 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (bar)
1517
Allowed values -
1618
--------------------- -----------------------------------
1719
Normalizers -
18-
--------------------- -----------------------------------
20+
--------------------- -----------------------------------

src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Symfony\Component\Form\Tests\Console\Descriptor\FooType (empty_data)
22
====================================================================
33

44
---------------- ----------------------%s
5+
Info - %s
6+
---------------- ----------------------%s
57
Required false %s
68
---------------- ----------------------%s
79
Default Value: null %s

src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Symfony\Component\Form\Tests\Console\Descriptor\FooType (foo)
33
=============================================================
44

5+
---------------- -----------%s
6+
Info - %s
57
---------------- -----------%s
68
Required true %s
79
---------------- -----------%s

src/Symfony/Component/Form/composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"php": "^7.2.5",
2020
"symfony/event-dispatcher": "^4.4|^5.0",
2121
"symfony/intl": "^4.4|^5.0",
22-
"symfony/options-resolver": "^5.0",
22+
"symfony/options-resolver": "^5.1",
2323
"symfony/polyfill-ctype": "~1.8",
2424
"symfony/polyfill-mbstring": "~1.0",
2525
"symfony/property-access": "^5.0",

src/Symfony/Component/OptionsResolver/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
-----
66

77
* added fluent configuration of options using `OptionResolver::define()`
8+
* added `setInfo()` and `getInfo()` methods
89

910
5.0.0
1011
-----

src/Symfony/Component/OptionsResolver/OptionsResolver.php

+53-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ class OptionsResolver implements Options
7171
*/
7272
private $allowedTypes = [];
7373

74+
/**
75+
* A list of info messages for each option.
76+
*/
77+
private $info = [];
78+
7479
/**
7580
* A list of closures for evaluating lazy options.
7681
*/
@@ -715,6 +720,48 @@ public function define(string $option): OptionConfigurator
715720
return new OptionConfigurator($option, $this);
716721
}
717722

723+
/**
724+
* Sets an info message for an option.
725+
*
726+
* @param string $option The option name
727+
* @param string $info The info message
728+
*
729+
* @return $this
730+
*
731+
* @throws UndefinedOptionsException If the option is undefined
732+
* @throws AccessException If called from a lazy option or normalizer
733+
*/
734+
public function setInfo(string $option, string $info)
735+
{
736+
if ($this->locked) {
737+
throw new AccessException('The Info message cannot be set from a lazy option or normalizer.');
738+
}
739+
740+
if (!isset($this->defined[$option])) {
741+
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
742+
}
743+
744+
$this->info[$option] = $info;
745+
746+
return $this;
747+
}
748+
749+
/**
750+
* Gets the info message for an option.
751+
*
752+
* @param string $option The option name
753+
*
754+
* @return string|null The info message of the given option
755+
*/
756+
public function getInfo(string $option): ?string
757+
{
758+
if (!isset($this->defined[$option])) {
759+
throw new UndefinedOptionsException(sprintf('The option "%s" does not exist. Defined options are: "%s".', $this->formatOptions([$option]), implode('", "', array_keys($this->defined))));
760+
}
761+
762+
return $this->info[$option] ?? null;
763+
}
764+
718765
/**
719766
* Removes the option with the given name.
720767
*
@@ -734,7 +781,7 @@ public function remove($optionNames)
734781

735782
foreach ((array) $optionNames as $option) {
736783
unset($this->defined[$option], $this->defaults[$option], $this->required[$option], $this->resolved[$option]);
737-
unset($this->lazy[$option], $this->normalizers[$option], $this->allowedTypes[$option], $this->allowedValues[$option]);
784+
unset($this->lazy[$option], $this->normalizers[$option], $this->allowedTypes[$option], $this->allowedValues[$option], $this->info[$option]);
738785
}
739786

740787
return $this;
@@ -763,6 +810,7 @@ public function clear()
763810
$this->allowedTypes = [];
764811
$this->allowedValues = [];
765812
$this->deprecated = [];
813+
$this->info = [];
766814

767815
return $this;
768816
}
@@ -996,6 +1044,10 @@ public function offsetGet($option, bool $triggerDeprecation = true)
9961044
);
9971045
}
9981046

1047+
if (isset($this->info[$option])) {
1048+
$message .= sprintf(' Info: %s.', $this->info[$option]);
1049+
}
1050+
9991051
throw new InvalidOptionsException($message);
10001052
}
10011053
}

src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php

+59
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
use PHPUnit\Framework\Assert;
1515
use PHPUnit\Framework\TestCase;
1616
use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector;
17+
use Symfony\Component\OptionsResolver\Exception\AccessException;
1718
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
19+
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
1820
use Symfony\Component\OptionsResolver\Options;
1921
use Symfony\Component\OptionsResolver\OptionsResolver;
2022

@@ -2410,4 +2412,61 @@ public function testResolveOptionsDefinedByOptionConfigurator()
24102412
$this->assertSame(['bar', 'zab'], $introspector->getAllowedValues('foo'));
24112413
$this->assertCount(1, $introspector->getNormalizers('foo'));
24122414
}
2415+
2416+
public function testGetInfo()
2417+
{
2418+
$info = 'The option info message';
2419+
$this->resolver->setDefined('foo');
2420+
$this->resolver->setInfo('foo', $info);
2421+
2422+
$this->assertSame($info, $this->resolver->getInfo('foo'));
2423+
}
2424+
2425+
public function testSetInfoOnNormalization()
2426+
{
2427+
$this->expectException(AccessException::class);
2428+
$this->expectExceptionMessage('The Info message cannot be set from a lazy option or normalizer.');
2429+
2430+
$this->resolver->setDefined('foo');
2431+
$this->resolver->setNormalizer('foo', static function (Options $options, $value) {
2432+
$options->setInfo('foo', 'Info');
2433+
});
2434+
2435+
$this->resolver->resolve(['foo' => 'bar']);
2436+
}
2437+
2438+
public function testSetInfoOnUndefinedOption()
2439+
{
2440+
$this->expectException(UndefinedOptionsException::class);
2441+
$this->expectExceptionMessage('The option "bar" does not exist. Defined options are: "foo".');
2442+
2443+
$this->resolver->setDefined('foo');
2444+
$this->resolver->setInfo('bar', 'The option info message');
2445+
}
2446+
2447+
public function testGetInfoOnUndefinedOption2()
2448+
{
2449+
$this->expectException(UndefinedOptionsException::class);
2450+
$this->expectExceptionMessage('The option "bar" does not exist. Defined options are: "foo".');
2451+
2452+
$this->resolver->setDefined('foo');
2453+
$this->resolver->getInfo('bar');
2454+
}
2455+
2456+
public function testInfoOnInvalidValue()
2457+
{
2458+
$this->expectException(InvalidOptionsException::class);
2459+
$this->expectExceptionMessage('The option "expires" with value DateTime is invalid. Info: A future date time.');
2460+
2461+
$this->resolver
2462+
->setRequired('expires')
2463+
->setInfo('expires', 'A future date time')
2464+
->setAllowedTypes('expires', \DateTime::class)
2465+
->setAllowedValues('expires', static function ($value) {
2466+
return $value >= new \DateTime('now');
2467+
})
2468+
;
2469+
2470+
$this->resolver->resolve(['expires' => new \DateTime('-1 hour')]);
2471+
}
24132472
}

0 commit comments

Comments
 (0)