Completed
Push — master ( 9f4c87...8a0b06 )
by Karel
07:12
created

Configuration::getTypesNode()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 54
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 38
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 54
ccs 38
cts 38
cp 1
rs 9.6716
cc 3
eloc 42
nc 1
nop 0
crap 3

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 FOS\ElasticaBundle\DependencyInjection;
4
5
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
6
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
7
use Symfony\Component\Config\Definition\ConfigurationInterface;
8
9
class Configuration implements ConfigurationInterface
10
{
11
    /**
12
     * Stores supported database drivers.
13
     *
14
     * @var array
15
     */
16
    private $supportedDrivers = array('orm', 'mongodb', 'propel', 'phpcr');
17
18
    /**
19
     * If the kernel is running in debug mode.
20
     *
21
     * @var bool
22
     */
23
    private $debug;
24
25 28
    public function __construct($debug)
26
    {
27 28
        $this->debug = $debug;
28 28
    }
29
30
    /**
31
     * Generates the configuration tree.
32
     *
33
     * @return TreeBuilder
34
     */
35 28
    public function getConfigTreeBuilder()
36
    {
37 28
        $treeBuilder = new TreeBuilder();
38 28
        $rootNode = $treeBuilder->root('fos_elastica', 'array');
39
40 28
        $this->addClientsSection($rootNode);
41 28
        $this->addIndexesSection($rootNode);
42
43
        $rootNode
44 28
            ->children()
45 28
                ->scalarNode('default_client')
46 28
                    ->info('Defaults to the first client defined')
47 28
                ->end()
48 28
                ->scalarNode('default_index')
49 28
                    ->info('Defaults to the first index defined')
50 28
                ->end()
51 28
                ->scalarNode('default_manager')->defaultValue('orm')->end()
52 28
                ->arrayNode('serializer')
53 28
                    ->treatNullLike(array())
54 28
                    ->children()
55 28
                        ->scalarNode('callback_class')->defaultValue('FOS\ElasticaBundle\Serializer\Callback')->end()
56 28
                        ->scalarNode('serializer')->defaultValue('serializer')->end()
57 28
                    ->end()
58 28
                ->end()
59 28
            ->end()
60
        ;
61
62 28
        return $treeBuilder;
63
    }
64
65
    /**
66
     * Adds the configuration for the "clients" key.
67
     */
68 28
    private function addClientsSection(ArrayNodeDefinition $rootNode)
69
    {
70
        $rootNode
71 28
            ->fixXmlConfig('client')
72 28
            ->children()
73 28
                ->arrayNode('clients')
74 28
                    ->useAttributeAsKey('id')
75 28
                    ->prototype('array')
76 28
                        ->performNoDeepMerging()
77
                        // Elastica names its properties with camel case, support both
78 28
                        ->beforeNormalization()
79
                        ->ifTrue(function ($v) { return isset($v['connection_strategy']); })
80
                        ->then(function ($v) {
81 4
                            $v['connectionStrategy'] = $v['connection_strategy'];
82 4
                            unset($v['connection_strategy']);
83
84 4
                            return $v;
85 28
                        })
86 28
                        ->end()
87
                        // If there is no connections array key defined, assume a single connection.
88 28
                        ->beforeNormalization()
89
                        ->ifTrue(function ($v) { return is_array($v) && !array_key_exists('connections', $v); })
90
                        ->then(function ($v) {
91
                            return array(
92 27
                                'connections' => array($v),
93
                            );
94 28
                        })
95 28
                        ->end()
96 28
                        ->children()
97 28
                            ->arrayNode('connections')
98 28
                                ->requiresAtLeastOneElement()
99 28
                                ->prototype('array')
100 28
                                    ->fixXmlConfig('header')
101 28
                                    ->children()
102 28
                                        ->scalarNode('url')
103 28
                                            ->validate()
104
                                                ->ifTrue(function ($url) { return $url && substr($url, -1) !== '/'; })
105
                                                ->then(function ($url) { return $url.'/'; })
106 28
                                            ->end()
107 28
                                        ->end()
108 28
                                        ->scalarNode('host')->end()
109 28
                                        ->scalarNode('port')->end()
110 28
                                        ->scalarNode('proxy')->end()
111 28
                                        ->scalarNode('aws_access_key_id')->end()
112 28
                                        ->scalarNode('aws_secret_access_key')->end()
113 28
                                        ->scalarNode('aws_region')->end()
114 28
                                        ->scalarNode('aws_session_token')->end()
115 28
                                        ->scalarNode('logger')
116 28
                                            ->defaultValue($this->debug ? 'fos_elastica.logger' : false)
117 28
                                            ->treatNullLike('fos_elastica.logger')
118 28
                                            ->treatTrueLike('fos_elastica.logger')
119 28
                                        ->end()
120 28
                                        ->booleanNode('compression')->defaultValue(false)->end()
121 28
                                        ->arrayNode('headers')
122 28
                                            ->useAttributeAsKey('name')
123 28
                                            ->prototype('scalar')->end()
124 28
                                        ->end()
125 28
                                        ->arrayNode('curl')
126 28
                                            ->useAttributeAsKey(CURLOPT_SSL_VERIFYPEER)
127 28
                                            ->prototype('boolean')->end()
128 28
                                        ->end()
129 28
                                        ->scalarNode('transport')->end()
130 28
                                        ->scalarNode('timeout')->end()
131 28
                                        ->scalarNode('connectTimeout')->end()
132 28
                                        ->scalarNode('retryOnConflict')
133 28
                                            ->defaultValue(0)
134 28
                                        ->end()
135 28
                                    ->end()
136 28
                                ->end()
137 28
                            ->end()
138 28
                            ->scalarNode('timeout')->end()
139 28
                            ->scalarNode('connectTimeout')->end()
140 28
                            ->scalarNode('headers')->end()
141 28
                            ->scalarNode('connectionStrategy')->defaultValue('Simple')->end()
142 28
                        ->end()
143 28
                    ->end()
144 28
                ->end()
145 28
            ->end()
146
        ;
147 28
    }
148
149
    /**
150
     * Adds the configuration for the "indexes" key.
151
     */
152 28
    private function addIndexesSection(ArrayNodeDefinition $rootNode)
153
    {
154
        $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...
155 28
            ->fixXmlConfig('index')
156 28
            ->children()
157 28
                ->arrayNode('indexes')
158 28
                    ->useAttributeAsKey('name')
159 28
                    ->prototype('array')
160 28
                        ->children()
161 28
                            ->scalarNode('index_name')
162 28
                                ->info('Defaults to the name of the index, but can be modified if the index name is different in ElasticSearch')
163 28
                            ->end()
164 28
                            ->booleanNode('use_alias')->defaultValue(false)->end()
165 28
                            ->scalarNode('client')->end()
166 28
                            ->scalarNode('finder')
167 28
                                ->treatNullLike(true)
168 28
                                ->defaultFalse()
169 28
                            ->end()
170 28
                            ->arrayNode('type_prototype')
171 28
                                ->children()
172 28
                                    ->scalarNode('analyzer')->end()
173 28
                                    ->append($this->getPersistenceNode())
174 28
                                    ->append($this->getSerializerNode())
175 28
                                ->end()
176 28
                            ->end()
177 28
                            ->variableNode('settings')->defaultValue(array())->end()
178 28
                        ->end()
179 28
                        ->append($this->getTypesNode())
180 28
                    ->end()
181 28
                ->end()
182 28
            ->end()
183
        ;
184 28
    }
185
186
    /**
187
     * Returns the array node used for "types".
188
     */
189 28
    protected function getTypesNode()
190
    {
191 28
        $builder = new TreeBuilder();
192 28
        $node = $builder->root('types');
193
194
        $node
195 28
            ->useAttributeAsKey('name')
196 28
            ->prototype('array')
197 28
                ->treatNullLike(array())
198 28
                ->beforeNormalization()
199 28
                ->ifNull()
200 28
                    ->thenEmptyArray()
201 28
                ->end()
202
                // Support multiple dynamic_template formats to match the old bundle style
203
                // and the way ElasticSearch expects them
204 28
                ->beforeNormalization()
205
                ->ifTrue(function ($v) { return isset($v['dynamic_templates']); })
206
                ->then(function ($v) {
207 4
                    $dt = array();
208 4
                    foreach ($v['dynamic_templates'] as $key => $type) {
209 4
                        if (is_int($key)) {
210
                            $dt[] = $type;
211
                        } else {
212 4
                            $dt[][$key] = $type;
213
                        }
214
                    }
215
216 4
                    $v['dynamic_templates'] = $dt;
217
218 4
                    return $v;
219 28
                })
220 28
                ->end()
221 28
                ->children()
222 28
                    ->booleanNode('date_detection')->end()
223 28
                    ->arrayNode('dynamic_date_formats')->prototype('scalar')->end()->end()
224 28
                    ->scalarNode('analyzer')->end()
225 28
                    ->booleanNode('numeric_detection')->end()
226 28
                    ->scalarNode('dynamic')->end()
227 28
                    ->variableNode('indexable_callback')->end()
228 28
                    ->append($this->getPersistenceNode())
229 28
                    ->append($this->getSerializerNode())
230 28
                ->end()
231 28
                ->append($this->getIdNode())
232 28
                ->append($this->getPropertiesNode())
233 28
                ->append($this->getDynamicTemplateNode())
234 28
                ->append($this->getSourceNode())
235 28
                ->append($this->getRoutingNode())
236 28
                ->append($this->getParentNode())
237 28
                ->append($this->getAllNode())
238 28
            ->end()
239
        ;
240
241 28
        return $node;
242
    }
243
244
    /**
245
     * Returns the array node used for "properties".
246
     */
247 28
    protected function getPropertiesNode()
248
    {
249 28
        $builder = new TreeBuilder();
250 28
        $node = $builder->root('properties');
251
252
        $node
253 28
            ->useAttributeAsKey('name')
254 28
            ->prototype('variable')
255 28
                ->treatNullLike(array());
256
257 28
        return $node;
258
    }
259
260
    /**
261
     * Returns the array node used for "dynamic_templates".
262
     */
263 28
    public function getDynamicTemplateNode()
264
    {
265 28
        $builder = new TreeBuilder();
266 28
        $node = $builder->root('dynamic_templates');
267
268
        $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 prototype() 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...
269 28
            ->prototype('array')
270 28
                ->prototype('array')
271 28
                    ->children()
272 28
                        ->scalarNode('match')->end()
273 28
                        ->scalarNode('unmatch')->end()
274 28
                        ->scalarNode('match_mapping_type')->end()
275 28
                        ->scalarNode('path_match')->end()
276 28
                        ->scalarNode('path_unmatch')->end()
277 28
                        ->scalarNode('match_pattern')->end()
278 28
                        ->arrayNode('mapping')
279 28
                            ->prototype('variable')
280 28
                                ->treatNullLike(array())
281 28
                            ->end()
282 28
                        ->end()
283 28
                    ->end()
284 28
                ->end()
285 28
            ->end()
286
        ;
287
288 28
        return $node;
289
    }
290
291
    /**
292
     * Returns the array node used for "_id".
293
     */
294 28 View Code Duplication
    protected function getIdNode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
295
    {
296 28
        $builder = new TreeBuilder();
297 28
        $node = $builder->root('_id');
298
299
        $node
300 28
            ->children()
301 28
            ->scalarNode('path')->end()
302 28
            ->end()
303
        ;
304
305 28
        return $node;
306
    }
307
308
    /**
309
     * Returns the array node used for "_source".
310
     */
311 28
    protected function getSourceNode()
312
    {
313 28
        $builder = new TreeBuilder();
314 28
        $node = $builder->root('_source');
315
316
        $node
0 ignored issues
show
Bug introduced by
The method arrayNode() does not seem to exist on object<Symfony\Component...odeDefinitionInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
317 28
            ->children()
318 28
                ->arrayNode('excludes')
319 28
                    ->useAttributeAsKey('name')
320 28
                    ->prototype('scalar')->end()
321 28
                ->end()
322 28
                ->arrayNode('includes')
323 28
                    ->useAttributeAsKey('name')
324 28
                    ->prototype('scalar')->end()
325 28
                ->end()
326 28
                ->scalarNode('compress')->end()
327 28
                ->scalarNode('compress_threshold')->end()
328 28
                ->scalarNode('enabled')->defaultTrue()->end()
329 28
            ->end()
330
        ;
331
332 28
        return $node;
333
    }
334
335
    /**
336
     * Returns the array node used for "_routing".
337
     */
338 28 View Code Duplication
    protected function getRoutingNode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
339
    {
340 28
        $builder = new TreeBuilder();
341 28
        $node = $builder->root('_routing');
342
343
        $node
344 28
            ->children()
345 28
                ->scalarNode('required')->end()
346 28
                ->scalarNode('path')->end()
347 28
            ->end()
348
        ;
349
350 28
        return $node;
351
    }
352
353
    /**
354
     * Returns the array node used for "_parent".
355
     */
356 28
    protected function getParentNode()
357
    {
358 28
        $builder = new TreeBuilder();
359 28
        $node = $builder->root('_parent');
360
361
        $node
362 28
            ->children()
363 28
                ->scalarNode('type')->end()
364 28
                ->scalarNode('property')->defaultValue(null)->end()
365 28
                ->scalarNode('identifier')->defaultValue('id')->end()
366 28
            ->end()
367
        ;
368
369 28
        return $node;
370
    }
371
372
    /**
373
     * Returns the array node used for "_all".
374
     */
375 28
    protected function getAllNode()
376
    {
377 28
        $builder = new TreeBuilder();
378 28
        $node = $builder->root('_all');
379
380
        $node
381 28
            ->children()
382 28
            ->scalarNode('enabled')->defaultValue(true)->end()
383 28
            ->scalarNode('analyzer')->end()
384 28
            ->end()
385
        ;
386
387 28
        return $node;
388
    }
389
390
    /**
391
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
392
     */
393 28
    protected function getPersistenceNode()
394
    {
395 28
        $builder = new TreeBuilder();
396 28
        $node = $builder->root('persistence');
397
398
        $node
399 28
            ->validate()
400 View Code Duplication
                ->ifTrue(function ($v) { return isset($v['driver']) && 'propel' === $v['driver'] && isset($v['listener']); })
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...
401 28
                    ->thenInvalid('Propel doesn\'t support listeners')
402 View Code Duplication
                ->ifTrue(function ($v) { return isset($v['driver']) && 'propel' === $v['driver'] && isset($v['repository']); })
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...
403 28
                    ->thenInvalid('Propel doesn\'t support the "repository" parameter')
404
                ->ifTrue(function($v) { return isset($v['driver']) && 'orm' !== $v['driver'] && !empty($v['elastica_to_model_transformer']['hints']); })
405 28
                    ->thenInvalid('Hints are only supported by the "orm" driver')
406 28
            ->end()
407 28
            ->children()
408 28
                ->scalarNode('driver')
409 28
                    ->defaultValue('orm')
410 28
                    ->validate()
411 28
                    ->ifNotInArray($this->supportedDrivers)
412 28
                        ->thenInvalid('The driver %s is not supported. Please choose one of '.json_encode($this->supportedDrivers))
413 28
                    ->end()
414 28
                ->end()
415 28
                ->scalarNode('model')->defaultValue(null)->end()
416 28
                ->scalarNode('repository')->end()
417 28
                ->scalarNode('identifier')->defaultValue('id')->end()
418 28
                ->arrayNode('provider')
419 28
                    ->addDefaultsIfNotSet()
420 28
                    ->children()
421 28
                        ->scalarNode('batch_size')->defaultValue(100)->end()
422 28
                        ->scalarNode('clear_object_manager')->defaultTrue()->end()
423 28
                        ->scalarNode('debug_logging')
424 28
                            ->defaultValue($this->debug)
425 28
                            ->treatNullLike(true)
426 28
                        ->end()
427 28
                        ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end()
428 28
                        ->scalarNode('service')->end()
429 28
                    ->end()
430 28
                ->end()
431 28
                ->arrayNode('listener')
432 28
                    ->addDefaultsIfNotSet()
433 28
                    ->children()
434 28
                        ->scalarNode('insert')->defaultTrue()->end()
435 28
                        ->scalarNode('update')->defaultTrue()->end()
436 28
                        ->scalarNode('delete')->defaultTrue()->end()
437 28
                        ->scalarNode('flush')->defaultTrue()->end()
438 28
                        ->booleanNode('defer')->defaultFalse()->end()
439 28
                        ->scalarNode('logger')
440 28
                            ->defaultFalse()
441 28
                            ->treatNullLike('fos_elastica.logger')
442 28
                            ->treatTrueLike('fos_elastica.logger')
443 28
                        ->end()
444 28
                        ->scalarNode('service')->end()
445 28
                    ->end()
446 28
                ->end()
447 28
                ->arrayNode('finder')
448 28
                    ->addDefaultsIfNotSet()
449 28
                    ->children()
450 28
                        ->scalarNode('service')->end()
451 28
                    ->end()
452 28
                ->end()
453 28
                ->arrayNode('elastica_to_model_transformer')
454 28
                    ->addDefaultsIfNotSet()
455 28
                    ->children()
456 28
                        ->arrayNode('hints')
457 28
                            ->prototype('array')
458 28
                                ->children()
459 28
                                    ->scalarNode('name')->end()
460 28
                                    ->scalarNode('value')->end()
461 28
                                ->end()
462 28
                            ->end()
463 28
                        ->end()
464 28
                        ->booleanNode('hydrate')->defaultTrue()->end()
465 28
                        ->booleanNode('ignore_missing')
466 28
                            ->defaultFalse()
467 28
                            ->info('Silently ignore results returned from Elasticsearch without corresponding persistent object.')
468 28
                        ->end()
469 28
                        ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end()
470 28
                        ->scalarNode('service')->end()
471 28
                    ->end()
472 28
                ->end()
473 28
                ->arrayNode('model_to_elastica_transformer')
474 28
                    ->addDefaultsIfNotSet()
475 28
                    ->children()
476 28
                        ->scalarNode('service')->end()
477 28
                    ->end()
478 28
                ->end()
479 28
                ->arrayNode('persister')
480 28
                    ->addDefaultsIfNotSet()
481 28
                    ->children()
482 28
                        ->scalarNode('service')->end()
483 28
                    ->end()
484 28
                ->end()
485 28
            ->end();
486
487 28
        return $node;
488
    }
489
490
    /**
491
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
492
     */
493 28
    protected function getSerializerNode()
494
    {
495 28
        $builder = new TreeBuilder();
496 28
        $node = $builder->root('serializer');
497
498
        $node
0 ignored issues
show
Bug introduced by
The method scalarNode() does not seem to exist on object<Symfony\Component...odeDefinitionInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
499 28
            ->addDefaultsIfNotSet()
500 28
            ->children()
501 28
                ->arrayNode('groups')
502 28
                    ->treatNullLike(array())
503 28
                    ->prototype('scalar')->end()
504 28
                ->end()
505 28
                ->scalarNode('version')->end()
506 28
                ->booleanNode('serialize_null')
507 28
                    ->defaultFalse()
508 28
                ->end()
509 28
            ->end();
510
511 28
        return $node;
512
    }
513
}
514