ConfigExpertConfiguration::addPolicies()   B
last analyzed

Complexity

Conditions 5
Paths 1

Size

Total Lines 78
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 78
rs 8.4316
cc 5
eloc 62
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
namespace Metfan\RabbitSetup\Configuration;
3
4
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
5
use Symfony\Component\Config\Definition\ConfigurationInterface;
6
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
7
8
9
/**
10
 * Declaration of configuration to validate and normalize config file
11
 *
12
 * @author Ulrich
13
 * @package Metfan\RabbitSetup\Configuration
14
 */
15
class ConfigExpertConfiguration implements ConfigurationInterface
16
{
17
    public function getConfigTreeBuilder()
18
    {
19
        $treeBuilder = new TreeBuilder();
20
        $rootNode = $treeBuilder->root('rabbit_setup');
21
22
        $rootNode
23
            ->validate()
24
                ->always()
25
                ->then(function($v){
26
                    /**
27
                     * ensure that connections are correctly declared between vhosts and connection
28
                     */
29
                    foreach ($v['vhosts'] as $name => $config) {
30
                        if (!isset($v['connections'][$config['connection']])) {
31
                            throw new InvalidTypeException(sprintf(
32
                                'Connection name "%s" for vhost %s have to be declared in "connections" section.',
33
                                $config['connection'],
34
                                $name
35
                            ));
36
                        }
37
                    }
38
39
                    return $v;
40
                })
41
            ->end()
42
            ->children()
43
                ->arrayNode('connections') #definition of connections
44
                    ->requiresAtLeastOneElement()
45
                    ->useAttributeAsKey('name') #use name as identifier
46
                    ->prototype('array')
47
                        ->children()
48
                            ->scalarNode('user')->defaultValue('guest')->end()
49
                            ->scalarNode('password')->defaultValue('guest')->end()
50
                            ->scalarNode('host')->defaultValue('127.0.0.1')->end()
51
                            ->scalarNode('port')->defaultValue(15672)->end()
52
                        ->end()
53
                    ->end()
54
                ->end()
55
                ->arrayNode('vhosts') # definition of vhosts
56
                    ->requiresAtLeastOneElement()
57
                    ->useAttributeAsKey('name')
58
                    ->prototype('array')
59
                        ->validate()
60
                            ->ifTrue(function($v){ return count($v['queues']) > 0;})
61
                            ->then(function($v) {
62
                                foreach ($v['queues'] as $name => $config) {
63
                                    if (isset($config['bindings'])) {
64
                                        foreach ($config['bindings'] as $binding) {
65
                                            if (!isset($v['exchanges'][$binding['exchange']])) {
66
                                                throw new InvalidTypeException(sprintf(
67
                                                    'Exchange "%s" use in binding of queue %s must be declared under exchanges key configuration.',
68
                                                    $binding['exchange'],
69
                                                    $name
70
                                                ));
71
                                            }
72
                                        }
73
                                    }
74
75
                                    if (isset($config['arguments'])
76
                                        && isset($config['arguments']['x-dead-letter-exchange'])
77
                                        && !isset($v['exchanges'][$config['arguments']['x-dead-letter-exchange']])) {
78
                                        throw new InvalidTypeException(sprintf(
79
                                            'Exchange "%s" use in x-dead-letter-exchange of queue %s must be declared under exchanges key configuration.',
80
                                            $config['arguments']['x-dead-letter-exchange'],
81
                                            $name
82
                                        ));
83
                                    }
84
                                }
85
86
                                return $v;
87
                            })
88
                        ->end()
89
                        ->children()
90
                            ->scalarNode('connection')->isRequired()->cannotBeEmpty()->end() #connection to use
91
                            ->append($this->addParameters()) #add parameters definition
92
                            ->append($this->addPolicies()) #add policies definition
93
                            ->append($this->addExchanges()) #add exchanges definition
94
                            ->append($this->addQueues()) #add queues definition
95
                        ->end()
96
                    ->end()
97
                ->end()
98
            ->end();
99
100
        return $treeBuilder;
101
    }
102
103
    public function addParameters()
104
    {
105
        $treeBuilder = new TreeBuilder();
106
        $node = $treeBuilder->root('parameters');
107
108
        $node
109
            ->validate()
110
                ->ifTrue(function($v) {return isset($v['federation-upstream-set']);})
111
                ->then(function($v){
112
                    /**
113
                     * Verify all server name use in federation-upstream-set
114
                     * were declared in federation-upstream
115
                     */
116
                    foreach ($v['federation-upstream-set'] as $name => $federationSet) {
117
                        foreach ($federationSet as $config) {
118
                            if ('all' != $config['upstream']
119
                                && !array_key_exists($config['upstream'], $v['federation-upstream'])) {
120
                                throw new InvalidTypeException(sprintf(
121
                                    'Unknown upstream server name: "%s" in upstream set: "%s".',
122
                                    $config['upstream'],
123
                                    $name));
124
                            }
125
                        }
126
                    }
127
                    return $v;
128
                })
129
            ->end()
130
131
132
            ->normalizeKeys(false) # don't transforme - into _
133
            ->children()
134
                ->arrayNode('federation-upstream')
135
                    ->useAttributeAsKey('name')
136
                    ->prototype('array')
137
                    ->normalizeKeys(false) # don't transforme - into _
138
                        ->children()
139
                            ->scalarNode('uri')
140
                                ->isRequired()
141
                                ->cannotBeEmpty()
142
                            ->end()
143
                            ->scalarNode('expires')
144
                                ->validate()
145
                                ->always()
146 View Code Duplication
                                    ->then(function($value){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
                                        if (!$value) {
148
                                            return null;
149
                                        } elseif (is_int($value)){
150
                                            return (int) $value;
151
                                        }
152
153
                                        throw new InvalidTypeException(sprintf(
154
                                            'Invalid value for path "expires". Expected integer or null, but got %s.',
155
                                            gettype($value)));
156
                                    })
157
                                ->end()
158
                                ->info('# in ms, leave blank mean forever')
159
                                ->defaultValue(null)
160
                            ->end()
161
                            ->scalarNode('message-ttl')
162
                                ->validate()
163
                                ->always()
164 View Code Duplication
                                    ->then(function($value){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
165
                                        if (!$value) {
166
                                            return null;
167
                                        } elseif (is_int($value)){
168
                                            return (int) $value;
169
                                        }
170
171
                                        throw new InvalidTypeException(sprintf(
172
                                            'Invalid value for path "expires". Expected integer or null, but got %s.',
173
                                            gettype($value)));
174
                                    })
175
                                ->end()
176
                                ->info('# in ms, leave blank mean forever')
177
                                ->defaultValue(null)
178
                            ->end()
179
                            ->integerNode('max-hops')
180
                                ->min(1)
181
                                ->defaultValue(1)
182
                            ->end()
183
                            ->integerNode('prefetch-count')
184
                                ->min(0)
185
                                ->defaultValue(1000)
186
                            ->end()
187
                            ->integerNode('reconnect-delay')
188
                                ->min(0)
189
                                ->info('# in s')
190
                                ->defaultValue(5)
191
                            ->end()
192
                            ->enumNode('ack-mode')
193
                                ->values(['on-confirm', 'on-publish', 'no-ack'])
194
                                ->defaultValue('on-confirm')
195
                            ->end()
196
                            ->booleanNode('trust-user-id')
197
                                ->treatNullLike(false)
198
                                ->defaultValue(false)
199
                            ->end()
200
                        ->end()
201
                    ->end()
202
                ->end()
203
                ->arrayNode('federation-upstream-set')
204
                    ->useAttributeAsKey('name')
205
                    ->prototype('array')
206
                        ->prototype('array')
207
                            ->children()
208
                                ->scalarNode('upstream')
209
                                ->end()
210
                            ->end()
211
                        ->end()
212
                    ->end()
213
                ->end()
214
            ->end();
215
216
        return $node;
217
    }
218
219
    public function addPolicies()
220
    {
221
        $treeBuilder = new TreeBuilder();
222
        $node = $treeBuilder->root('policies');
223
224
        $node
225
            ->validate()
226
                ->always()
227
                ->then(function($v) {
228
                    /**
229
                     * When applying policy to queues or exchanges some options can't be use
230
                     * depending of apply type.
231
                     */
232
                    foreach ($v as $policyName => $policy) {
233
                        $definitionsUsed = array_keys($policy['definition']);
234
                        $intersect = [];
235
                        if ('exchanges' == $policy['apply-to']) {
236
                            $forbid = [
237
                                'message-ttl',
238
                                'expires',
239
                                'max-length',
240
                                'max-length-bytes',
241
                                'dead-letter-exchange',
242
                                'dead-letter-routing-key'];
243
                            $intersect = array_intersect($definitionsUsed, $forbid);
244
                        } elseif ('queues' == $policy['apply-to']) {
245
                            $intersect = array_intersect($definitionsUsed, ['alternate-exchange']);
246
                        }
247
248
                        if (count($intersect) > 0) {
249
                            throw  new InvalidTypeException(sprintf(
250
                                'You can\'t use "%s" with %s in policy: %s',
251
                                implode(', ', $intersect),
252
                                $policy['apply-to'],
253
                                $policyName
254
                            ));
255
                        }
256
                    }
257
258
                    return $v;
259
                })
260
            ->end()
261
262
            ->useAttributeAsKey('name')
263
            ->prototype('array')
264
                ->normalizeKeys(false) # don't transforme - into _
265
                ->children()
266
                    ->scalarNode('pattern')
267
                        ->isRequired()
268
                        ->cannotBeEmpty()
269
                    ->end()
270
                    ->integerNode('priority')
271
                        ->defaultValue(0)
272
                    ->end()
273
                    ->enumNode('apply-to')
274
                        ->values(['exchanges', 'queues', 'all'])
275
                        ->defaultValue('all')
276
                    ->end()
277
                    ->arrayNode('definition')
278
                        ->isRequired()
279
                        ->normalizeKeys(false) # don't transforme - into _
280
                        ->children()
281
                            ->integerNode('message-ttl')->end()
282
                            ->integerNode('expires')->end()
283
                            ->integerNode('max-length')->end()
284
                            ->integerNode('max-length-bytes')->end()
285
                            ->scalarNode('alternate-exchange')->end()
286
                            ->scalarNode('dead-letter-exchange')->end()
287
                            ->scalarNode('dead-letter-routing-key')->end()
288
                            ->scalarNode('federation-upstream-set')->end()
289
                            ->scalarNode('federation-upstream')->end()
290
                        ->end()
291
                    ->end()
292
                ->end()
293
            ->end();
294
295
        return $node;
296
    }
297
298
    public function addExchanges()
299
    {
300
        $treeBuilder = new TreeBuilder();
301
        $node = $treeBuilder->root('exchanges');
302
303
        $node
304
            ->useAttributeAsKey('name')
305
            ->prototype('array')
306
                ->normalizeKeys(false) # don't transforme - into _
307
                ->children()
308
                    ->enumNode('type')
309
                        ->values(['topic', 'fanout', 'direct', 'headers'])
310
                        ->isRequired()
311
                    ->end()
312
                    ->booleanNode('durable')
313
                        ->defaultValue(true)
314
                    ->end()
315
                    ->booleanNode('auto-delete')
316
                        ->defaultValue(false)
317
                    ->end()
318
                    ->booleanNode('internal')
319
                        ->defaultValue(false)
320
                    ->end()
321
                    ->scalarNode('alternate-exchange')
322
                    ->end()
323
                ->end()
324
            ->end();
325
326
        return $node;
327
    }
328
329
    public function addQueues()
330
    {
331
        $treeBuilder = new TreeBuilder();
332
        $node = $treeBuilder->root('queues');
333
334
        $node
335
            ->useAttributeAsKey('name')
336
            ->prototype('array')
337
                ->normalizeKeys(false) # don't transforme - into _
338
                ->children()
339
                    ->booleanNode('durable')
340
                        ->defaultValue(true)
341
                    ->end()
342
                    ->booleanNode('auto-delete')
343
                        ->defaultValue(false)
344
                    ->end()
345
                    ->arrayNode('arguments')
346
                        ->normalizeKeys(false) # don't transforme - into _
347
                        ->children()
348
                            ->integerNode('x-message-ttl')->end()
349
                            ->integerNode('x-expires')->end()
350
                            ->integerNode('x-max-length')->end()
351
                            ->integerNode('x-max-length-bytes')->end()
352
                            ->integerNode('x-max-priority')->end()
353
                            ->scalarNode('x-dead-letter-exchange')->end()
354
                            ->scalarNode('x-dead-letter-routing-key')->end()
355
                        ->end()
356
                    ->end()
357
                    ->arrayNode('bindings')
358
                        ->prototype('array')
359
                                ->children()
360
                                    ->scalarNode('exchange')
361
                                        ->isRequired()
362
                                    ->end()
363
                                    ->scalarNode('routing_key')
364
                                        ->isRequired()
365
                                    ->end()
366
                                ->end()
367
                        ->end()
368
                    ->end()
369
                ->end()
370
            ->end();
371
372
        return $node;
373
    }
374
}
375