Completed
Pull Request — master (#917)
by Dmitry
08:52
created

Configuration::getTtlNode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 11

Duplication

Lines 16
Ratio 100 %

Code Coverage

Tests 10
CRAP Score 1
Metric Value
dl 16
loc 16
ccs 10
cts 10
cp 1
rs 9.4285
cc 1
eloc 11
nc 1
nop 0
crap 1
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 27
    public function __construct($debug)
26
    {
27 27
        $this->debug = $debug;
28 27
    }
29
30
    /**
31
     * Generates the configuration tree.
32
     *
33
     * @return TreeBuilder
34
     */
35 27
    public function getConfigTreeBuilder()
36
    {
37 27
        $treeBuilder = new TreeBuilder();
38 27
        $rootNode = $treeBuilder->root('fos_elastica', 'array');
39
40 27
        $this->addClientsSection($rootNode);
41 27
        $this->addIndexesSection($rootNode);
42 27
        $this->addIndexTemplatesSection($rootNode);
43
44
        $rootNode
45 27
            ->children()
46 27
                ->scalarNode('default_client')
47 27
                    ->info('Defaults to the first client defined')
48 27
                ->end()
49 27
                ->scalarNode('default_index')
50 27
                    ->info('Defaults to the first index defined')
51 27
                ->end()
52 27
                ->scalarNode('default_manager')->defaultValue('orm')->end()
53 27
                ->arrayNode('serializer')
54 27
                    ->treatNullLike(array())
55 27
                    ->children()
56 27
                        ->scalarNode('callback_class')->defaultValue('FOS\ElasticaBundle\Serializer\Callback')->end()
57 27
                        ->scalarNode('serializer')->defaultValue('serializer')->end()
58 27
                    ->end()
59 27
                ->end()
60 27
            ->end()
61
        ;
62
63 27
        return $treeBuilder;
64
    }
65
66
    /**
67
     * Adds the configuration for the "clients" key.
68
     */
69 27
    private function addClientsSection(ArrayNodeDefinition $rootNode)
70
    {
71
        $rootNode
72 27
            ->fixXmlConfig('client')
73 27
            ->children()
74 27
                ->arrayNode('clients')
75 27
                    ->useAttributeAsKey('id')
76 27
                    ->prototype('array')
77 27
                        ->performNoDeepMerging()
78
                        // BC - Renaming 'servers' node to 'connections'
79 27
                        ->beforeNormalization()
80
                        ->ifTrue(function ($v) { return isset($v['servers']); })
81
                        ->then(function ($v) {
82
                            $v['connections'] = $v['servers'];
83
                            unset($v['servers']);
84
85
                            return $v;
86 27
                        })
87 27
                        ->end()
88
                        // Elastica names its properties with camel case, support both
89 27
                        ->beforeNormalization()
90
                        ->ifTrue(function ($v) { return isset($v['connection_strategy']); })
91
                        ->then(function ($v) {
92 4
                            $v['connectionStrategy'] = $v['connection_strategy'];
93 4
                            unset($v['connection_strategy']);
94
95 4
                            return $v;
96 27
                        })
97 27
                        ->end()
98
                        // If there is no connections array key defined, assume a single connection.
99 27
                        ->beforeNormalization()
100
                        ->ifTrue(function ($v) { return is_array($v) && !array_key_exists('connections', $v); })
101
                        ->then(function ($v) {
102
                            return array(
103 26
                                'connections' => array($v),
104
                            );
105 27
                        })
106 27
                        ->end()
107 27
                        ->children()
108 27
                            ->arrayNode('connections')
109 27
                                ->requiresAtLeastOneElement()
110 27
                                ->prototype('array')
111 27
                                    ->fixXmlConfig('header')
112 27
                                    ->children()
113 27
                                        ->scalarNode('url')
114 27
                                            ->validate()
115
                                                ->ifTrue(function ($url) { return $url && substr($url, -1) !== '/'; })
116
                                                ->then(function ($url) { return $url.'/'; })
117 27
                                            ->end()
118 27
                                        ->end()
119 27
                                        ->scalarNode('host')->end()
120 27
                                        ->scalarNode('port')->end()
121 27
                                        ->scalarNode('proxy')->end()
122 27
                                        ->scalarNode('logger')
123 27
                                            ->defaultValue($this->debug ? 'fos_elastica.logger' : false)
124 27
                                            ->treatNullLike('fos_elastica.logger')
125 27
                                            ->treatTrueLike('fos_elastica.logger')
126 27
                                        ->end()
127 27
                                        ->booleanNode('compression')->defaultValue(false)->end()
128 27
                                        ->arrayNode('headers')
129 27
                                            ->useAttributeAsKey('name')
130 27
                                            ->prototype('scalar')->end()
131 27
                                        ->end()
132 27
                                        ->scalarNode('transport')->end()
133 27
                                        ->scalarNode('timeout')->end()
134 27
                                        ->scalarNode('connectTimeout')->end()
135 27
                                        ->scalarNode('retryOnConflict')
136 27
                                            ->defaultValue(0)
137 27
                                        ->end()
138 27
                                    ->end()
139 27
                                ->end()
140 27
                            ->end()
141 27
                            ->scalarNode('timeout')->end()
142 27
                            ->scalarNode('connectTimeout')->end()
143 27
                            ->scalarNode('headers')->end()
144 27
                            ->scalarNode('connectionStrategy')->defaultValue('Simple')->end()
145 27
                        ->end()
146 27
                    ->end()
147 27
                ->end()
148 27
            ->end()
149
        ;
150 27
    }
151
152
    /**
153
     * Adds the configuration for the "indexes" key.
154
     */
155 27
    private function addIndexesSection(ArrayNodeDefinition $rootNode)
156
    {
157
        $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...
158 27
            ->fixXmlConfig('index')
159 27
            ->children()
160 27
                ->arrayNode('indexes')
161 27
                    ->useAttributeAsKey('name')
162 27
                    ->prototype('array')
163 27
                        ->children()
164 27
                            ->scalarNode('index_name')
165 27
                                ->info('Defaults to the name of the index, but can be modified if the index name is different in ElasticSearch')
166 27
                            ->end()
167 27
                            ->booleanNode('use_alias')->defaultValue(false)->end()
168 27
                            ->scalarNode('client')->end()
169 27
                            ->scalarNode('finder')
170 27
                                ->treatNullLike(true)
171 27
                                ->defaultFalse()
172 27
                            ->end()
173 27
                            ->arrayNode('type_prototype')
174 27
                                ->children()
175 27
                                    ->scalarNode('index_analyzer')->end()
176 27
                                    ->scalarNode('search_analyzer')->end()
177 27
                                    ->append($this->getPersistenceNode())
178 27
                                    ->append($this->getSerializerNode())
179 27
                                ->end()
180 27
                            ->end()
181 27
                            ->variableNode('settings')->defaultValue(array())->end()
182 27
                        ->end()
183 27
                        ->append($this->getTypesNode())
184 27
                    ->end()
185 27
                ->end()
186 27
            ->end()
187
        ;
188 27
    }
189
190
    /**
191
     * Returns the array node used for "types".
192
     */
193 27
    protected function getTypesNode()
194
    {
195 27
        $builder = new TreeBuilder();
196 27
        $node = $builder->root('types');
197
198
        $node
199 27
            ->useAttributeAsKey('name')
200 27
            ->prototype('array')
201 27
                ->treatNullLike(array())
202 27
                ->beforeNormalization()
203 27
                ->ifNull()
204 27
                ->thenEmptyArray()
205 27
                ->end()
206
                // BC - Renaming 'mappings' node to 'properties'
207 27
                ->beforeNormalization()
208
                ->ifTrue(function ($v) { return array_key_exists('mappings', $v); })
209
                ->then(function ($v) {
210 13
                    $v['properties'] = $v['mappings'];
211 13
                    unset($v['mappings']);
212
213 13
                    return $v;
214 27
                })
215 27
                ->end()
216
                // BC - Support the old is_indexable_callback property
217 27
                ->beforeNormalization()
218
                ->ifTrue(function ($v) {
219 19
                    return isset($v['persistence']) &&
220 19
                        isset($v['persistence']['listener']) &&
221 19
                        isset($v['persistence']['listener']['is_indexable_callback']);
222 27
                })
223
                ->then(function ($v) {
224 5
                    $callback = $v['persistence']['listener']['is_indexable_callback'];
225
226 5
                    if (is_array($callback)) {
227 5
                        list($class) = $callback + array(null);
228
229 5
                        if ($class[0] !== '@' && is_string($class) && !class_exists($class)) {
230
                            $callback[0] = '@'.$class;
231
                        }
232
                    }
233
234 5
                    $v['indexable_callback'] = $callback;
235 5
                    unset($v['persistence']['listener']['is_indexable_callback']);
236
237 5
                    return $v;
238 27
                })
239 27
                ->end()
240
                // Support multiple dynamic_template formats to match the old bundle style
241
                // and the way ElasticSearch expects them
242 27
                ->beforeNormalization()
243
                ->ifTrue(function ($v) { return isset($v['dynamic_templates']); })
244
                ->then(function ($v) {
245 4
                    $dt = array();
246 4
                    foreach ($v['dynamic_templates'] as $key => $type) {
247 4
                        if (is_int($key)) {
248 4
                            $dt[] = $type;
249
                        } else {
250 4
                            $dt[][$key] = $type;
251
                        }
252
                    }
253
254 4
                    $v['dynamic_templates'] = $dt;
255
256 4
                    return $v;
257 27
                })
258 27
                ->end()
259 27
                ->children()
260 27
                    ->booleanNode('date_detection')->end()
261 27
                    ->arrayNode('dynamic_date_formats')->prototype('scalar')->end()->end()
262 27
                    ->scalarNode('index_analyzer')->end()
263 27
                    ->booleanNode('numeric_detection')->end()
264 27
                    ->scalarNode('search_analyzer')->end()
265 27
                    ->scalarNode('dynamic')->end()
266 27
                    ->variableNode('indexable_callback')->end()
267 27
                    ->append($this->getPersistenceNode())
268 27
                    ->append($this->getSerializerNode())
269 27
                ->end()
270 27
                ->append($this->getIdNode())
271 27
                ->append($this->getPropertiesNode())
272 27
                ->append($this->getDynamicTemplateNode())
273 27
                ->append($this->getSourceNode())
274 27
                ->append($this->getBoostNode())
275 27
                ->append($this->getRoutingNode())
276 27
                ->append($this->getParentNode())
277 27
                ->append($this->getAllNode())
278 27
                ->append($this->getTimestampNode())
279 27
                ->append($this->getTtlNode())
280 27
            ->end()
281
        ;
282
283 27
        return $node;
284
    }
285
286
    /**
287
     * Returns the array node used for "properties".
288
     */
289 27
    protected function getPropertiesNode()
290
    {
291 27
        $builder = new TreeBuilder();
292 27
        $node = $builder->root('properties');
293
294
        $node
295 27
            ->useAttributeAsKey('name')
296 27
            ->prototype('variable')
297 27
                ->treatNullLike(array());
298
299 27
        return $node;
300
    }
301
302
    /**
303
     * Returns the array node used for "dynamic_templates".
304
     */
305 27
    public function getDynamicTemplateNode()
306
    {
307 27
        $builder = new TreeBuilder();
308 27
        $node = $builder->root('dynamic_templates');
309
310
        $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...
311 27
            ->prototype('array')
312 27
                ->prototype('array')
313 27
                    ->children()
314 27
                        ->scalarNode('match')->end()
315 27
                        ->scalarNode('unmatch')->end()
316 27
                        ->scalarNode('match_mapping_type')->end()
317 27
                        ->scalarNode('path_match')->end()
318 27
                        ->scalarNode('path_unmatch')->end()
319 27
                        ->scalarNode('match_pattern')->end()
320 27
                        ->arrayNode('mapping')
321 27
                            ->prototype('variable')
322 27
                                ->treatNullLike(array())
323 27
                            ->end()
324 27
                        ->end()
325 27
                    ->end()
326 27
                ->end()
327 27
            ->end()
328
        ;
329
330 27
        return $node;
331
    }
332
333
    /**
334
     * Returns the array node used for "_id".
335
     */
336 27 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...
337
    {
338 27
        $builder = new TreeBuilder();
339 27
        $node = $builder->root('_id');
340
341
        $node
342 27
            ->children()
343 27
            ->scalarNode('path')->end()
344 27
            ->end()
345
        ;
346
347 27
        return $node;
348
    }
349
350
    /**
351
     * Returns the array node used for "_source".
352
     */
353 27
    protected function getSourceNode()
354
    {
355 27
        $builder = new TreeBuilder();
356 27
        $node = $builder->root('_source');
357
358
        $node
359 27
            ->children()
360 27
                ->arrayNode('excludes')
361 27
                    ->useAttributeAsKey('name')
362 27
                    ->prototype('scalar')->end()
363 27
                ->end()
364 27
                ->arrayNode('includes')
365 27
                    ->useAttributeAsKey('name')
366 27
                    ->prototype('scalar')->end()
367 27
                ->end()
368 27
                ->scalarNode('compress')->end()
369 27
                ->scalarNode('compress_threshold')->end()
370 27
                ->scalarNode('enabled')->defaultTrue()->end()
371 27
            ->end()
372
        ;
373
374 27
        return $node;
375
    }
376
377
    /**
378
     * Returns the array node used for "_boost".
379
     */
380 27
    protected function getBoostNode()
381
    {
382 27
        $builder = new TreeBuilder();
383 27
        $node = $builder->root('_boost');
384
385
        $node
386 27
            ->children()
387 27
                ->scalarNode('name')->end()
388 27
                ->scalarNode('null_value')->end()
389 27
            ->end()
390
        ;
391
392 27
        return $node;
393
    }
394
395
    /**
396
     * Returns the array node used for "_routing".
397
     */
398 27 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...
399
    {
400 27
        $builder = new TreeBuilder();
401 27
        $node = $builder->root('_routing');
402
403
        $node
404 27
            ->children()
405 27
                ->scalarNode('required')->end()
406 27
                ->scalarNode('path')->end()
407 27
            ->end()
408
        ;
409
410 27
        return $node;
411
    }
412
413
    /**
414
     * Returns the array node used for "_parent".
415
     */
416 27
    protected function getParentNode()
417
    {
418 27
        $builder = new TreeBuilder();
419 27
        $node = $builder->root('_parent');
420
421
        $node
422 27
            ->children()
423 27
                ->scalarNode('type')->end()
424 27
                ->scalarNode('property')->defaultValue(null)->end()
425 27
                ->scalarNode('identifier')->defaultValue('id')->end()
426 27
            ->end()
427
        ;
428
429 27
        return $node;
430
    }
431
432
    /**
433
     * Returns the array node used for "_all".
434
     */
435 27
    protected function getAllNode()
436
    {
437 27
        $builder = new TreeBuilder();
438 27
        $node = $builder->root('_all');
439
440
        $node
441 27
            ->children()
442 27
            ->scalarNode('enabled')->defaultValue(true)->end()
443 27
            ->scalarNode('index_analyzer')->end()
444 27
            ->scalarNode('search_analyzer')->end()
445 27
            ->end()
446
        ;
447
448 27
        return $node;
449
    }
450
451
    /**
452
     * Returns the array node used for "_timestamp".
453
     */
454 27 View Code Duplication
    protected function getTimestampNode()
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...
455
    {
456 27
        $builder = new TreeBuilder();
457 27
        $node = $builder->root('_timestamp');
458
459
        $node
460 27
            ->children()
461 27
            ->scalarNode('enabled')->defaultValue(true)->end()
462 27
            ->scalarNode('path')->end()
463 27
            ->scalarNode('format')->end()
464 27
            ->scalarNode('store')->end()
465 27
            ->scalarNode('index')->end()
466 27
            ->end()
467
        ;
468
469 27
        return $node;
470
    }
471
472
    /**
473
     * Returns the array node used for "_ttl".
474
     */
475 27 View Code Duplication
    protected function getTtlNode()
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...
476
    {
477 27
        $builder = new TreeBuilder();
478 27
        $node = $builder->root('_ttl');
479
480
        $node
481 27
            ->children()
482 27
            ->scalarNode('enabled')->defaultValue(true)->end()
483 27
            ->scalarNode('default')->end()
484 27
            ->scalarNode('store')->end()
485 27
            ->scalarNode('index')->end()
486 27
            ->end()
487
        ;
488
489 27
        return $node;
490
    }
491
492
    /**
493
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
494
     */
495 27
    protected function getPersistenceNode()
496
    {
497 27
        $builder = new TreeBuilder();
498 27
        $node = $builder->root('persistence');
499
500
        $node
501 27
            ->validate()
502 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...
503 27
                    ->thenInvalid('Propel doesn\'t support listeners')
504 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...
505 27
                    ->thenInvalid('Propel doesn\'t support the "repository" parameter')
506
                ->ifTrue(function($v) { return isset($v['driver']) && 'orm' !== $v['driver'] && !empty($v['elastica_to_model_transformer']['hints']); })
507 27
                    ->thenInvalid('Hints are only supported by the "orm" driver')
508 27
            ->end()
509 27
            ->children()
510 27
                ->scalarNode('driver')
511 27
                    ->validate()
512 27
                    ->ifNotInArray($this->supportedDrivers)
513 27
                        ->thenInvalid('The driver %s is not supported. Please choose one of '.json_encode($this->supportedDrivers))
514 27
                    ->end()
515 27
                ->end()
516 27
                ->scalarNode('model')->end()
517 27
                ->scalarNode('repository')->end()
518 27
                ->scalarNode('identifier')->defaultValue('id')->end()
519 27
                ->arrayNode('provider')
520 27
                    ->children()
521 27
                        ->scalarNode('batch_size')->defaultValue(100)->end()
522 27
                        ->scalarNode('clear_object_manager')->defaultTrue()->end()
523 27
                        ->scalarNode('debug_logging')
524 27
                            ->defaultValue($this->debug)
525 27
                            ->treatNullLike(true)
526 27
                        ->end()
527 27
                        ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end()
528 27
                        ->scalarNode('service')->end()
529 27
                    ->end()
530 27
                ->end()
531 27
                ->arrayNode('listener')
532 27
                    ->children()
533 27
                        ->scalarNode('insert')->defaultTrue()->end()
534 27
                        ->scalarNode('update')->defaultTrue()->end()
535 27
                        ->scalarNode('delete')->defaultTrue()->end()
536 27
                        ->scalarNode('flush')->defaultTrue()->end()
537 27
                        ->booleanNode('immediate')->defaultFalse()->end()
538 27
                        ->scalarNode('logger')
539 27
                            ->defaultFalse()
540 27
                            ->treatNullLike('fos_elastica.logger')
541 27
                            ->treatTrueLike('fos_elastica.logger')
542 27
                        ->end()
543 27
                        ->scalarNode('service')->end()
544 27
                    ->end()
545 27
                ->end()
546 27
                ->arrayNode('finder')
547 27
                    ->children()
548 27
                        ->scalarNode('service')->end()
549 27
                    ->end()
550 27
                ->end()
551 27
                ->arrayNode('elastica_to_model_transformer')
552 27
                    ->addDefaultsIfNotSet()
553 27
                    ->children()
554 27
                        ->arrayNode('hints')
555 27
                            ->prototype('array')
556 27
                                ->children()
557 27
                                    ->scalarNode('name')->end()
558 27
                                    ->scalarNode('value')->end()
559 27
                                ->end()
560 27
                            ->end()
561 27
                        ->end()
562 27
                        ->booleanNode('hydrate')->defaultTrue()->end()
563 27
                        ->booleanNode('ignore_missing')
564 27
                            ->defaultFalse()
565 27
                            ->info('Silently ignore results returned from Elasticsearch without corresponding persistent object.')
566 27
                        ->end()
567 27
                        ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end()
568 27
                        ->scalarNode('service')->end()
569 27
                    ->end()
570 27
                ->end()
571 27
                ->arrayNode('model_to_elastica_transformer')
572 27
                    ->addDefaultsIfNotSet()
573 27
                    ->children()
574 27
                        ->scalarNode('service')->end()
575 27
                    ->end()
576 27
                ->end()
577 27
                ->arrayNode('persister')
578 27
                    ->addDefaultsIfNotSet()
579 27
                    ->children()
580 27
                        ->scalarNode('service')->end()
581 27
                    ->end()
582 27
                ->end()
583 27
            ->end();
584
585 27
        return $node;
586
    }
587
588
    /**
589
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
590
     */
591 27
    protected function getSerializerNode()
592
    {
593 27
        $builder = new TreeBuilder();
594 27
        $node = $builder->root('serializer');
595
596
        $node
597 27
            ->addDefaultsIfNotSet()
598 27
            ->children()
599 27
                ->arrayNode('groups')
600 27
                    ->treatNullLike(array())
601 27
                    ->prototype('scalar')->end()
602 27
                ->end()
603 27
                ->scalarNode('version')->end()
604 27
                ->booleanNode('serialize_null')
605 27
                    ->defaultFalse()
606 27
                ->end()
607 27
            ->end();
608
609 27
        return $node;
610
    }
611
612
    /**
613
     * Adds the configuration for the "index_templates" key.
614
     *
615
     * @param ArrayNodeDefinition $rootNode
616
     *
617
     * @return void
618
     */
619 27
    private function addIndexTemplatesSection(ArrayNodeDefinition $rootNode)
620
    {
621
        $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...
622 27
            ->fixXmlConfig('index_template')
623 27
            ->children()
624 27
                ->arrayNode('index_templates')
625 27
                    ->useAttributeAsKey('name')
626 27
                    ->prototype('array')
627 27
                        ->children()
628 27
                            ->scalarNode('template_name')
629 27
                                ->info('Defaults to the name of the index template, but can be modified if the index name is different in ElasticSearch')
630 27
                            ->end()
631 27
                            ->scalarNode('template')->isRequired()->end()
632 27
                            ->scalarNode('client')->end()
633 27
                            ->variableNode('settings')->defaultValue(array())->end()
634 27
                        ->end()
635 27
                        ->append($this->getTypesNode())
636 27
                    ->end()
637 27
                ->end()
638 27
            ->end()
639
        ;
640 27
    }
641
}
642