Completed
Push — master ( eef2d6...f1adda )
by Keith
03:34
created

Configuration::getQueuesNode()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 78
Code Lines 73

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 72
CRAP Score 1

Importance

Changes 7
Bugs 1 Features 3
Metric Value
c 7
b 1
f 3
dl 0
loc 78
ccs 72
cts 72
cp 1
rs 8.902
cc 1
eloc 73
nc 1
nop 0
crap 1

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
/**
4
 * Copyright 2014 Underground Elephant
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 *
18
 * @package     qpush-bundle
19
 * @copyright   Underground Elephant 2014
20
 * @license     Apache License, Version 2.0
21
 */
22
23
namespace Uecode\Bundle\QPushBundle\DependencyInjection;
24
25
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
26
use Symfony\Component\Config\Definition\ConfigurationInterface;
27
28
/**
29
 * @author Keith Kirk <[email protected]>
30
 */
31
class Configuration implements ConfigurationInterface
32
{
33 1
    public function getConfigTreeBuilder()
34
    {
35 1
        $treeBuilder = new TreeBuilder();
36 1
        $rootNode    = $treeBuilder->root('uecode_qpush');
37
38
        $rootNode
39 1
            ->addDefaultsIfNotSet()
40 1
            ->children()
41 1
                ->scalarNode('cache_service')
42 1
                    ->defaultNull()
43 1
                ->end()
44 1
                ->booleanNode('logging_enabled')
45 1
                    ->defaultTrue()
46 1
                ->end()
47 1
                ->append($this->getProvidersNode())
48 1
                ->append($this->getQueuesNode())
49 1
            ->end()
50
        ;
51
52 1
        return $treeBuilder;
53
    }
54
55 1
    private function getProvidersNode()
56
    {
57 1
        $treeBuilder    = new TreeBuilder();
58 1
        $node           = $treeBuilder->root('providers');
59
        $requirements   = [
60 1
            'aws' => [],
61 1
            'ironmq' => ['token', 'project_id'],
62 1
            'sync' => [],
63 1
            'custom' => ['service'],
64 1
            'file' => ['path']
65 1
        ];
66
67
        $node
68 1
            ->useAttributeAsKey('name')
69 1
            ->prototype('array')
70 1
                ->treatNullLike([])
71 1
                ->children()
72 1
                    ->enumNode('driver')
73 1
                        ->isRequired()
74 1
                        ->values(array_keys($requirements))
75 1
                    ->end()
76
                    // IronMQ
77 1
                    ->scalarNode('token')->end()
78 1
                    ->scalarNode('project_id')->end()
79 1
                    ->scalarNode('service')->end()
80 1
                    ->enumNode('host')
81 1
                        ->defaultValue('mq-aws-eu-west-1-1')
82 1
                        ->values([
83 1
                            'mq-aws-eu-west-1-1',
84 1
                            'mq-aws-us-east-1-1',
85 1
                        ])
86 1
                    ->end()
87 1
                    ->scalarNode('port')
88 1
                        ->defaultValue('443')
89 1
                    ->end()
90 1
                    ->scalarNode('api_version')
91 1
                        ->defaultValue(3)
92 1
                    ->end()
93
                    // AWS
94 1
                    ->scalarNode('key')->end()
95 1
                    ->scalarNode('secret')->end()
96 1
                    ->scalarNode('region')
97 1
                        ->defaultValue('us-east-1')
98 1
                    ->end()
99
                    // File
100 1
                    ->scalarNode('path')->end()
101 1
                ->end()
102
103 1
                ->validate()
104 1
                ->always()
105
                ->then(function (array $provider) use ($node, $requirements) {
106 1
                    foreach ($requirements[$provider['driver']] as $requirement) {
107 1
                        if (empty($provider[$requirement])) {
108
                            throw new \InvalidArgumentException(
109
                                sprintf('%s queue providers must have a %s; none provided', $provider['driver'], $requirement)
110
                            );
111
                        }
112 1
                    }
113
114 1
                    return $provider;
115 1
                })
116 1
            ->end()
117
        ;
118
119 1
        return $node;
120
    }
121
122 1
    private function getQueuesNode()
123
    {
124 1
        $treeBuilder = new TreeBuilder();
125 1
        $node        = $treeBuilder->root('queues');
126
127
        $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...
128 1
            ->requiresAtLeastOneElement()
129 1
            ->useAttributeAsKey('name')
130 1
            ->prototype('array')
131 1
                ->children()
132 1
                    ->scalarNode('provider')
133 1
                        ->isRequired()
134 1
                        ->info('The Queue Provider to use')
135 1
                    ->end()
136 1
                    ->arrayNode('options')
137 1
                        ->children()
138 1
                            ->scalarNode('queue_name')
139 1
                                ->defaultNull()
140 1
                                ->info('The actual name of the queue')
141 1
                            ->end()
142 1
                            ->booleanNode('push_notifications')
143 1
                                ->defaultFalse()
144 1
                                ->info('Whether notifications are sent to the subscribers')
145 1
                            ->end()
146 1
                            ->scalarNode('push_type')
147 1
                                ->defaultValue('multicast')
148 1
                                ->info('Whether the push queue is multicast or unicast')
149 1
                                ->example('unicast')
150 1
                            ->end()
151 1
                            ->scalarNode('notification_retries')
152 1
                                ->defaultValue(3)
153 1
                                ->info('How many attempts the Push Notifications are retried if the Subscriber returns an error')
154 1
                                ->example(3)
155 1
                            ->end()
156 1
                            ->scalarNode('notification_retries_delay')
157 1
                                ->defaultValue(60)
158 1
                                ->info('Delay between each Push Notification retry in seconds')
159 1
                                ->example(3)
160 1
                                ->end()
161 1
                            ->scalarNode('message_delay')
162 1
                                ->defaultValue(0)
163 1
                                ->info('How many seconds before messages are inititally visible in the Queue')
164 1
                                ->example(0)
165 1
                            ->end()
166 1
                            ->scalarNode('message_timeout')
167 1
                                ->defaultValue(30)
168 1
                                ->info('How many seconds the Queue hides a message while its being processed')
169 1
                                ->example(30)
170 1
                            ->end()
171 1
                            ->scalarNode('message_expiration')
172 1
                                ->defaultValue(604800)
173 1
                                ->info('How many seconds a message is kept in Queue, the default is 7 days (604800 seconds)')
174 1
                                ->example(604800)
175 1
                            ->end()
176 1
                            ->scalarNode('messages_to_receive')
177 1
                                ->defaultValue(1)
178 1
                                ->info('Max amount of messages to receive at once - an event will be fired for each individually')
179 1
                                ->example(1)
180 1
                            ->end()
181 1
                            ->scalarNode('receive_wait_time')
182 1
                                ->defaultValue(0)
183 1
                                ->info('How many seconds to Long Poll when requesting messages - if supported')
184 1
                                ->example(3)
185 1
                            ->end()
186 1
                            ->scalarNode('rate_limit')
187 1
                                ->defaultValue(-1)
188 1
                                ->info('How many push requests per second will be triggered. -1 for unlimited, 0 disables push')
189 1
                                ->example(1)
190 1
                            ->end()
191 1
                            ->append($this->getSubscribersNode())
192 1
                        ->end()
193 1
                    ->end()
194 1
                ->end()
195 1
            ->end()
196
        ;
197
198 1
        return $node;
199
    }
200
201 1
    private function getSubscribersNode()
202
    {
203 1
        $treeBuilder = new TreeBuilder();
204 1
        $node        = $treeBuilder->root('subscribers');
205
206
        $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...
207 1
            ->prototype('array')
208 1
                ->children()
209 1
                    ->scalarNode('endpoint')
210 1
                        ->info('The url or email address to notify')
211 1
                        ->example('http://foo.bar/qpush/')
212 1
                    ->end()
213 1
                    ->enumNode('protocol')
214 1
                        ->values(['email', 'http', 'https'])
215 1
                        ->info('The endpoint type')
216 1
                        ->example('http')
217 1
                    ->end()
218 1
                ->end()
219 1
            ->end()
220
        ;
221
222 1
        return $node;
223
    }
224
}
225