Completed
Push — master ( b9c485...94fed1 )
by Michał
13:51
created

RbacBundle/DependencyInjection/Configuration.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Bundle\RbacBundle\DependencyInjection;
13
14
use Sylius\Bundle\RbacBundle\Form\Type\PermissionType;
15
use Sylius\Bundle\RbacBundle\Form\Type\RoleType;
16
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
17
use Sylius\Bundle\ResourceBundle\Form\Type\ResourceChoiceType;
18
use Sylius\Bundle\ResourceBundle\SyliusResourceBundle;
19
use Sylius\Component\Rbac\Model\Permission;
20
use Sylius\Component\Rbac\Model\PermissionInterface;
21
use Sylius\Component\Rbac\Model\Role;
22
use Sylius\Component\Rbac\Model\RoleInterface;
23
use Sylius\Component\Resource\Factory\Factory;
24
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
25
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
26
use Symfony\Component\Config\Definition\ConfigurationInterface;
27
28
/**
29
 * This class contains the configuration information for the bundle.
30
 *
31
 * This information is solely responsible for how the different configuration
32
 * sections are normalized, and merged.
33
 *
34
 * @author Paweł Jędrzejewski <[email protected]>
35
 */
36
class Configuration implements ConfigurationInterface
37
{
38
    /**
39
     * {@inheritdoc}
40
     */
41
    public function getConfigTreeBuilder()
42
    {
43
        $treeBuilder = new TreeBuilder();
44
        $rootNode = $treeBuilder->root('sylius_rbac');
45
46
        $rootNode
47
            ->children()
48
                ->scalarNode('driver')->defaultValue(SyliusResourceBundle::DRIVER_DOCTRINE_ORM)->end()
49
                ->scalarNode('authorization_checker')->defaultValue('sylius.authorization_checker.default')->end()
50
                ->scalarNode('identity_provider')->defaultValue('sylius.authorization_identity_provider.security')->end()
51
                ->scalarNode('permission_map')->defaultValue('sylius.permission_map.cached')->end()
52
                ->arrayNode('security_roles')
53
                    ->useAttributeAsKey('id')
54
                    ->prototype('scalar')
55
                    ->defaultValue([])
56
                ->end()
57
            ->end()
58
        ;
59
60
        $this->addResourcesSection($rootNode);
61
        $this->addRolesSection($rootNode);
62
        $this->addPermissionsSection($rootNode);
63
64
        return $treeBuilder;
65
    }
66
67
    /**
68
     * @param ArrayNodeDefinition $node
69
     */
70
    private function addResourcesSection(ArrayNodeDefinition $node)
71
    {
72
        $node
73
            ->children()
74
                ->arrayNode('resources')
75
                    ->addDefaultsIfNotSet()
76
                    ->children()
77
                        ->arrayNode('role')
78
                            ->addDefaultsIfNotSet()
79
                            ->children()
80
                                ->variableNode('options')->end()
81
                                ->arrayNode('classes')
82
                                    ->addDefaultsIfNotSet()
83
                                    ->children()
84
                                        ->scalarNode('model')->defaultValue(Role::class)->cannotBeEmpty()->end()
85
                                        ->scalarNode('interface')->defaultValue(RoleInterface::class)->cannotBeEmpty()->end()
86
                                        ->scalarNode('controller')->defaultValue(ResourceController::class)->cannotBeEmpty()->end()
87
                                        ->scalarNode('repository')->cannotBeEmpty()->end()
88
                                        ->scalarNode('factory')->defaultValue(Factory::class)->end()
89
                                        ->arrayNode('form')
90
                                            ->addDefaultsIfNotSet()
91
                                            ->children()
92
                                                ->scalarNode('default')->defaultValue(RoleType::class)->cannotBeEmpty()->end()
93
                                                ->scalarNode('choice')->defaultValue(ResourceChoiceType::class)->cannotBeEmpty()->end()
94
                                            ->end()
95
                                        ->end()
96
                                    ->end()
97
                                ->end()
98
                                ->arrayNode('validation_groups')
99
                                    ->addDefaultsIfNotSet()
100
                                    ->children()
101
                                        ->arrayNode('default')
102
                                            ->prototype('scalar')->end()
103
                                            ->defaultValue(['sylius'])
104
                                        ->end()
105
                                    ->end()
106
                                ->end()
107
                            ->end()
108
                        ->end()
109
                        ->arrayNode('permission')
110
                            ->addDefaultsIfNotSet()
111
                            ->children()
112
                                ->variableNode('options')->end()
113
                                ->arrayNode('classes')
114
                                    ->addDefaultsIfNotSet()
115
                                    ->children()
116
                                        ->scalarNode('model')->defaultValue(Permission::class)->cannotBeEmpty()->end()
117
                                        ->scalarNode('interface')->defaultValue(PermissionInterface::class)->cannotBeEmpty()->end()
118
                                        ->scalarNode('controller')->defaultValue(ResourceController::class)->cannotBeEmpty()->end()
119
                                        ->scalarNode('repository')->cannotBeEmpty()->end()
120
                                        ->scalarNode('factory')->defaultValue(Factory::class)->end()
121
                                        ->arrayNode('form')
122
                                            ->addDefaultsIfNotSet()
123
                                            ->children()
124
                                                ->scalarNode('default')->defaultValue(PermissionType::class)->cannotBeEmpty()->end()
125
                                                ->scalarNode('choice')->defaultValue(ResourceChoiceType::class)->cannotBeEmpty()->end()
126
                                            ->end()
127
                                        ->end()
128
                                    ->end()
129
                                ->end()
130
                                ->arrayNode('validation_groups')
131
                                    ->addDefaultsIfNotSet()
132
                                    ->children()
133
                                        ->arrayNode('default')
134
                                            ->prototype('scalar')->end()
135
                                            ->defaultValue(['sylius'])
136
                                        ->end()
137
                                    ->end()
138
                                ->end()
139
                            ->end()
140
                        ->end()
141
                    ->end()
142
                ->end()
143
            ->end()
144
        ;
145
    }
146
147
    /**
148
     * @param ArrayNodeDefinition $node
149
     */
150
    private function addRolesSection(ArrayNodeDefinition $node)
151
    {
152
        $node
0 ignored issues
show
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Config...\Builder\NodeDefinition as the method children() does only exist in the following sub-classes of Symfony\Component\Config...\Builder\NodeDefinition: Symfony\Component\Config...der\ArrayNodeDefinition. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
153
            ->children()
154
                ->arrayNode('roles')
155
                    ->useAttributeAsKey('id')
156
                    ->prototype('array')
157
                        ->children()
158
                            ->scalarNode('name')->isRequired()->cannotBeEmpty()->end()
159
                            ->scalarNode('description')->end()
160
                            ->arrayNode('permissions')
161
                                ->prototype('scalar')->end()
162
                            ->end()
163
                            ->arrayNode('security_roles')
164
                                ->prototype('scalar')->end()
165
                                ->defaultValue([])
166
                            ->end()
167
                        ->end()
168
                    ->end()
169
                ->end()
170
                ->arrayNode('roles_hierarchy')
171
                    ->useAttributeAsKey('id')
172
                    ->prototype('array')
173
                        ->beforeNormalization()->ifString()->then(function ($v) { return ['value' => $v]; })->end()
174
                        ->beforeNormalization()
175
                            ->ifTrue(function ($v) { return is_array($v) && isset($v['value']); })
176
                            ->then(function ($v) { return preg_split('/\s*,\s*/', $v['value']); })
177
                        ->end()
178
                        ->prototype('scalar')->end()
179
                    ->end()
180
                ->end()
181
            ->end()
182
        ;
183
    }
184
185
    /**
186
     * @param ArrayNodeDefinition $node
187
     */
188
    private function addPermissionsSection(ArrayNodeDefinition $node)
189
    {
190
        $node
0 ignored issues
show
The method defaultValue() does not seem to exist on object<Symfony\Component...on\Builder\NodeBuilder>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
191
            ->children()
192
                ->arrayNode('permissions')
193
                    ->useAttributeAsKey('id')
194
                    ->prototype('scalar')->end()
195
                    ->defaultValue([])
196
                ->end()
197
                ->arrayNode('permissions_hierarchy')
198
                    ->useAttributeAsKey('id')
199
                    ->prototype('array')
200
                        ->performNoDeepMerging()
201
                        ->beforeNormalization()->ifString()->then(function ($v) { return ['value' => $v]; })->end()
202
                        ->beforeNormalization()
203
                            ->ifTrue(function ($v) { return is_array($v) && isset($v['value']); })
204
                            ->then(function ($v) { return preg_split('/\s*,\s*/', $v['value']); })
205
                        ->end()
206
                        ->prototype('scalar')->end()
207
                    ->end()
208
                ->end()
209
            ->end()
210
        ;
211
    }
212
}
213