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 1ff5640

Browse filesBrowse files
lmilluccinicolas-grekas
authored andcommitted
[OptionsResolver] Add new OptionConfigurator class to define options with fluent interface
1 parent 1c28bf7 commit 1ff5640
Copy full SHA for 1ff5640

File tree

4 files changed

+177
-1
lines changed
Filter options

4 files changed

+177
-1
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/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+
5.1.0
5+
-----
6+
7+
* added fluent configuration of options using `OptionResolver::define()`
8+
49
5.0.0
510
-----
611

+127Lines 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+
* @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

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/OptionsResolver.php
+13-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php
+32Lines changed: 32 additions & 0 deletions
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)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.