Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Pull Request — 0.11 (#398)
by Jérémiah
17:35
created

TypesConfiguration::getConfigTreeBuilder()   C

Complexity

Conditions 8
Paths 1

Size

Total Lines 96

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 67
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 96
ccs 67
cts 67
cp 1
rs 6.8428
c 0
b 0
f 0
cc 8
nc 1
nop 0
crap 8

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Overblog\GraphQLBundle\DependencyInjection;
4
5
use Overblog\GraphQLBundle\Config;
6
use Overblog\GraphQLBundle\Config\Processor\InheritanceProcessor;
7
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
8
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
9
use Symfony\Component\Config\Definition\ConfigurationInterface;
10
11
class TypesConfiguration implements ConfigurationInterface
12
{
13
    private static $types = [
14
        'object',
15
        'enum',
16
        'interface',
17
        'union',
18
        'input-object',
19
        'custom-scalar',
20
    ];
21
22 37
    public function getConfigTreeBuilder()
23
    {
24 37
        $treeBuilder = new TreeBuilder();
25 37
        $rootNode = $treeBuilder->root('overblog_graphql_types');
26
27 37
        $configTypeKeys = \array_map(
28
            function ($type) {
29 37
                return $this->normalizedConfigTypeKey($type);
30 37
            },
31 37
            self::$types
32
        );
33
34 37
        $this->addBeforeNormalization($rootNode);
35
36
        $rootNode
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...
37 37
            ->useAttributeAsKey('name')
38 37
            ->prototype('array')
39
                // config is the unique config entry allowed
40 37
                ->beforeNormalization()
41
                    ->ifTrue(function ($v) use ($configTypeKeys) {
42 37
                        if (!empty($v) && \is_array($v)) {
43 37
                            $keys = \array_keys($v);
44 37
                            foreach ($configTypeKeys as $configTypeKey) {
45 37
                                if (\in_array($configTypeKey, $keys)) {
46 37
                                    return true;
47
                                }
48
                            }
49
                        }
50
51 32
                        return  false;
52 37
                    })
53 37
                        ->thenInvalid(
54 37
                            \sprintf(
55 37
                                'Don\'t use internal config keys %s, replace it by "config" instead.',
56 37
                                \implode(', ', $configTypeKeys)
57
                            )
58
                        )
59 37
                ->end()
60
                // config is renamed _{TYPE}_config
61 37
                ->beforeNormalization()
62
                    ->ifTrue(function ($v) {
63 32
                        return isset($v['type']) && \is_string($v['type']);
64 37
                    })
65
                    ->then(function ($v) {
66 32
                        $key = $this->normalizedConfigTypeKey($v['type']);
67
68 32
                        if (empty($v[$key])) {
69 32
                            $v[$key] = isset($v['config']) ? $v['config'] : [];
70
                        }
71 32
                        unset($v['config']);
72
73 32
                        return $v;
74 37
                    })
75 37
                ->end()
76 37
                ->cannotBeOverwritten()
77 37
                ->children()
78 37
                    ->scalarNode('class_name')
79 37
                        ->isRequired()
80 37
                        ->validate()
81
                            ->ifTrue(function ($name) {
82 32
                                return !\preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $name);
83 37
                            })
84 37
                            ->thenInvalid('A valid class name starts with a letter or underscore, followed by any number of letters, numbers, or underscores.')
85 37
                        ->end()
86 37
                    ->end()
87 37
                    ->enumNode('type')->values(self::$types)->isRequired()->end()
88 37
                    ->arrayNode(InheritanceProcessor::INHERITS_KEY)
89 37
                        ->prototype('scalar')->info('Types to inherit of.')->end()
90 37
                    ->end()
91 37
                    ->booleanNode('decorator')->info('Decorator will not be generated.')->defaultFalse()->end()
92 37
                    ->append(Config\ObjectTypeDefinition::create()->getDefinition())
93 37
                    ->append(Config\EnumTypeDefinition::create()->getDefinition())
94 37
                    ->append(Config\InterfaceTypeDefinition::create()->getDefinition())
95 37
                    ->append(Config\UnionTypeDefinition::create()->getDefinition())
96 37
                    ->append(Config\InputObjectTypeDefinition::create()->getDefinition())
97 37
                    ->append(Config\CustomScalarTypeDefinition::create()->getDefinition())
98 37
                    ->variableNode('config')->end()
99 37
                ->end()
100
                // _{TYPE}_config is renamed config
101 37
                ->validate()
102
                    ->ifTrue(function ($v) {
103 32
                        return isset($v[$this->normalizedConfigTypeKey($v['type'])]);
104 37
                    })
105
                    ->then(function ($v) {
106 32
                        $key = $this->normalizedConfigTypeKey($v['type']);
107 32
                        $v['config'] = $v[$key];
108 32
                        unset($v[$key]);
109
110 32
                        return $v;
111 37
                    })
112 37
                ->end()
113
114 37
            ->end();
115
116 37
        return $treeBuilder;
117
    }
118
119 37
    private function addBeforeNormalization(ArrayNodeDefinition $node)
120
    {
121
        $node
122
            // process beforeNormalization (should be execute after relay normalization)
123 37
            ->beforeNormalization()
124
                ->ifTrue(function ($types) {
125 37
                    return \is_array($types);
126 37
                })
127
                ->then(function ($types) {
128 37
                    return Config\Processor::process($types, Config\Processor::BEFORE_NORMALIZATION);
129 37
                })
130 37
            ->end()
131
            ;
132 37
    }
133
134 37
    private function normalizedConfigTypeKey($type)
135
    {
136 37
        return '_'.\str_replace('-', '_', $type).'_config';
137
    }
138
}
139