Completed
Pull Request — master (#20)
by Kevin
03:55
created

Configuration   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Test Coverage

Coverage 0%
Metric Value
wmc 3
lcom 0
cbo 3
dl 0
loc 94
ccs 0
cts 58
cp 0
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getConfigTreeBuilder() 0 19 1
B addApnsClientsNode() 0 29 1
B addGcmClientsNode() 0 28 1
1
<?php
2
3
namespace LinkValue\JarvisBundle\DependencyInjection;
4
5
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
6
use Symfony\Component\Config\Definition\ConfigurationInterface;
7
8
/**
9
 * This is the class that validates and merges configuration from app/config files.
10
 */
11
class Configuration implements ConfigurationInterface
12
{
13
    /**
14
     * {@inheritdoc}
15
     */
16
    public function getConfigTreeBuilder()
17
    {
18
        $treeBuilder = new TreeBuilder();
19
        $rootNode = $treeBuilder->root('link_value_mobile_notif');
20
21
        $rootNode
22
            ->children()
23
                ->arrayNode('clients')
24
                    ->isRequired()
25
                    ->children()
26
                        ->append($this->addApnsClientsNode())
27
                        ->append($this->addGcmClientsNode())
28
                    ->end()
29
                ->end()
30
            ->end()
31
        ;
32
33
        return $treeBuilder;
34
    }
35
36
    /**
37
     * Add APNS clients node.
38
     *
39
     * @return \Symfony\Component\Config\Definition\Builder\NodeDefinition
40
     */
41
    private function addApnsClientsNode()
42
    {
43
        $builder = new TreeBuilder();
44
        $node = $builder->root('apns');
45
46
        $node
47
            ->useAttributeAsKey('name')
48
            ->prototype('array')
49
                ->children()
50
                    ->arrayNode('services')
51
                        ->addDefaultsIfNotSet()
52
                        ->children()
53
                            ->scalarNode('logger')->defaultValue('logger')->end()
54
                            ->scalarNode('profiler')->defaultValue('link_value_mobile_notif.profiler.client_profiler')->end()
55
                        ->end()
56
                    ->end()
57
                    ->arrayNode('params')
58
                        ->children()
59
                            ->scalarNode('endpoint')->cannotBeEmpty()->defaultValue('tls://gateway.sandbox.push.apple.com:2195')->end()
60
                            ->scalarNode('ssl_pem_path')->cannotBeEmpty()->isRequired()->end()
61
                            ->scalarNode('ssl_passphrase')->cannotBeEmpty()->end()
62
                        ->end()
63
                    ->end()
64
                ->end()
65
            ->end()
66
        ;
67
68
        return $node;
69
    }
70
71
    /**
72
     * Add Google Cloud Messaging clients node.
73
     *
74
     * @return \Symfony\Component\Config\Definition\Builder\NodeDefinition
75
     */
76
    private function addGcmClientsNode()
77
    {
78
        $builder = new TreeBuilder();
79
        $node = $builder->root('gcm');
80
81
        $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...
82
            ->useAttributeAsKey('name')
83
            ->prototype('array')
84
                ->children()
85
                    ->arrayNode('services')
86
                        ->addDefaultsIfNotSet()
87
                        ->children()
88
                            ->scalarNode('logger')->defaultValue('logger')->end()
89
                            ->scalarNode('profiler')->defaultValue('link_value_mobile_notif.profiler.client_profiler')->end()
90
                        ->end()
91
                    ->end()
92
                    ->arrayNode('params')
93
                        ->children()
94
                            ->scalarNode('endpoint')->cannotBeEmpty()->defaultValue('https://android.googleapis.com/gcm/send')->end()
95
                            ->scalarNode('api_access_key')->cannotBeEmpty()->isRequired()->end()
96
                        ->end()
97
                    ->end()
98
                ->end()
99
            ->end()
100
        ;
101
102
        return $node;
103
    }
104
}
105