Symfony: [Config] Array nodes with default values aren't validated

Created on 18 Mar 2017  路  3Comments  路  Source: symfony/symfony

| Q | A
| ---------------- | -----
| Bug report? | yes
| Feature request? | no
| BC Break report? | no
| RFC? | no
| Symfony version | all

The Scenario

We have an ivory_ckeditor option with 2 childs: enabled and config_name. The config_name option has to be defined when the enabled option is true, however can be left out when enabled is false.

To achieve this, we've defined the following structure:

$root
    ->children()
        ->arrayNode('bundles')
            ->isRequired()
            ->children()
                ->arrayNode('content')
                    ->addDefaultsIfNotSet()
                    ->canBeEnabled()
                    ->children()
                        ->arrayNode('ivory_ckeditor')
                            ->addDefaultsIfNotSet()
                            ->treatFalseLike(['enabled' => false])
                            ->treatTrueLike(['enabled' => true])
                            ->treatNullLike(['enabled' => 'auto'])
                            ->validate()
                                ->ifTrue(function ($v) { return false !== $v['enabled'] && !isset($v['config_name']); })
                                ->thenInvalid('The config_name option has to be defined if CKEditor integration is enabled.')
                            ->end()
                            ->children()
                                ->enumNode('enabled')
                                    ->values([true, false, 'auto'])
                                    ->defaultValue('auto')
                                ->end()
                                ->scalarNode('config_name')->end()
                            ->end()
                        ->end() // ivory_ckeditor
                    ->end()
                ->end() // content
            ->end()
        ->end() // bundles
    ->end()
;

Test Case

Given the following configuration:

acme:
    bundles:
        content: ~

Then I would expect an error: The config_name option has to be defined if CKEditor integration is enabled.

Instead, no error is reported. In fact, the complete ->validate() rule is not executed.

The explanation

As soon as setDefaultsIfNotSet() is used and there are default values, validation is skipped (see the code).

While it seems logical that a default value is valid and thus doesn't need validation, this can't be applied 100% for array nodes: Some children might not have a default value and need to be validated.

Proposal

I would propose to always run validation, even if default values apply. As this might break applications, we need to add a flag to ArrayNodeBuilder to enable this validation, triggering a deprecation when it disables. Much like the choices_as_value option in the choice form type was handled.

Bug Config Stalled Needs Review

Most helpful comment

Instead of a flag I would for now prefer triggering the errors as warnings and switch them to errors in 4.0. That keeps it within BC promise.

All 3 comments

Instead of a flag I would for now prefer triggering the errors as warnings and switch them to errors in 4.0. That keeps it within BC promise.

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

Not sure, can't reproduce this anymore (and I don't understand my previous code reference). Let's close

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HappyJiJi picture HappyJiJi  路  3Comments

ryan0x44 picture ryan0x44  路  3Comments

patrick-mcdougle picture patrick-mcdougle  路  3Comments

FRAGnatt picture FRAGnatt  路  3Comments

ghost picture ghost  路  3Comments