Completed
Pull Request — master (#1569)
by
unknown
03:09
created

Configuration   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 538
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 99.73%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 5
dl 0
loc 538
ccs 370
cts 371
cp 0.9973
rs 10
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getConfigTreeBuilder() 0 30 1
A getDynamicTemplateNode() 0 26 1
A createTreeBuilderNode() 0 4 1
A addIndexTemplatesSection() 0 22 1
A getTypesNode() 0 53 3
A getPropertiesNode() 0 11 1
A getIdNode() 0 12 1
A getSourceNode() 0 22 1
A getRoutingNode() 0 13 1
A getAllNode() 0 13 1
B getPersistenceNode() 0 99 3
A getSerializerNode() 0 19 1
B addClientsSection() 0 102 4
A addIndexesSection() 0 34 1
1
<?php
2
3
/*
4
 * This file is part of the FOSElasticaBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\ElasticaBundle\DependencyInjection;
13
14
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
15
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
16
use Symfony\Component\Config\Definition\ConfigurationInterface;
17
18
class Configuration implements ConfigurationInterface
19
{
20
    private const SUPPORTED_DRIVERS = ['orm', 'mongodb', 'phpcr'];
21
22
    /**
23
     * If the kernel is running in debug mode.
24
     *
25
     * @var bool
26
     */
27
    private $debug;
28
29 34
    public function __construct($debug)
30
    {
31 34
        $this->debug = $debug;
32 34
    }
33
34
    /**
35
     * Generates the configuration tree.
36
     *
37
     * @return TreeBuilder
38
     */
39 34
    public function getConfigTreeBuilder()
40
    {
41 34
        $treeBuilder = new TreeBuilder('fos_elastica');
42 34
        $rootNode = $treeBuilder->getRootNode();
43
44 34
        $this->addClientsSection($rootNode);
0 ignored issues
show
Compatibility introduced by
$rootNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition>. It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
45 34
        $this->addIndexesSection($rootNode);
0 ignored issues
show
Compatibility introduced by
$rootNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition>. It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
46 34
        $this->addIndexTemplatesSection($rootNode);
0 ignored issues
show
Compatibility introduced by
$rootNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition>. It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
47
48
        $rootNode
49 34
            ->children()
50 34
                ->scalarNode('default_client')
51 34
                    ->info('Defaults to the first client defined')
52 34
                ->end()
53 34
                ->scalarNode('default_index')
54 34
                    ->info('Defaults to the first index defined')
55 34
                ->end()
56 34
                ->scalarNode('default_manager')->defaultValue('orm')->end()
57 34
                ->arrayNode('serializer')
58 34
                    ->treatNullLike([])
59 34
                    ->children()
60 34
                        ->scalarNode('callback_class')->defaultValue('FOS\ElasticaBundle\Serializer\Callback')->end()
61 34
                        ->scalarNode('serializer')->defaultValue('serializer')->end()
62 34
                    ->end()
63 34
                ->end()
64 34
            ->end()
65
        ;
66
67 34
        return $treeBuilder;
68
    }
69
70
    /**
71
     * Returns the array node used for "dynamic_templates".
72
     */
73 34
    private function getDynamicTemplateNode()
74
    {
75 34
        $node = $this->createTreeBuilderNode('dynamic_templates');
76
77
        $node
78 34
            ->prototype('array')
79 34
                ->prototype('array')
80 34
                    ->children()
81 34
                        ->scalarNode('match')->end()
82 34
                        ->scalarNode('unmatch')->end()
83 34
                        ->scalarNode('match_mapping_type')->end()
84 34
                        ->scalarNode('path_match')->end()
85 34
                        ->scalarNode('path_unmatch')->end()
86 34
                        ->scalarNode('match_pattern')->end()
87 34
                        ->arrayNode('mapping')
88 34
                            ->prototype('variable')
89 34
                                ->treatNullLike([])
90 34
                            ->end()
91 34
                        ->end()
92 34
                    ->end()
93 34
                ->end()
94 34
            ->end()
95
        ;
96
97 34
        return $node;
98
    }
99
100
    /**
101
     * Returns the array node used for "types".
102
     */
103 34
    private function getTypesNode()
104
    {
105 34
        $node = $this->createTreeBuilderNode('types');
106
107
        $node
0 ignored issues
show
Bug introduced by
The method useAttributeAsKey() does not exist on Symfony\Component\Config...\Builder\NodeDefinition. Did you maybe mean attribute()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
108 34
            ->useAttributeAsKey('name')
109 34
            ->prototype('array')
110 34
                ->treatNullLike([])
111 34
                ->beforeNormalization()
112 34
                ->ifNull()
113 34
                    ->thenEmptyArray()
114 34
                ->end()
115
                // Support multiple dynamic_template formats to match the old bundle style
116
                // and the way ElasticSearch expects them
117 34
                ->beforeNormalization()
118
                ->ifTrue(function ($v) {
119 24
                    return isset($v['dynamic_templates']);
120 34
                })
121
                ->then(function ($v) {
122 5
                    $dt = [];
123 5
                    foreach ($v['dynamic_templates'] as $key => $type) {
124 5
                        if (is_int($key)) {
125 5
                            $dt[] = $type;
126
                        } else {
127
                            $dt[][$key] = $type;
128
                        }
129
                    }
130
131 5
                    $v['dynamic_templates'] = $dt;
132
133 5
                    return $v;
134 34
                })
135 34
                ->end()
136 34
                ->children()
137 34
                    ->booleanNode('date_detection')->end()
138 34
                    ->arrayNode('dynamic_date_formats')->prototype('scalar')->end()->end()
139 34
                    ->scalarNode('analyzer')->end()
140 34
                    ->booleanNode('numeric_detection')->end()
141 34
                    ->scalarNode('dynamic')->end()
142 34
                    ->append($this->getPersistenceNode())
143 34
                    ->append($this->getSerializerNode())
144 34
                ->end()
145 34
                ->append($this->getIdNode())
146 34
                ->append($this->getPropertiesNode())
147 34
                ->append($this->getDynamicTemplateNode())
148 34
                ->append($this->getSourceNode())
149 34
                ->append($this->getRoutingNode())
150 34
                ->append($this->getAllNode())
151 34
            ->end()
152
        ;
153
154 34
        return $node;
155
    }
156
157
    /**
158
     * Returns the array node used for "properties".
159
     */
160 34
    private function getPropertiesNode()
161
    {
162 34
        $node = $this->createTreeBuilderNode('properties');
163
164
        $node
0 ignored issues
show
Bug introduced by
The method useAttributeAsKey() does not exist on Symfony\Component\Config...\Builder\NodeDefinition. Did you maybe mean attribute()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
165 34
            ->useAttributeAsKey('name')
166 34
            ->prototype('variable')
167 34
                ->treatNullLike([]);
168
169 34
        return $node;
170
    }
171
172
    /**
173
     * Returns the array node used for "_id".
174
     */
175 34
    private function getIdNode()
176
    {
177 34
        $node = $this->createTreeBuilderNode('_id');
178
179
        $node
180 34
            ->children()
181 34
            ->scalarNode('path')->end()
182 34
            ->end()
183
        ;
184
185 34
        return $node;
186
    }
187
188
    /**
189
     * Returns the array node used for "_source".
190
     */
191 34
    private function getSourceNode()
192
    {
193 34
        $node = $this->createTreeBuilderNode('_source');
194
195
        $node
196 34
            ->children()
197 34
                ->arrayNode('excludes')
198 34
                    ->useAttributeAsKey('name')
199 34
                    ->prototype('scalar')->end()
200 34
                ->end()
201 34
                ->arrayNode('includes')
202 34
                    ->useAttributeAsKey('name')
203 34
                    ->prototype('scalar')->end()
204 34
                ->end()
205 34
                ->scalarNode('compress')->end()
206 34
                ->scalarNode('compress_threshold')->end()
207 34
                ->scalarNode('enabled')->defaultTrue()->end()
208 34
            ->end()
209
        ;
210
211 34
        return $node;
212
    }
213
214
    /**
215
     * Returns the array node used for "_routing".
216
     */
217 34
    private function getRoutingNode()
218
    {
219 34
        $node = $this->createTreeBuilderNode('_routing');
220
221
        $node
222 34
            ->children()
223 34
                ->scalarNode('required')->end()
224 34
                ->scalarNode('path')->end()
225 34
            ->end()
226
        ;
227
228 34
        return $node;
229
    }
230
231
    /**
232
     * Returns the array node used for "_all".
233
     */
234 34
    private function getAllNode()
235
    {
236 34
        $node = $this->createTreeBuilderNode('_all');
237
238
        $node
239 34
            ->children()
240 34
            ->scalarNode('enabled')->defaultValue(true)->end()
241 34
            ->scalarNode('analyzer')->end()
242 34
            ->end()
243
        ;
244
245 34
        return $node;
246
    }
247
248
    /**
249
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
250
     */
251 34
    private function getPersistenceNode()
252
    {
253 34
        $node = $this->createTreeBuilderNode('persistence');
254
255
        $node
256 34
            ->validate()
257
                ->ifTrue(function ($v) {
258 16
                    return isset($v['driver']) && 'orm' !== $v['driver'] && !empty($v['elastica_to_model_transformer']['hints']);
259 34
                })
260 34
                    ->thenInvalid('Hints are only supported by the "orm" driver')
261 34
            ->end()
262 34
            ->children()
263 34
                ->scalarNode('driver')
264 34
                    ->defaultValue('orm')
265 34
                    ->validate()
266 34
                    ->ifNotInArray(self::SUPPORTED_DRIVERS)
267 34
                        ->thenInvalid('The driver %s is not supported. Please choose one of '.json_encode(self::SUPPORTED_DRIVERS))
268 34
                    ->end()
269 34
                ->end()
270 34
                ->scalarNode('model')->defaultValue(null)->end()
271 34
                ->scalarNode('repository')->end()
272 34
                ->scalarNode('identifier')->defaultValue('id')->end()
273 34
                ->arrayNode('provider')
274 34
                    ->addDefaultsIfNotSet()
275 34
                    ->children()
276 34
                        ->scalarNode('batch_size')->defaultValue(100)->end()
277 34
                        ->scalarNode('clear_object_manager')->defaultTrue()->end()
278 34
                        ->scalarNode('debug_logging')
279 34
                            ->defaultValue($this->debug)
280 34
                            ->treatNullLike(true)
281 34
                        ->end()
282 34
                        ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end()
283 34
                        ->scalarNode('service')->end()
284 34
                    ->end()
285 34
                ->end()
286 34
                ->arrayNode('listener')
287 34
                    ->addDefaultsIfNotSet()
288 34
                    ->children()
289 34
                        ->booleanNode('enabled')->defaultTrue()->end()
290 34
                        ->scalarNode('insert')->defaultTrue()->end()
291 34
                        ->scalarNode('update')->defaultTrue()->end()
292 34
                        ->scalarNode('delete')->defaultTrue()->end()
293 34
                        ->scalarNode('flush')->defaultTrue()->end()
294 34
                        ->booleanNode('defer')->defaultFalse()->end()
295 34
                        ->scalarNode('logger')
296 34
                            ->defaultFalse()
297 34
                            ->treatNullLike('fos_elastica.logger')
298 34
                            ->treatTrueLike('fos_elastica.logger')
299 34
                        ->end()
300 34
                        ->scalarNode('service')->end()
301 34
                    ->end()
302 34
                ->end()
303 34
                ->arrayNode('finder')
304 34
                    ->addDefaultsIfNotSet()
305 34
                    ->children()
306 34
                        ->scalarNode('service')->end()
307 34
                    ->end()
308 34
                ->end()
309 34
                ->arrayNode('elastica_to_model_transformer')
310 34
                    ->addDefaultsIfNotSet()
311 34
                    ->children()
312 34
                        ->arrayNode('hints')
313 34
                            ->prototype('array')
314 34
                                ->children()
315 34
                                    ->scalarNode('name')->end()
316 34
                                    ->scalarNode('value')->end()
317 34
                                ->end()
318 34
                            ->end()
319 34
                        ->end()
320 34
                        ->booleanNode('hydrate')->defaultTrue()->end()
321 34
                        ->booleanNode('ignore_missing')
322 34
                            ->defaultFalse()
323 34
                            ->info('Silently ignore results returned from Elasticsearch without corresponding persistent object.')
324 34
                        ->end()
325 34
                        ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end()
326 34
                        ->scalarNode('service')->end()
327 34
                    ->end()
328 34
                ->end()
329 34
                ->arrayNode('model_to_elastica_transformer')
330 34
                    ->addDefaultsIfNotSet()
331 34
                    ->children()
332 34
                        ->scalarNode('service')->end()
333 34
                    ->end()
334 34
                ->end()
335 34
                ->arrayNode('persister')
336 34
                    ->addDefaultsIfNotSet()
337 34
                    ->children()
338 34
                        ->enumNode('refresh')
339 34
                            ->treatTrueLike('true')
340 34
                            ->treatFalseLike('false')
341 34
                            ->values(['true', 'wait_for', 'false'])
342 34
                        ->end()
343 34
                        ->scalarNode('service')->end()
344 34
                    ->end()
345 34
                ->end()
346 34
            ->end();
347
348 34
        return $node;
349
    }
350
351
    /**
352
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
353
     */
354 34
    private function getSerializerNode()
355
    {
356 34
        $node = $this->createTreeBuilderNode('serializer');
357
358
        $node
359 34
            ->addDefaultsIfNotSet()
360 34
            ->children()
361 34
                ->arrayNode('groups')
362 34
                    ->treatNullLike([])
363 34
                    ->prototype('scalar')->end()
364 34
                ->end()
365 34
                ->scalarNode('version')->end()
366 34
                ->booleanNode('serialize_null')
367 34
                    ->defaultFalse()
368 34
                ->end()
369 34
            ->end();
370
371 34
        return $node;
372
    }
373
374
    /**
375
     * Adds the configuration for the "clients" key.
376
     */
377 34
    private function addClientsSection(ArrayNodeDefinition $rootNode)
378
    {
379
        $rootNode
380 34
            ->fixXmlConfig('client')
381 34
            ->children()
382 34
                ->arrayNode('clients')
383 34
                    ->useAttributeAsKey('id')
384 34
                    ->prototype('array')
385 34
                        ->performNoDeepMerging()
386
                        // Elastica names its properties with camel case, support both
387 34
                        ->beforeNormalization()
388
                        ->ifTrue(function ($v) {
389 32
                            return isset($v['connection_strategy']);
390 34
                        })
391
                        ->then(function ($v) {
392 5
                            $v['connectionStrategy'] = $v['connection_strategy'];
393 5
                            unset($v['connection_strategy']);
394
395 5
                            return $v;
396 34
                        })
397 34
                        ->end()
398
                        // If there is no connections array key defined, assume a single connection.
399 34
                        ->beforeNormalization()
400
                        ->ifTrue(function ($v) {
401 32
                            return is_array($v) && !array_key_exists('connections', $v);
402 34
                        })
403
                        ->then(function ($v) {
404
                            return [
405 32
                                'connections' => [$v],
406
                            ];
407 34
                        })
408 34
                        ->end()
409 34
                        ->children()
410 34
                            ->arrayNode('connections')
411 34
                                ->requiresAtLeastOneElement()
412 34
                                ->prototype('array')
413 34
                                    ->fixXmlConfig('header')
414 34
                                    ->children()
415 34
                                        ->scalarNode('url')
416 34
                                            ->validate()
417
                                                ->ifTrue(function ($url) {
418 18
                                                    return $url && '/' !== substr($url, -1);
419 34
                                                })
420
                                                ->then(function ($url) {
421 18
                                                    return $url.'/';
422 34
                                                })
423 34
                                            ->end()
424 34
                                        ->end()
425 34
                                        ->scalarNode('username')->end()
426 34
                                        ->scalarNode('password')->end()
427 34
                                        ->scalarNode('host')->end()
428 34
                                        ->scalarNode('port')->end()
429 34
                                        ->scalarNode('proxy')->end()
430 34
                                        ->arrayNode('http_error_codes')
431 34
                                            ->beforeNormalization()
432
                                                ->ifTrue(function ($v) { return !is_array($v); })
433
                                                ->then(function ($v) { return array($v); })
434 34
                                            ->end()
435 34
                                            ->requiresAtLeastOneElement()
436 34
                                            ->defaultValue([400, 403, 404])
437 34
                                            ->prototype('scalar')->end()
438 34
                                        ->end()
439 34
                                        ->scalarNode('aws_access_key_id')->end()
440 34
                                        ->scalarNode('aws_secret_access_key')->end()
441 34
                                        ->scalarNode('aws_region')->end()
442 34
                                        ->scalarNode('aws_session_token')->end()
443 34
                                        ->booleanNode('ssl')->defaultValue(false)->end()
444 34
                                        ->scalarNode('logger')
445 34
                                            ->defaultValue($this->debug ? 'fos_elastica.logger' : false)
446 34
                                            ->treatNullLike('fos_elastica.logger')
447 34
                                            ->treatTrueLike('fos_elastica.logger')
448 34
                                        ->end()
449 34
                                        ->booleanNode('compression')->defaultValue(false)->end()
450 34
                                        ->arrayNode('headers')
451 34
                                            ->normalizeKeys(false)
452 34
                                            ->useAttributeAsKey('name')
453 34
                                            ->prototype('scalar')->end()
454 34
                                        ->end()
455 34
                                        ->arrayNode('curl')
456 34
                                            ->useAttributeAsKey(CURLOPT_SSL_VERIFYPEER)
457 34
                                            ->prototype('boolean')->end()
458 34
                                        ->end()
459 34
                                        ->scalarNode('transport')->end()
460 34
                                        ->scalarNode('timeout')->end()
461 34
                                        ->scalarNode('connectTimeout')->end()
462 34
                                        ->scalarNode('retryOnConflict')
463 34
                                            ->defaultValue(0)
464 34
                                        ->end()
465 34
                                        ->booleanNode('persistent')->defaultValue(true)->end()
466 34
                                    ->end()
467 34
                                ->end()
468 34
                            ->end()
469 34
                            ->scalarNode('timeout')->end()
470 34
                            ->scalarNode('connectTimeout')->end()
471 34
                            ->scalarNode('headers')->end()
472 34
                            ->scalarNode('connectionStrategy')->defaultValue('Simple')->end()
473 34
                        ->end()
474 34
                    ->end()
475 34
                ->end()
476 34
            ->end()
477
        ;
478 34
    }
479
480
    /**
481
     * Adds the configuration for the "indexes" key.
482
     */
483 34
    private function addIndexesSection(ArrayNodeDefinition $rootNode)
484
    {
485
        $rootNode
486 34
            ->fixXmlConfig('index')
487 34
            ->children()
488 34
                ->arrayNode('indexes')
489 34
                    ->useAttributeAsKey('name')
490 34
                    ->prototype('array')
491 34
                        ->children()
492 34
                            ->scalarNode('index_name')
493 34
                                ->info('Defaults to the name of the index, but can be modified if the index name is different in ElasticSearch')
494 34
                            ->end()
495 34
                            ->variableNode('indexable_callback')->end()
496 34
                            ->booleanNode('use_alias')->defaultValue(false)->end()
497 34
                            ->scalarNode('client')->end()
498 34
                            ->scalarNode('finder')
499 34
                                ->treatNullLike(true)
500 34
                                ->defaultFalse()
501 34
                            ->end()
502 34
                            ->arrayNode('type_prototype')
503 34
                                ->children()
504 34
                                    ->scalarNode('analyzer')->end()
505 34
                                    ->append($this->getPersistenceNode())
506 34
                                    ->append($this->getSerializerNode())
507 34
                                ->end()
508 34
                            ->end()
509 34
                            ->variableNode('settings')->defaultValue([])->end()
510 34
                        ->end()
511 34
                        ->append($this->getTypesNode())
512 34
                    ->end()
513 34
                ->end()
514 34
            ->end()
515
        ;
516 34
    }
517
518
    /**
519
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
520
     */
521 34
    private function createTreeBuilderNode($name)
522
    {
523 34
        return (new TreeBuilder($name))->getRootNode();
524
    }
525
526
    /**
527
     * Adds the configuration for the "index_templates" key.
528
     *
529
     * @param ArrayNodeDefinition $rootNode
530
     *
531
     * @return void
532
     */
533 34
    private function addIndexTemplatesSection(ArrayNodeDefinition $rootNode)
534
    {
535
        $rootNode
536 34
            ->fixXmlConfig('index_template')
537 34
            ->children()
538 34
                ->arrayNode('index_templates')
539 34
                    ->useAttributeAsKey('name')
540 34
                    ->prototype('array')
541 34
                        ->children()
542 34
                            ->scalarNode('template_name')
543 34
                                ->info('Defaults to the name of the index template, but can be modified if the index name is different in ElasticSearch')
544 34
                            ->end()
545 34
                            ->scalarNode('template')->isRequired()->end()
546 34
                            ->scalarNode('client')->end()
547 34
                            ->variableNode('settings')->defaultValue([])->end()
548 34
                        ->end()
549 34
                        ->append($this->getTypesNode())
550 34
                    ->end()
551 34
                ->end()
552 34
            ->end()
553
        ;
554 34
    }
555
}
556