Skip to content

Navigation Menu

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 877a720

Browse filesBrowse files
committed
Add setOptions method
1 parent 0deaa1e commit 877a720
Copy full SHA for 877a720

11 files changed

+852
-99
lines changed

‎UPGRADE-7.3.md

Copy file name to clipboardExpand all lines: UPGRADE-7.3.md
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,25 @@ FrameworkBundle
3939
because its default value will change in version 8.0
4040
* Deprecate the `--show-arguments` option of the `container:debug` command, as arguments are now always shown
4141

42+
OptionsResolver
43+
---------------
44+
45+
* Deprecate defining nested options via `setDefault()`, use `setOptions()` instead
46+
47+
*Before*
48+
```php
49+
$resolver->setDefault('option', function (OptionsResolver $resolver) {
50+
// ...
51+
});
52+
```
53+
54+
*After*
55+
```php
56+
$resolver->setOptions('option', function (OptionsResolver $resolver) {
57+
// ...
58+
});
59+
```
60+
4261
Serializer
4362
----------
4463

‎src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Ldap/Adapter/ExtLdap/Connection.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ protected function configureOptions(OptionsResolver $resolver): void
170170
$resolver->setAllowedTypes('debug', 'bool');
171171
$resolver->setDefault('referrals', false);
172172
$resolver->setAllowedTypes('referrals', 'bool');
173-
$resolver->setDefault('options', function (OptionsResolver $options, Options $parent) {
173+
$resolver->setOptions('options', function (OptionsResolver $options, Options $parent) {
174174
$options->setDefined(array_map('strtolower', array_keys((new \ReflectionClass(ConnectionOptions::class))->getConstants())));
175175

176176
if (true === $parent['debug']) {

‎src/Symfony/Component/Ldap/composer.json

Copy file name to clipboardExpand all lines: src/Symfony/Component/Ldap/composer.json
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@
1818
"require": {
1919
"php": ">=8.2",
2020
"ext-ldap": "*",
21-
"symfony/options-resolver": "^6.4|^7.0"
21+
"symfony/options-resolver": "^7.3"
2222
},
2323
"require-dev": {
2424
"symfony/security-core": "^6.4|^7.0",
2525
"symfony/security-http": "^6.4|^7.0"
2626
},
2727
"conflict": {
28-
"symfony/options-resolver": "<6.4",
2928
"symfony/security-core": "<6.4"
3029
},
3130
"autoload": {

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ CHANGELOG
55
---
66

77
* Support union type in `OptionResolver::setAllowedTypes()` method
8+
* Add `OptionsResolver::setOptions()` and `OptionConfigurator::options()` methods
9+
* Deprecate defining nested options via `setDefault()`, use `setOptions()` instead
810

911
6.4
1012
---

‎src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,14 @@ public function getDeprecation(string $option): array
101101
{
102102
return ($this->get)('deprecated', $option, \sprintf('No deprecation was set for the "%s" option.', $option));
103103
}
104+
105+
/**
106+
* @return \Closure[]
107+
*
108+
* @throws NoConfigurationException when no nested is configured
109+
*/
110+
public function getNested(string $option): array
111+
{
112+
return ($this->get)('nested', $option, \sprintf('No nested was set for the "%s" option.', $option));
113+
}
104114
}

‎src/Symfony/Component/OptionsResolver/OptionConfigurator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/OptionConfigurator.php
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,18 @@ public function ignoreUndefined(bool $ignore = true): static
143143

144144
return $this;
145145
}
146+
147+
/**
148+
* Defines nested options.
149+
*
150+
* @param \Closure(OptionsResolver $resolver, Options $parent): void $nested
151+
*
152+
* @return $this
153+
*/
154+
public function options(\Closure $nested): static
155+
{
156+
$this->resolver->setOptions($this->name, $nested);
157+
158+
return $this;
159+
}
146160
}

‎src/Symfony/Component/OptionsResolver/OptionsResolver.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/OptionsResolver.php
+66-42Lines changed: 66 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ class OptionsResolver implements Options
6464
*/
6565
private array $nested = [];
6666

67+
/**
68+
* BC layer. Remove in Symfony 8.0.
69+
*
70+
* @var array<string, true>
71+
*/
72+
private array $deprecatedNested = [];
73+
6774
/**
6875
* The names of required options.
6976
*/
@@ -178,20 +185,6 @@ class OptionsResolver implements Options
178185
* is spread across different locations of your code, such as base and
179186
* sub-classes.
180187
*
181-
* If you want to define nested options, you can pass a closure with the
182-
* following signature:
183-
*
184-
* $options->setDefault('database', function (OptionsResolver $resolver) {
185-
* $resolver->setDefined(['dbname', 'host', 'port', 'user', 'pass']);
186-
* }
187-
*
188-
* To get access to the parent options, add a second argument to the closure's
189-
* signature:
190-
*
191-
* function (OptionsResolver $resolver, Options $parent) {
192-
* // 'default' === $parent['connection']
193-
* }
194-
*
195188
* @return $this
196189
*
197190
* @throws AccessException If called from a lazy option or normalizer
@@ -226,13 +219,22 @@ public function setDefault(string $option, mixed $value): static
226219
$this->lazy[$option][] = $value;
227220
$this->defined[$option] = true;
228221

229-
// Make sure the option is processed and is not nested anymore
230-
unset($this->resolved[$option], $this->nested[$option]);
222+
// Make sure the option is processed
223+
unset($this->resolved[$option]);
224+
225+
// BC layer. Remove in Symfony 8.0.
226+
if (isset($this->deprecatedNested[$option])) {
227+
unset($this->nested[$option]);
228+
}
231229

232230
return $this;
233231
}
234232

233+
// Remove in Symfony 8.0.
235234
if (isset($params[0]) && ($type = $params[0]->getType()) instanceof \ReflectionNamedType && self::class === $type->getName() && (!isset($params[1]) || (($type = $params[1]->getType()) instanceof \ReflectionNamedType && Options::class === $type->getName()))) {
235+
trigger_deprecation('symfony/options-resolver', '7.3', 'Defining nested options via "%s()" is deprecated and will be removed in Symfony 8.0, use "setOptions()" method instead.', __METHOD__);
236+
$this->deprecatedNested[$option] = true;
237+
236238
// Store closure for later evaluation
237239
$this->nested[$option][] = $value;
238240
$this->defaults[$option] = [];
@@ -245,8 +247,13 @@ public function setDefault(string $option, mixed $value): static
245247
}
246248
}
247249

248-
// This option is not lazy nor nested anymore
249-
unset($this->lazy[$option], $this->nested[$option]);
250+
// This option is not lazy anymore
251+
unset($this->lazy[$option]);
252+
253+
// BC layer. Remove in Symfony 8.0.
254+
if (isset($this->deprecatedNested[$option])) {
255+
unset($this->nested[$option]);
256+
}
250257

251258
// Yet undefined options can be marked as resolved, because we only need
252259
// to resolve options with lazy closures, normalizers or validation
@@ -403,6 +410,30 @@ public function getDefinedOptions(): array
403410
return array_keys($this->defined);
404411
}
405412

413+
/**
414+
* Defines nested options.
415+
*
416+
* @param \Closure(self $resolver, Options $parent): void $nested
417+
*
418+
* @return $this
419+
*/
420+
public function setOptions(string $option, \Closure $nested): static
421+
{
422+
if ($this->locked) {
423+
throw new AccessException('Nested options cannot be defined from a lazy option or normalizer.');
424+
}
425+
426+
// Store closure for later evaluation
427+
$this->nested[$option][] = $nested;
428+
$this->defaults[$option] = [];
429+
$this->defined[$option] = true;
430+
431+
// Make sure the option is processed
432+
unset($this->resolved[$option]);
433+
434+
return $this;
435+
}
436+
406437
public function isNested(string $option): bool
407438
{
408439
return isset($this->nested[$option]);
@@ -947,6 +978,23 @@ public function offsetGet(mixed $option, bool $triggerDeprecation = true): mixed
947978

948979
$value = $this->defaults[$option];
949980

981+
// Resolve the option if the default value is lazily evaluated
982+
if (isset($this->lazy[$option])) {
983+
// If the closure is already being called, we have a cyclic dependency
984+
if (isset($this->calling[$option])) {
985+
throw new OptionDefinitionException(\sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
986+
}
987+
988+
$this->calling[$option] = true;
989+
try {
990+
foreach ($this->lazy[$option] as $closure) {
991+
$value = $closure($this, $value);
992+
}
993+
} finally {
994+
unset($this->calling[$option]);
995+
}
996+
}
997+
950998
// Resolve the option if it is a nested definition
951999
if (isset($this->nested[$option])) {
9521000
// If the closure is already being called, we have a cyclic dependency
@@ -958,7 +1006,6 @@ public function offsetGet(mixed $option, bool $triggerDeprecation = true): mixed
9581006
throw new InvalidOptionsException(\sprintf('The nested option "%s" with value %s is expected to be of type array, but is of type "%s".', $this->formatOptions([$option]), $this->formatValue($value), get_debug_type($value)));
9591007
}
9601008

961-
// The following section must be protected from cyclic calls.
9621009
$this->calling[$option] = true;
9631010
try {
9641011
$resolver = new self();
@@ -989,29 +1036,6 @@ public function offsetGet(mixed $option, bool $triggerDeprecation = true): mixed
9891036
}
9901037
}
9911038

992-
// Resolve the option if the default value is lazily evaluated
993-
if (isset($this->lazy[$option])) {
994-
// If the closure is already being called, we have a cyclic
995-
// dependency
996-
if (isset($this->calling[$option])) {
997-
throw new OptionDefinitionException(\sprintf('The options "%s" have a cyclic dependency.', $this->formatOptions(array_keys($this->calling))));
998-
}
999-
1000-
// The following section must be protected from cyclic
1001-
// calls. Set $calling for the current $option to detect a cyclic
1002-
// dependency
1003-
// BEGIN
1004-
$this->calling[$option] = true;
1005-
try {
1006-
foreach ($this->lazy[$option] as $closure) {
1007-
$value = $closure($this, $value);
1008-
}
1009-
} finally {
1010-
unset($this->calling[$option]);
1011-
}
1012-
// END
1013-
}
1014-
10151039
// Validate the type of the resolved option
10161040
if (isset($this->allowedTypes[$option])) {
10171041
$valid = true;

‎src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,13 @@ public function testGetDeprecationMessageThrowsOnNotDefinedOption()
263263
$debug = new OptionsResolverIntrospector($resolver);
264264
$debug->getDeprecation('foo');
265265
}
266+
267+
public function testGetClosureNested()
268+
{
269+
$resolver = new OptionsResolver();
270+
$resolver->setOptions('foo', $closure = function (OptionsResolver $resolver) {});
271+
272+
$debug = new OptionsResolverIntrospector($resolver);
273+
$this->assertSame([$closure], $debug->getNested('foo'));
274+
}
266275
}

0 commit comments

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