Skip to content

Commit 9549b89

Browse files
committed
[Config] Deprecate setting a default value to a node that is required, and vice versa
1 parent e3141c9 commit 9549b89

File tree

5 files changed

+64
-2
lines changed

5 files changed

+64
-2
lines changed

UPGRADE-7.4.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Config
2222
------
2323

2424
* Deprecate accessing the internal scope of the loader in PHP config files, use only its public API instead
25+
* Deprecate setting a default value to a node that is required, and vice versa
2526

2627
Console
2728
-------

src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public function addConfiguration(NodeDefinition $node): void
5353
{
5454
$node
5555
->children()
56-
->scalarNode('service')->isRequired()->cannotBeEmpty()->defaultValue('ldap')->end()
56+
->scalarNode('service')->isRequired()->cannotBeEmpty()->example('ldap')->end()
5757
->scalarNode('base_dn')->isRequired()->cannotBeEmpty()->end()
5858
->scalarNode('search_dn')->defaultNull()->end()
5959
->scalarNode('search_password')->defaultNull()->end()

src/Symfony/Component/Config/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
* Add `ArrayNodeDefinition::acceptAndWrap()` to list alternative types that should be accepted and wrapped in an array
1111
* Add array-shapes to generated config builders
1212
* Deprecate accessing the internal scope of the loader in PHP config files, use only its public API instead
13+
* Deprecate setting a default value to a node that is required, and vice versa
1314

1415
7.3
1516
---

src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ public function getNode(bool $forceRootNode = false): NodeInterface
178178
*/
179179
public function defaultValue(mixed $value): static
180180
{
181+
if ($this->required) {
182+
// Uncomment in 8.0
183+
// throw new InvalidDefinitionException(sprintf('You cannot set a default value to the node "%s" as it is required.', $this->name));
184+
trigger_deprecation('symfony/config', '7.4', 'Setting a default value to the node "%s" is deprecated when it is required.', $this->name);
185+
}
186+
181187
$this->default = true;
182188
$this->defaultValue = $value;
183189

@@ -191,6 +197,12 @@ public function defaultValue(mixed $value): static
191197
*/
192198
public function isRequired(): static
193199
{
200+
if ($this->default) {
201+
// Uncomment in 8.0
202+
// throw new InvalidDefinitionException(sprintf('You cannot set the node "%s" as required as it has a default value.', $this->name));
203+
trigger_deprecation('symfony/config', '7.4', 'Setting the node "%s" as required is deprecated when it has a default value.', $this->name);
204+
}
205+
194206
$this->required = true;
195207

196208
return $this;

src/Symfony/Component/Config/Tests/Definition/Builder/NodeDefinitionTest.php

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,17 @@
1111

1212
namespace Symfony\Component\Config\Tests\Definition\Builder;
1313

14+
use PHPUnit\Framework\Attributes\DataProvider;
15+
use PHPUnit\Framework\Attributes\Group;
16+
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
1417
use PHPUnit\Framework\TestCase;
1518
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
19+
use Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition;
1620
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
21+
use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
22+
use Symfony\Component\Config\Definition\Builder\StringNodeDefinition;
23+
use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition;
24+
use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
1725

1826
class NodeDefinitionTest extends TestCase
1927
{
@@ -60,10 +68,50 @@ public function testDocUrlWithoutPackage()
6068

6169
public function testUnknownPackageThrowsException()
6270
{
71+
$node = new ArrayNodeDefinition('node');
72+
6373
$this->expectException(\OutOfBoundsException::class);
6474
$this->expectExceptionMessage('Package "phpunit/invalid" is not installed');
6575

66-
$node = new ArrayNodeDefinition('node');
6776
$node->docUrl('https://example.com/doc/{package}/{version:major}.{version:minor}', 'phpunit/invalid');
6877
}
78+
79+
#[IgnoreDeprecations]
80+
#[Group('legacy')]
81+
#[DataProvider('provideDefinitionClassesAndDefaultValues')]
82+
public function testIncoherentRequiredAndDefaultValue(string $class, mixed $defaultValue)
83+
{
84+
$node = new $class('foo');
85+
self::assertInstanceOf(NodeDefinition::class, $node);
86+
87+
// $this->expectException(InvalidDefinitionException::class);
88+
// $this->expectExceptionMessage('You cannot set the node "foo" as required as it has a default value.');
89+
$this->expectUserDeprecationMessage('Since symfony/config 7.4: Setting the node "foo" as required is deprecated when it has a default value.');
90+
91+
$node->defaultValue($defaultValue)->isRequired();
92+
}
93+
94+
#[IgnoreDeprecations]
95+
#[Group('legacy')]
96+
#[DataProvider('provideDefinitionClassesAndDefaultValues')]
97+
public function testIncoherentDefaultValueAndRequired(string $class, mixed $defaultValue)
98+
{
99+
$node = new $class('foo');
100+
self::assertInstanceOf(NodeDefinition::class, $node);
101+
102+
// $this->expectException(InvalidDefinitionException::class);
103+
// $this->expectExceptionMessage('You cannot set a default value to the node "foo" as it is required.');
104+
$this->expectUserDeprecationMessage('Since symfony/config 7.4: Setting a default value to the node "foo" is deprecated when it is required.');
105+
106+
$node->isRequired()->defaultValue($defaultValue);
107+
}
108+
109+
public static function provideDefinitionClassesAndDefaultValues()
110+
{
111+
yield [ArrayNodeDefinition::class, []];
112+
yield [ScalarNodeDefinition::class, null];
113+
yield [BooleanNodeDefinition::class, false];
114+
yield [StringNodeDefinition::class, 'default'];
115+
yield [VariableNodeDefinition::class, 'default'];
116+
}
69117
}

0 commit comments

Comments
 (0)