Description
Symfony version(s) affected
v2.1.0+
Description
In my use-case I have a node with enabled
field, which can have 3 values:
true
: always enable componentfalse
: do not enable the componentnull
: enable if it's needed (dependent on rather complex logic, outside of the scope of config schema)
The issue is I cannot use booleanNode()
as it is well... boolean.
How to reproduce
->children()
->enumNode('enabled')
->values([true, false, null])
->defaultNull()
->end()
While the code above "works", using bin/console config:dump-reference
reveals that in fact the null
is not an expected values:
doctrine_changeset_marshaller:
enabled: null # One of true; false
Possible Solution
The issue stems from usage of array_unique()
in two places:
symfony/src/Symfony/Component/Config/Definition/EnumNode.php
Lines 13 to 19 in 8308aea
The issue is, \array_unique()
compares values according to their string representation. I believe this is less than idea in the case of EnumNode
. The \array_unique()
, unlike functions like \in_array()
does not support $strict
parameter (and the discussion on that died in 2013). Thus, to really solve this issue a custom strict function would need to be used:
However, this does not cover empty string case. Given the EnumNode
usage of the array where keys in the array aren't important, I think the solution would be to replace \array_unique()
call with a function like:
function arrayUniqueStrict(array $values): array
{
$unique = [];
foreach($values as $k => $v) {
if (!\in_array($v, $unique, true)) {
$unique[$k] = $v;
}
}
return $unique;
}
Additional Context
If the intention of EnumNode
to be type-loose, then my suggested fix is obviously a no-go. In such a case I think it should be noted in the docs.