8000 feature #33848 [OptionsResolver] Add new OptionConfigurator class to … · symfony/symfony@4e659ca · GitHub
[go: up one dir, main page]

Skip to content

Commit 4e659ca

Browse files
feature #33848 [OptionsResolver] Add new OptionConfigurator class to define options with fluent interface (lmillucci, yceruto)
This PR was merged into the 5.1-dev branch. Discussion ---------- [OptionsResolver] Add new OptionConfigurator class to define options with fluent interface | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #33735 | License | MIT | Doc PR | symfony/symfony-docs#12426 - [x] submit changes to the documentation This PR adds OptionConfigurator to the OptionsResolver Commits ------- 1ff5640 [OptionsResolver] Add new OptionConfigurator class to define options with fluent interface
2 parents 1c28bf7 + 1ff5640 commit 4e659ca

File tree

4 files changed

+177
-1
lines changed

4 files changed

+177
-1
lines changed

src/Symfony/Component/OptionsResolver/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
5.1.0
5+
-----
6+
7+
* added fluent configuration of options using `OptionResolver::define()`
8+
49
5.0.0
510
-----
611

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\OptionsResolver;
13+
14+
use Symfony\Component\OptionsResolver\Exception\AccessException;
15+
16+
final class OptionConfigurator
17+
{
18+
private $name;
19+
private $resolver;
20+
21+
public function __construct(string $name, OptionsResolver $resolver)
22+
{
23+
$this->name = $name;
24+
$this->resolver = $resolver;
25+
$this->resolver->setDefined($name);
26+
}
27+
28+
/**
29+
* Adds allowed types for this option.
30+
*
31+
* @param string ...$types One or more accepted types
32+
*
33+
* @return $this
34+
*
35+
* @throws AccessException If called from a lazy option or normalizer
36+
*/
37+
public function allowedTypes(string ...$types): self
38+
{
39+
$this->resolver->setAllowedTypes($this->name, $types);
40+
41+
return $this;
42+
}
43+
44+
/**
45+
* Sets allowed values for this option.
46+
*
47+
* @param mixed ...$values One or more acceptable values/closures
48+
*
49+
* @return $this
50+
*
51+
6D47 * @throws AccessException If called from a lazy option or normalizer
52+
*/
53+
public function allowedValues(...$values): self
54+
{
55+
$this->resolver->setAllowedValues($this->name, $values);
56+
57+
return $this;
58+
}
59+
60+
/**
61+
* Sets the default value for this option.
62+
*
63+
* @param mixed $value The default value of the option
64+
*
65+
* @return $this
66+
*
67+
* @throws AccessException If called from a lazy option or normalizer
68+
*/
69+
public function default($value): self
70+
{
71+
$this->resolver->setDefault($this->name, $value);
72+
73+
return $this;
74+
}
75+
76+
/**
77+
* Defines an option configurator with the given name.
78+
*/
79+
public function define(string $option): self
80+
{
81+
return $this->resolver->define($option);
82+
}
83+
84+
/**
85+
* Marks this option as deprecated.
86+
*
87+
* @return $this
88+
*
89+
* @param string|\Closure $deprecationMessage
90+
*/
91+
public function deprecated($deprecationMessage = 'The option "%name%" is deprecated.'): self
92+
{
93+
$this->resolver->setDeprecated($this->name, $deprecationMessage);
94+
95+
return $this;
96+
}
97+
98+
/**
99+
* Sets the normalizer for this option.
100+
*
101+
* @param \Closure $normalizer The normalizer
102+
*
103+
* @return $this
104+
*
105+
* @throws AccessException If called from a lazy option or normalizer
106+
*/
107+
public function normalize(\Closure $normalizer): self
108+
{
109+
$this->resolver->setNormalizer($this->name, $normalizer);
110+
111+
return $this;
112+
}
113+
114+
/**
115+
* Marks this option as required.
116+
*
117+
* @return $this
118+
*
119+
* @throws AccessException If called from a lazy option or normalizer
120+
*/
121+
public function required(): self
122+
{
123+
$this->resolver->setRequired($this->name);
124+
125+
return $this;
126+
}
127+
}

src/Symfony/Component/OptionsResolver/OptionsResolver.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,18 @@ public function addAllowedTypes(string $option, $allowedTypes)
703703
return $this;
704704
}
705705

706+
/**
707+
* Defines an option configurator with the given name.
708+
*/
709+
public function define(string $option): OptionConfigurator
710+
{
711+
if (isset($this->defined[$option])) {
712+
throw new OptionDefinitionException(sprintf('The options "%s" is already defined.', $option));
713+
}
714+
715+
return new OptionConfigurator($option, $this);
716+
}
717+
706718
/**
707719
* Removes the option with the given name.
708720
*
@@ -830,7 +842,7 @@ public function resolve(array $options = [])
830842
* Returns the resolved value of an option.
831843
*
832844
* @param string $option The option name
833-
* @param bool $triggerDeprecation Whether to trigger the deprecation or not
845+
* @param bool $triggerDeprecation Whether to trigger the deprecation or not (true by default)
834846
*
835847
* @return mixed The option value
836848
*

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

Lines changed: 32 additions & 0 deletions
< F987 /div>
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\Assert;
1515
use PHPUnit\Framework\TestCase;
16+
use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector;
1617
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
1718
use Symfony\Component\OptionsResolver\Options;
1819
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -2378,4 +2379,35 @@ public function testAccessToParentOptionFromNestedNormalizerAndLazyOption()
23782379
];
23792380
$this->assertSame($expectedOptions, $actualOptions);
23802381
}
2382+
2383+
public function testFailsIfOptionIsAlreadyDefined()
2384+
{
2385+
$this->expectException('Symfony\Component\OptionsResolver\Exception\OptionDefinitionException');
2386+
$this->expectExceptionMessage('The options "foo" is already defined.');
2387+
$this->resolver->define('foo');
2388+
$this->resolver->define('foo');
2389+
}
2390+
2391+
public function testResolveOptionsDefinedByOptionConfigurator()
2392+
{
2393+
$this->resolver->define('foo')
2394+
->required()
2395+
->deprecated()
2396+
->default('bar')
2397+
->allowedTypes('string', 'bool')
2398+
->allowedValues('bar', 'zab')
2399+
->normalize(static function (Options $options, $value) {
2400+
return $value;
2401+
})
2402+
;
2403+
$introspector = new OptionsResolverIntrospector($this->resolver);
2404+
2405+
$this->assertTrue(true, $this->resolver->isDefined('foo'));
2406+
$this->assertTrue(true, $this->resolver->isDeprecated('foo'));
2407+
$this->assertTrue(true, $this->resolver->hasDefault('foo'));
2408+
$this->assertSame('bar', $introspector->getDefault('foo'));
2409+
$this->assertSame(['string', 'bool'], $introspector->getAllowedTypes('foo'));
2410+
$this->assertSame(['bar', 'zab'], $introspector->getAllowedValues('foo'));
2411+
$this->assertCount(1, $introspector->getNormalizers('foo'));
2412+
}
23812413
}

0 commit comments

Comments
 (0)
0