Completed
Push — master ( 6c4efe...df4b6e )
by Tobias
08:17
created

Configuration::getProvidersNode()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 21
cts 21
cp 1
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 22
nc 1
nop 0
crap 1
1
<?php
2
3
/*
4
 * This file is part of the BazingaGeocoderBundle package.
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @license    MIT License
9
 */
10
11
namespace Bazinga\GeocoderBundle\DependencyInjection;
12
13
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
14
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
15
use Symfony\Component\Config\Definition\ConfigurationInterface;
16
17
/**
18
 * @author William Durand <[email protected]>
19
 */
20
class Configuration implements ConfigurationInterface
21
{
22
    /**
23
     * Whether to use the debug mode.
24
     *
25
     * @see https://github.com/doctrine/DoctrineBundle/blob/v1.5.2/DependencyInjection/Configuration.php#L31-L41
26
     *
27
     * @var bool
28
     */
29
    private $debug;
30
31
    /**
32
     * @param bool $debug
33
     */
34 23
    public function __construct($debug)
35
    {
36 23
        $this->debug = (bool) $debug;
37 23
    }
38
39
    /**
40
     * Generates the configuration tree builder.
41
     *
42
     * @return TreeBuilder The tree builder
43
     */
44 23
    public function getConfigTreeBuilder()
45
    {
46 23
        $treeBuilder = new TreeBuilder();
47 23
        $rootNode = $treeBuilder->root('bazinga_geocoder');
48
49
        $rootNode
50 23
            ->children()
51 23
            ->append($this->getProvidersNode())
52 23
            ->arrayNode('profiling')
53 23
                ->addDefaultsIfNotSet()
54 23
                ->treatFalseLike(['enabled' => false])
55 23
                ->treatTrueLike(['enabled' => true])
56 23
                ->treatNullLike(['enabled' => $this->debug])
57 23
                ->info('Extend the debug profiler with information about requests.')
58 23
                ->children()
59 23
                    ->booleanNode('enabled')
60 23
                        ->info('Turn the toolbar on or off. Defaults to kernel debug mode.')
61 23
                        ->defaultValue($this->debug)
62 23
                    ->end()
63 23
                ->end()
64 23
            ->end()
65 23
            ->arrayNode('fake_ip')
66 23
                ->beforeNormalization()
67 23
                ->ifString()
68
                    ->then(function ($value) {
69
                        return ['ip' => $value];
70 23
                    })
71 23
                ->end()
72 23
                ->canBeEnabled()
73 23
                ->children()
74 23
                    ->scalarNode('ip')->defaultNull()->end()
75 23
                ->end()
76 23
            ->end();
77
78 23
        return $treeBuilder;
79
    }
80
81
    /**
82
     * @return ArrayNodeDefinition
83
     */
84 23
    private function getProvidersNode()
85
    {
86 23
        $treeBuilder = new TreeBuilder();
87 23
        $node = $treeBuilder->root('providers');
88
89
        $node
0 ignored issues
show
Bug introduced by
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...
90 23
            ->requiresAtLeastOneElement()
91 23
            ->useAttributeAsKey('name')
92 23
            ->prototype('array')
93 23
                ->children()
94 23
                    ->scalarNode('factory')->isRequired()->cannotBeEmpty()->end()
95 23
                    ->variableNode('options')->defaultValue([])->end()
96 23
                    ->scalarNode('cache')->defaultNull()->end()
97 23
                    ->scalarNode('cache_lifetime')->defaultNull()->end()
98 23
                    ->scalarNode('limit')->defaultNull()->end()
99 23
                    ->scalarNode('locale')->defaultNull()->end()
100 23
                    ->scalarNode('logger')->defaultNull()->end()
101 23
                    ->arrayNode('aliases')
102 23
                        ->prototype('scalar')->end()
103 23
                    ->end()
104 23
                    ->append($this->createClientPluginNode())
105 23
                ->end()
106 23
            ->end();
107
108 23
        return $node;
109
    }
110
111
    /**
112
     * Create plugin node of a client.
113
     *
114
     * @return ArrayNodeDefinition The plugin node
115
     */
116 23
    private function createClientPluginNode()
117
    {
118 23
        $builder = new TreeBuilder();
119 23
        $node = $builder->root('plugins');
120
121
        /** @var ArrayNodeDefinition $pluginList */
122
        $pluginList = $node
123 23
            ->info('A list of plugin service ids. The order is important.')
124 23
            ->prototype('array')
125
        ;
126
        $pluginList
127
            // support having just a service id in the list
128 23
            ->beforeNormalization()
129 23
                ->always(function ($plugin) {
130
                    if (is_string($plugin)) {
131
                        return [
132
                            'reference' => [
133
                                'enabled' => true,
134
                                'id' => $plugin,
135
                            ],
136
                        ];
137
                    }
138
139
                    return $plugin;
140 23
                })
141 23
            ->end()
142
        ;
143
144
        $pluginList
145 23
            ->children()
146 23
                ->arrayNode('reference')
147 23
                    ->canBeEnabled()
148 23
                    ->info('Reference to a plugin service')
149 23
                    ->children()
150 23
                        ->scalarNode('id')
151 23
                            ->info('Service id of a plugin')
152 23
                            ->isRequired()
153 23
                            ->cannotBeEmpty()
154 23
                        ->end()
155 23
                    ->end()
156 23
                ->end()
157 23
            ->end()
158 23
        ->end();
159
160 23
        return $node;
161
    }
162
}
163