Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[FrameworkBundle] Lock configuration not working as expected #31197

Closed
@HypeMC

Description

@HypeMC

Symfony version(s) affected: >=3.4

Description
I've found two issues with the framework bundle lock configuration:

  1. When you don't have the full stack framework but only certain components, eg flex
  2. When xml is used

How to reproduce

  1. 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).

  1. 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

  1. I've added a beforeNormalization rule that adds an enabled flag if it's missing:
    ->beforeNormalization()
        ->ifTrue(function ($v) { return \is_array($v) && !isset($v['enabled']); })
        ->then(function ($v) { return $v + ['enabled' => true]; })
    ->end()
  1. I've added a beforeNormalization rule for xml files since the fixXmlConfig and useAttributeAsKey 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()

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions