Configuration::getConfigTreeBuilder()   B
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 155

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 155
rs 8
c 0
b 0
f 0
cc 1
nc 1
nop 0

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
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\NotificationBundle\DependencyInjection;
15
16
use Enqueue\AmqpLib\AmqpConnectionFactory;
17
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
18
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
19
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
20
use Symfony\Component\Config\Definition\ConfigurationInterface;
21
22
class Configuration implements ConfigurationInterface
23
{
24
    /**
25
     * {@inheritdoc}
26
     */
27
    public function getConfigTreeBuilder()
28
    {
29
        $treeBuilder = new TreeBuilder('sonata_notification');
30
31
        $rootNode = $treeBuilder->getRootNode()->children();
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...
32
33
        $backendInfo = <<<'EOF'
34
Other backends you can use:
35
36
sonata.notification.backend.postpone
37
sonata.notification.backend.doctrine
38
sonata.notification.backend.rabbitmq
39
EOF;
40
41
        $iterationListenersInfo = <<<EOF
42
Listeners attached to the IterateEvent
43
Iterate event is thrown on each command iteration
44
45
Iteration listener class must implement Sonata\NotificationBundle\Event\IterationListener
46
EOF;
47
48
        $rootNode
49
            ->scalarNode('backend')
50
                ->info($backendInfo)
51
                ->defaultValue('sonata.notification.backend.runtime')
52
            ->end()
53
            ->append($this->getQueueNode())
54
            ->arrayNode('backends')
55
                ->children()
56
                    ->arrayNode('doctrine')
57
                        ->children()
58
                            ->scalarNode('message_manager')
59
                                ->defaultValue('sonata.notification.manager.message.default')
60
                            ->end()
61
                            ->scalarNode('max_age')
62
                                ->info('The max age in seconds')
63
                                ->defaultValue(86400)
64
                            ->end()
65
                            ->scalarNode('pause')
66
                                ->info('The delay in microseconds')
67
                                ->defaultValue(500000)
68
                            ->end()
69
                            ->scalarNode('batch_size')
70
                                ->info('The number of items on each iteration')
71
                                ->defaultValue(10)
72
                            ->end()
73
                            ->arrayNode('states')
74
                                ->info('Raising errors level')
75
                                ->addDefaultsIfNotSet()
76
                                ->children()
77
                                    ->integerNode('in_progress')
78
                                        ->defaultValue(10)
79
                                    ->end()
80
                                    ->integerNode('error')
81
                                        ->defaultValue(20)
82
                                    ->end()
83
                                    ->integerNode('open')
84
                                        ->defaultValue(100)
85
                                    ->end()
86
                                    ->integerNode('done')
87
                                        ->defaultValue(10000)
88
                                    ->end()
89
                                ->end()
90
                            ->end()
91
                        ->end()
92
                    ->end()
93
                    ->arrayNode('rabbitmq')
94
                        ->children()
95
                            ->scalarNode('exchange')
96
                                ->cannotBeEmpty()
97
                                ->isRequired()
98
                            ->end()
99
                            ->arrayNode('connection')
100
                                ->addDefaultsIfNotSet()
101
                                ->children()
102
                                    ->scalarNode('host')
103
                                        ->defaultValue('localhost')
104
                                    ->end()
105
                                    ->scalarNode('port')
106
                                        ->defaultValue(5672)
107
                                    ->end()
108
                                    ->scalarNode('user')
109
                                        ->defaultValue('guest')
110
                                    ->end()
111
                                    ->scalarNode('pass')
112
                                        ->defaultValue('guest')
113
                                    ->end()
114
                                    ->scalarNode('vhost')
115
                                        ->defaultValue('guest')
116
                                    ->end()
117
                                    ->scalarNode('console_url')
118
                                        ->defaultValue('http://localhost:55672/api')
119
                                    ->end()
120
                                    ->scalarNode('factory_class')
121
                                        ->cannotBeEmpty()
122
                                        ->defaultValue(AmqpConnectionFactory::class)
123
                                        ->info('This option defines an AMQP connection factory to be used to establish a connection with RabbitMQ.')
124
                                    ->end()
125
                                ->end()
126
                            ->end()
127
                        ->end()
128
                    ->end()
129
                ->end()
130
            ->end()
131
            ->arrayNode('consumers')
132
                ->addDefaultsIfNotSet()
133
                ->children()
134
                    ->booleanNode('register_default')
135
                        ->info('If set to true, SwiftMailerConsumer and LoggerConsumer will be registered as services')
136
                        ->defaultTrue()
137
                    ->end()
138
                ->end()
139
            ->end()
140
            ->arrayNode('iteration_listeners')
141
                ->info($iterationListenersInfo)
142
                ->defaultValue([])
143
                ->prototype('scalar')->end()
144
            ->end()
145
            ->arrayNode('class')
146
                ->addDefaultsIfNotSet()
147
                ->children()
148
                    ->scalarNode('message')
149
                        ->defaultValue('App\\Entity\\Message')
150
                    ->end()
151
                ->end()
152
            ->end()
153
            ->arrayNode('admin')
154
                ->addDefaultsIfNotSet()
155
                ->children()
156
                    ->booleanNode('enabled')
157
                        ->defaultFalse()
158
                    ->end()
159
                    ->arrayNode('message')
160
                        ->addDefaultsIfNotSet()
161
                        ->children()
162
                            ->scalarNode('class')
163
                                ->cannotBeEmpty()
164
                                ->defaultValue('Sonata\\NotificationBundle\\Admin\\MessageAdmin')
165
                            ->end()
166
                            ->scalarNode('controller')
167
                                ->cannotBeEmpty()
168
                                ->defaultValue('SonataNotificationBundle:MessageAdmin')
169
                            ->end()
170
                            ->scalarNode('translation')
171
                                ->cannotBeEmpty()
172
                                ->defaultValue('SonataNotificationBundle')
173
                            ->end()
174
                        ->end()
175
                    ->end()
176
                ->end()
177
            ->end()
178
        ;
179
180
        return $treeBuilder;
181
    }
182
183
    /**
184
     * @return ArrayNodeDefinition|NodeDefinition
185
     */
186
    protected function getQueueNode()
187
    {
188
        $treeBuilder = new TreeBuilder('queues');
189
190
        $node = $treeBuilder->getRootNode();
191
192
        $queuesInfo = <<<'EOF'
193
Example for using RabbitMQ
194
    - { queue: myQueue, recover: true, default: false, routing_key: the_routing_key, dead_letter_exchange: 'my.dead.letter.exchange' }
195
    - { queue: catchall, default: true }
196
197
Example for using Doctrine
198
    - { queue: sonata_page, types: [sonata.page.create_snapshot, sonata.page.create_snapshots] }
199
    - { queue: catchall, default: true }
200
EOF;
201
202
        $routingKeyInfo = <<<'EOF'
203
Only used by RabbitMQ
204
205
Direct exchange with routing_key
206
EOF;
207
208
        $recoverInfo = <<<'EOF'
209
Only used by RabbitMQ
210
211
If set to true, the consumer will respond with a `basic.recover` when an exception occurs,
212
otherwise it will not respond at all and the message will be unacknowledged
213
EOF;
214
215
        $deadLetterExchangeInfo = <<<'EOF'
216
Only used by RabbitMQ
217
218
If is set, failed messages will be rejected and sent to this exchange
219
EOF;
220
221
        $deadLetterRoutingKeyInfo = <<<'EOF'
222
Only used by RabbitMQ
223
224
If set, failed messages will be routed to the queue using this key by dead-letter-exchange,
225
otherwise it will be requeued to the original queue if `dead-letter-exchange` is set.
226
227
If set, the queue must be configured with this key as `routing_key`.
228
EOF;
229
230
        $ttlInfo = <<<'EOF'
231
Only used by RabbitMQ
232
233
Defines the per-queue message time-to-live (milliseconds)
234
EOF;
235
236
        $prefetchCountInfo = <<<'EOF'
237
Only used by RabbitMQ
238
239
Defines the number of messages which will be delivered to the customer at a time.
240
EOF;
241
242
        $typesInfo = <<<'EOF'
243
Only used by Doctrine
244
245
Defines types handled by the message backend
246
EOF;
247
248
        $connectionNode = $node
249
            ->info($queuesInfo)
250
            ->requiresAtLeastOneElement()
251
            ->prototype('array')
252
        ;
253
254
        $connectionNode
255
            ->children()
256
                ->scalarNode('queue')
257
                    ->info('The name of the queue')
258
                    ->cannotBeEmpty()
259
                    ->isRequired()
260
                ->end()
261
                ->booleanNode('default')
262
                    ->info('Set the name of the default queue')
263
                    ->defaultValue(false)
264
                ->end()
265
266
                // RabbitMQ configuration
267
                ->scalarNode('routing_key')
268
                    ->info($routingKeyInfo)
269
                    ->defaultValue('')
270
                ->end()
271
                ->booleanNode('recover')
272
                    ->info($recoverInfo)
273
                    ->defaultValue(false)
274
                ->end()
275
                ->scalarNode('dead_letter_exchange')
276
                    ->info($deadLetterExchangeInfo)
277
                    ->defaultValue(null)
278
                ->end()
279
                ->scalarNode('dead_letter_routing_key')
280
                    ->info($deadLetterRoutingKeyInfo)
281
                    ->defaultValue(null)
282
                ->end()
283
                ->integerNode('ttl')
284
                    ->info($ttlInfo)
285
                    ->min(0)
286
                    ->defaultValue(null)
287
                ->end()
288
                ->integerNode('prefetch_count')
289
                    ->info($prefetchCountInfo)
290
                    ->min(0)
291
                    ->max(65535)
292
                    ->defaultValue(null)
293
                ->end()
294
295
                // Database configuration (Doctrine)
296
                ->arrayNode('types')
297
                    ->info($typesInfo)
298
                    ->defaultValue([])
299
                    ->prototype('scalar')->end()
300
                ->end()
301
            ->end();
302
303
        return $node;
304
    }
305
}
306