Completed
Pull Request — master (#277)
by Enrico
10:51
created

Configuration   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 115
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 91.67%

Importance

Changes 0
Metric Value
dl 0
loc 115
ccs 44
cts 48
cp 0.9167
rs 10
c 0
b 0
f 0
wmc 7
lcom 1
cbo 4

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
B getConfigTreeBuilder() 0 43 2
A setValue() 0 4 1
A getValue() 0 8 2
A valueIsTrue() 0 4 1
1
<?php
2
/**
3
 * @author Patsura Dmitry https://github.com/ovr <[email protected]>
4
 */
5
6
namespace PHPSA;
7
8
use PhpParser\ParserFactory;
9
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
10
use Symfony\Component\Config\Definition\ConfigurationInterface;
11
use Symfony\Component\Config\Definition\Processor;
12
13
/**
14
 * PHPSA configuration
15
 */
16
class Configuration implements ConfigurationInterface
17
{
18
    /**
19
     * @var array
20
     */
21
    protected $configuration;
22
23
    /**
24
     * Create a configuration from array.
25
     *
26
     * @param array $configuration
27
     * @param array $analyzersConfiguration
28
     */
29 882
    public function __construct(array $configuration = [], array $analyzersConfiguration = [])
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $analyzersConfiguration exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
30
    {
31 882
        $processor = new Processor();
32
33 882
        $configTree = $this->getConfigTreeBuilder($analyzersConfiguration);
34
35 882
        $this->configuration = $processor->process(
36 882
            $configTree->buildTree(),
37
            $configuration
38 882
        );
39 882
    }
40
41
    /**
42
     * Generates the configuration tree.
43
     *
44
     * @param array $analyzersConfiguration
45
     *
46
     * @return TreeBuilder
47
     */
48 882
    public function getConfigTreeBuilder(array $analyzersConfiguration = [])
0 ignored issues
show
Comprehensibility Naming introduced by
The variable name $analyzersConfiguration exceeds the maximum configured length of 20.

Very long variable names usually make code harder to read. It is therefore recommended not to make variable names too verbose.

Loading history...
49
    {
50 882
        $treeBuilder = new TreeBuilder();
51 882
        $root = $treeBuilder->root('phpsa');
52
53
        $root
54 882
            ->children()
55 882
                ->booleanNode('blame')->defaultFalse()->end()
56 882
                ->scalarNode('language_level')
57 882
                    ->defaultValue(PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION)
58 882
                    ->attribute('example', '5.3')
59 882
                    ->attribute('info', 'Will be used to automatically disable the analyzers that require a greater version of PHP.')
60 882
                ->end()
61 882
                ->enumNode('parser')
62 882
                    ->defaultValue('prefer-7')
63 882
                    ->attribute('label', 'Check types of Arguments.')
64 882
                    ->values([
65 882
                        ParserFactory::PREFER_PHP7 => 'prefer-7',
66 882
                        ParserFactory::PREFER_PHP5 => 'prefer-5',
67 882
                        ParserFactory::ONLY_PHP7 => 'only-7',
68 882
                        ParserFactory::ONLY_PHP5 => 'only-5'
69 882
                    ])
70 882
                ->end()
71 882
            ->end()
72
        ;
73
74
        $analyzersConfigRoot = $root
75 882
            ->children()
76 882
                ->arrayNode('analyzers')
77 882
                ->addDefaultsIfNotSet();
78
79 882
        $language_error = (new TreeBuilder())->root('language_error')
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 canBeDisabled() 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...
80 882
            ->info("Contains all compiler notices. Those are raised when PHP with strict error reporting would create at least a Notice message. (mostly experimental)")
81 882
            ->canBeDisabled();
82
83 882
        $analyzersConfigRoot->append($language_error);
84
85 882
        foreach ($analyzersConfiguration as $config) {
86 48
            $analyzersConfigRoot->append($config);
87 882
        }
88
89 882
        return $treeBuilder;
90
    }
91
92
    /**
93
     * Sets a configuration setting.
94
     *
95
     * @param string $key
96
     * @param string $value
97
     */
98
    public function setValue($key, $value)
99
    {
100
        $this->configuration[$key] = $value;
101
    }
102
103
    /**
104
     * Gets a configuration setting.
105
     *
106
     * @param string $key
107
     * @param mixed $default
108
     *
109
     * @return mixed
110
     */
111 48
    public function getValue($key, $default = null)
112
    {
113 48
        if (array_key_exists($key, $this->configuration)) {
114 48
            return $this->configuration[$key];
115
        }
116
117
        return $default;
118
    }
119
120
    /**
121
     * Checks if a configuration setting is set.
122
     *
123
     * @param string $key
124
     * @return bool
125
     */
126 48
    public function valueIsTrue($key)
127
    {
128 48
        return (bool) $this->configuration[$key];
129
    }
130
}
131