Skip to content

Commit 9f8f8f1

Browse files
[Config] Allow using defaultNull() on BooleanNodeDefinition
1 parent b61db2f commit 9f8f8f1

File tree

5 files changed

+83
-3
lines changed

5 files changed

+83
-3
lines changed

src/Symfony/Component/Config/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Add `#[WhenNot]` attribute to prevent service from being registered in a specific environment
88
* Generate a meta file in JSON format for resource tracking
99
* Add `SkippingResourceChecker`
10+
* Add support for `defaultNull()` on `BooleanNode`
1011

1112
7.1
1213
---

src/Symfony/Component/Config/Definition/BooleanNode.php

+14-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,23 @@
2020
*/
2121
class BooleanNode extends ScalarNode
2222
{
23+
public function __construct(
24+
?string $name,
25+
?NodeInterface $parent = null,
26+
string $pathSeparator = self::DEFAULT_PATH_SEPARATOR,
27+
protected bool $nullable = false
28+
) {
29+
parent::__construct($name, $parent, $pathSeparator);
30+
}
31+
2332
protected function validateType(mixed $value): void
2433
{
2534
if (!\is_bool($value)) {
26-
$ex = new InvalidTypeException(\sprintf('Invalid type for path "%s". Expected "bool", but got "%s".', $this->getPath(), get_debug_type($value)));
35+
if (null === $value && $this->nullable) {
36+
return;
37+
}
38+
39+
$ex = new InvalidTypeException(\sprintf('Invalid type for path "%s". Expected "%sbool", but got "%s".', $this->getPath(), $this->nullable ? '?' : '', get_debug_type($value)));
2740
if ($hint = $this->getInfo()) {
2841
$ex->addHint($hint);
2942
}

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

+17-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function __construct(?string $name, ?NodeParentInterface $parent = null)
3333
*/
3434
protected function instantiateNode(): BooleanNode
3535
{
36-
return new BooleanNode($this->name, $this->parent, $this->pathSeparator);
36+
return new BooleanNode($this->name, $this->parent, $this->pathSeparator, null === $this->nullEquivalent);
3737
}
3838

3939
/**
@@ -43,4 +43,20 @@ public function cannotBeEmpty(): static
4343
{
4444
throw new InvalidDefinitionException('->cannotBeEmpty() is not applicable to BooleanNodeDefinition.');
4545
}
46+
47+
public function defaultNull(): static
48+
{
49+
$this->nullEquivalent = null;
50+
51+
return parent::defaultNull();
52+
}
53+
54+
public function defaultValue(mixed $value): static
55+
{
56+
if (null === $value) {
57+
$this->nullEquivalent = null;
58+
}
59+
60+
return parent::defaultValue($value);
61+
}
4662
}

src/Symfony/Component/Config/Tests/Definition/BooleanNodeTest.php

+27-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,33 @@ public function testNormalize(bool $value)
2626
$this->assertSame($value, $node->normalize($value));
2727
}
2828

29+
public function testNullValueOnNullable()
30+
{
31+
$node = new BooleanNode('test', null, '.', true);
32+
33+
$this->assertNull($node->normalize(null));
34+
}
35+
36+
public function testNullValueOnNotNullable()
37+
{
38+
$node = new BooleanNode('test', null, '.', false);
39+
40+
$this->expectException(InvalidTypeException::class);
41+
$this->expectExceptionMessage('Invalid type for path "test". Expected "bool", but got "null".');
42+
43+
$this->assertNull($node->normalize(null));
44+
}
45+
46+
public function testInvalidValueOnNullable()
47+
{
48+
$node = new BooleanNode('test', null, '.', true);
49+
50+
$this->expectException(InvalidTypeException::class);
51+
$this->expectExceptionMessage('Invalid type for path "test". Expected "?bool", but got "int".');
52+
53+
$node->normalize(123);
54+
}
55+
2956
/**
3057
* @dataProvider getValidValues
3158
*/
@@ -60,7 +87,6 @@ public function testNormalizeThrowsExceptionOnInvalidValues($value)
6087
public static function getInvalidValues(): array
6188
{
6289
return [
63-
[null],
6490
[''],
6591
['foo'],
6692
[0],

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

+24
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,30 @@ public function testCannotBeEmptyThrowsAnException()
2525
$def->cannotBeEmpty();
2626
}
2727

28+
public function testBooleanNodeWithDefaultNull()
29+
{
30+
$def = new BooleanNodeDefinition('foo');
31+
$def->defaultNull();
32+
33+
$node = $def->getNode();
34+
$this->assertTrue($node->hasDefaultValue());
35+
$this->assertNull($node->getDefaultValue());
36+
37+
$this->assertNull($node->normalize(null));
38+
}
39+
40+
public function testBooleanNodeWithDefaultValueAtNull()
41+
{
42+
$def = new BooleanNodeDefinition('foo');
43+
$def->defaultValue(null);
44+
45+
$node = $def->getNode();
46+
$this->assertTrue($node->hasDefaultValue());
47+
$this->assertNull($node->getDefaultValue());
48+
49+
$this->assertNull($node->normalize(null));
50+
}
51+
2852
public function testSetDeprecated()
2953
{
3054
$def = new BooleanNodeDefinition('foo');

0 commit comments

Comments
 (0)