Closed
Description
Symfony version(s) affected: >=3.4
Description
I've found two issues with the framework bundle lock configuration:
- When you don't have the full stack framework but only certain components, eg flex
- When xml is used
How to reproduce
- Add the following configuration to a symfony installation that's NOT a full stack one:
lock:
invoice: 'flock'
report: 'semaphore'
You'll get the following error:
In Configuration.php line 955:
Notice: Undefined index: enabled
The problem is with the following configuration:
// src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
->{!class_exists(FullStack::class) && class_exists(Lock::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->beforeNormalization()
->ifTrue(function ($v) { return \is_array($v) && !isset($v['resources']); })
->then(function ($v) {
$e = $v['enabled'];
unset($v['enabled']);
return ['enabled' => $e, 'resources' => $v];
})
->end()
When you have a full stack symfony installation canBeEnabled
adds an enabled
flag:
// src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php
->beforeNormalization()
->ifArray()
->then(function ($v) {
$v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true;
return $v;
})
->end()
canBeDisabled
however does not do this, but the beforeNormalization
configuration code assumes that enabled
always exists (the $e = $v['enabled'];
part).
- I've tried using the xml from the original PR but I got the foloowing error:
Invalid type for path "framework.lock.resources.resource.0". Expected scalar, but got array.
The reason for this is cause ->fixXmlConfig('resource')
happenes after all the beforeNormalization
rules, one of which is:
->beforeNormalization()
->ifTrue(function ($v) { return \is_array($v) && !isset($v['resources']); })
->then(function ($v) {
$e = $v['enabled'];
unset($v['enabled']);
return ['enabled' => $e, 'resources' => $v];
})
->end()
so you get:
'resources' => [
'resource' => [
[
'name' => 'foo',
'value' => 'semaphore',
],
[
'name' => 'bar',
'value' => 'flock',
],
],
],
Also, adding ->useAttributeAsKey('name')
doesn't help cause of the following beforeNormalization
rule which is run first:
->beforeNormalization()
->ifTrue(function ($v) { return \is_array($v) && array_keys($v) === range(0, \count($v) - 1); })
->then(function ($v) { return ['default' => $v]; })
->end()
so you get:
'resources' => [
'default' => [
[
'name' => 'foo',
'value' => 'semaphore',
],
[
'name' => 'bar',
'value' => 'flock',
],
],
],
Possible Solution
- I've added a
beforeNormalization
rule that adds anenabled
flag if it's missing:
->beforeNormalization()
->ifTrue(function ($v) { return \is_array($v) && !isset($v['enabled']); })
->then(function ($v) { return $v + ['enabled' => true]; })
->end()
- I've added a
beforeNormalization
rule for xml files since thefixXmlConfig
anduseAttributeAsKey
options didn't work in this case:
->beforeNormalization()
->ifTrue(function ($v) { return \is_array($v) && isset($v['resource']); })
->then(function ($v) {
$resources = [];
foreach ($v['resource'] as $resource) {
$resources = array_merge_recursive(
$resources,
\is_array($resource) ? [$resource['name'] => $resource['value']] : ['default' => $resource]
);
}
return [
'enabled' => $v['enabled'],
'resources' => $resources,
];
})
->end()