Completed
Push — master ( e1d635...b29ece )
by Karel
40:58 queued 38:57
created

Configuration   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 540
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 97.93%

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 5
dl 0
loc 540
ccs 378
cts 386
cp 0.9793
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getDynamicTemplateNode() 0 26 1
A getConfigTreeBuilder() 0 36 1
A getPropertiesNode() 0 11 1
A getIdNode() 0 12 1
A getSourceNode() 0 22 1
A getRoutingNode() 0 13 1
B getPersistenceNode() 0 99 3
A getSerializerNode() 0 19 1
B addClientsSection() 0 102 4
B addIndexesSection() 0 71 3
A createTreeBuilderNode() 0 4 1
B addIndexTemplatesSection() 0 57 3
1
<?php
2
3
/*
4
 * This file is part of the FOSElasticaBundle package.
5
 *
6
 * (c) FriendsOfSymfony <https://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 35
    public function __construct(bool $debug)
30
    {
31 35
        $this->debug = $debug;
32 35
    }
33
34
    /**
35
     * Generates the configuration tree.
36
     *
37
     * @return TreeBuilder
38
     */
39 35
    public function getConfigTreeBuilder()
40
    {
41 35
        $treeBuilder = new TreeBuilder('fos_elastica');
42 35
        $rootNode = $treeBuilder->getRootNode();
43
44 35
        $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 35
        $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 35
        $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 35
            ->children()
50 35
                ->scalarNode('default_client')
51 35
                    ->info('Defaults to the first client defined')
52 35
                ->end()
53 35
                ->scalarNode('default_index')
54 35
                    ->info('Defaults to the first index defined')
55 35
                ->end()
56 35
                ->scalarNode('default_manager')->defaultValue('orm')->end()
57 35
                ->arrayNode('messenger')
58 35
                    ->canBeEnabled()
59 35
                    ->children()
60 35
                        ->scalarNode('message_bus')->defaultNull()->end()
61 35
                    ->end()
62 35
                ->end()
63 35
                ->arrayNode('serializer')
64 35
                    ->treatNullLike([])
65 35
                    ->children()
66 35
                        ->scalarNode('callback_class')->defaultValue('FOS\ElasticaBundle\Serializer\Callback')->end()
67 35
                        ->scalarNode('serializer')->defaultValue('serializer')->end()
68 35
                    ->end()
69 35
                ->end()
70 35
            ->end()
71
        ;
72
73 35
        return $treeBuilder;
74
    }
75
76
    /**
77
     * Returns the array node used for "dynamic_templates".
78
     */
79 35
    private function getDynamicTemplateNode()
80
    {
81 35
        $node = $this->createTreeBuilderNode('dynamic_templates');
82
83
        $node
84 35
            ->prototype('array')
85 35
                ->prototype('array')
86 35
                    ->children()
87 35
                        ->scalarNode('match')->end()
88 35
                        ->scalarNode('unmatch')->end()
89 35
                        ->scalarNode('match_mapping_type')->end()
90 35
                        ->scalarNode('path_match')->end()
91 35
                        ->scalarNode('path_unmatch')->end()
92 35
                        ->scalarNode('match_pattern')->end()
93 35
                        ->arrayNode('mapping')
94 35
                            ->prototype('variable')
95 35
                                ->treatNullLike([])
96 35
                            ->end()
97 35
                        ->end()
98 35
                    ->end()
99 35
                ->end()
100 35
            ->end()
101
        ;
102
103 35
        return $node;
104
    }
105
106
    /**
107
     * Returns the array node used for "properties".
108
     */
109 35
    private function getPropertiesNode()
110
    {
111 35
        $node = $this->createTreeBuilderNode('properties');
112
113
        $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...
114 35
            ->useAttributeAsKey('name')
115 35
            ->prototype('variable')
116 35
                ->treatNullLike([]);
117
118 35
        return $node;
119
    }
120
121
    /**
122
     * Returns the array node used for "_id".
123
     */
124 35
    private function getIdNode()
125
    {
126 35
        $node = $this->createTreeBuilderNode('_id');
127
128
        $node
129 35
            ->children()
130 35
            ->scalarNode('path')->end()
131 35
            ->end()
132
        ;
133
134 35
        return $node;
135
    }
136
137
    /**
138
     * Returns the array node used for "_source".
139
     */
140 35
    private function getSourceNode()
141
    {
142 35
        $node = $this->createTreeBuilderNode('_source');
143
144
        $node
145 35
            ->children()
146 35
                ->arrayNode('excludes')
147 35
                    ->useAttributeAsKey('name')
148 35
                    ->prototype('scalar')->end()
149 35
                ->end()
150 35
                ->arrayNode('includes')
151 35
                    ->useAttributeAsKey('name')
152 35
                    ->prototype('scalar')->end()
153 35
                ->end()
154 35
                ->scalarNode('compress')->end()
155 35
                ->scalarNode('compress_threshold')->end()
156 35
                ->scalarNode('enabled')->defaultTrue()->end()
157 35
            ->end()
158
        ;
159
160 35
        return $node;
161
    }
162
163
    /**
164
     * Returns the array node used for "_routing".
165
     */
166 35
    private function getRoutingNode()
167
    {
168 35
        $node = $this->createTreeBuilderNode('_routing');
169
170
        $node
171 35
            ->children()
172 35
                ->scalarNode('required')->end()
173 35
                ->scalarNode('path')->end()
174 35
            ->end()
175
        ;
176
177 35
        return $node;
178
    }
179
180
    /**
181
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
182
     */
183 35
    private function getPersistenceNode()
184
    {
185 35
        $node = $this->createTreeBuilderNode('persistence');
186
187
        $node
188 35
            ->validate()
189
                ->ifTrue(function ($v) {
190 17
                    return isset($v['driver']) && 'orm' !== $v['driver'] && !empty($v['elastica_to_model_transformer']['hints']);
191 35
                })
192 35
                    ->thenInvalid('Hints are only supported by the "orm" driver')
193 35
            ->end()
194 35
            ->children()
195 35
                ->scalarNode('driver')
196 35
                    ->defaultValue('orm')
197 35
                    ->validate()
198 35
                    ->ifNotInArray(self::SUPPORTED_DRIVERS)
199 35
                        ->thenInvalid('The driver %s is not supported. Please choose one of '.json_encode(self::SUPPORTED_DRIVERS))
200 35
                    ->end()
201 35
                ->end()
202 35
                ->scalarNode('model')->defaultValue(null)->end()
203 35
                ->scalarNode('repository')->end()
204 35
                ->scalarNode('identifier')->defaultValue('id')->end()
205 35
                ->arrayNode('provider')
206 35
                    ->addDefaultsIfNotSet()
207 35
                    ->children()
208 35
                        ->scalarNode('batch_size')->defaultValue(100)->end()
209 35
                        ->scalarNode('clear_object_manager')->defaultTrue()->end()
210 35
                        ->booleanNode('debug_logging')
211 35
                            ->defaultValue($this->debug)
212 35
                            ->treatNullLike(true)
213 35
                        ->end()
214 35
                        ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end()
215 35
                        ->scalarNode('service')->end()
216 35
                    ->end()
217 35
                ->end()
218 35
                ->arrayNode('listener')
219 35
                    ->addDefaultsIfNotSet()
220 35
                    ->children()
221 35
                        ->booleanNode('enabled')->defaultTrue()->end()
222 35
                        ->scalarNode('insert')->defaultTrue()->end()
223 35
                        ->scalarNode('update')->defaultTrue()->end()
224 35
                        ->scalarNode('delete')->defaultTrue()->end()
225 35
                        ->scalarNode('flush')->defaultTrue()->end()
226 35
                        ->booleanNode('defer')->defaultFalse()->end()
227 35
                        ->scalarNode('logger')
228 35
                            ->defaultFalse()
229 35
                            ->treatNullLike('fos_elastica.logger')
230 35
                            ->treatTrueLike('fos_elastica.logger')
231 35
                        ->end()
232 35
                        ->scalarNode('service')->end()
233 35
                    ->end()
234 35
                ->end()
235 35
                ->arrayNode('finder')
236 35
                    ->addDefaultsIfNotSet()
237 35
                    ->children()
238 35
                        ->scalarNode('service')->end()
239 35
                    ->end()
240 35
                ->end()
241 35
                ->arrayNode('elastica_to_model_transformer')
242 35
                    ->addDefaultsIfNotSet()
243 35
                    ->children()
244 35
                        ->arrayNode('hints')
245 35
                            ->prototype('array')
246 35
                                ->children()
247 35
                                    ->scalarNode('name')->end()
248 35
                                    ->scalarNode('value')->end()
249 35
                                ->end()
250 35
                            ->end()
251 35
                        ->end()
252 35
                        ->booleanNode('hydrate')->defaultTrue()->end()
253 35
                        ->booleanNode('ignore_missing')
254 35
                            ->defaultFalse()
255 35
                            ->info('Silently ignore results returned from Elasticsearch without corresponding persistent object.')
256 35
                        ->end()
257 35
                        ->scalarNode('query_builder_method')->defaultValue('createQueryBuilder')->end()
258 35
                        ->scalarNode('service')->end()
259 35
                    ->end()
260 35
                ->end()
261 35
                ->arrayNode('model_to_elastica_transformer')
262 35
                    ->addDefaultsIfNotSet()
263 35
                    ->children()
264 35
                        ->scalarNode('service')->end()
265 35
                    ->end()
266 35
                ->end()
267 35
                ->arrayNode('persister')
268 35
                    ->addDefaultsIfNotSet()
269 35
                    ->children()
270 35
                        ->enumNode('refresh')
271 35
                            ->treatTrueLike('true')
272 35
                            ->treatFalseLike('false')
273 35
                            ->values(['true', 'wait_for', 'false'])
274 35
                        ->end()
275 35
                        ->scalarNode('service')->end()
276 35
                    ->end()
277 35
                ->end()
278 35
            ->end();
279
280 35
        return $node;
281
    }
282
283
    /**
284
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
285
     */
286 35
    private function getSerializerNode()
287
    {
288 35
        $node = $this->createTreeBuilderNode('serializer');
289
290
        $node
291 35
            ->addDefaultsIfNotSet()
292 35
            ->children()
293 35
                ->arrayNode('groups')
294 35
                    ->treatNullLike([])
295 35
                    ->prototype('scalar')->end()
296 35
                ->end()
297 35
                ->scalarNode('version')->end()
298 35
                ->booleanNode('serialize_null')
299 35
                    ->defaultFalse()
300 35
                ->end()
301 35
            ->end();
302
303 35
        return $node;
304
    }
305
306
    /**
307
     * Adds the configuration for the "clients" key.
308
     */
309 35
    private function addClientsSection(ArrayNodeDefinition $rootNode)
310
    {
311
        $rootNode
312 35
            ->fixXmlConfig('client')
313 35
            ->children()
314 35
                ->arrayNode('clients')
315 35
                    ->useAttributeAsKey('id')
316 35
                    ->prototype('array')
317 35
                        ->performNoDeepMerging()
318
                        // Elastica names its properties with camel case, support both
319 35
                        ->beforeNormalization()
320
                        ->ifTrue(function ($v) {
321 33
                            return isset($v['connection_strategy']);
322 35
                        })
323
                        ->then(function ($v) {
324 5
                            $v['connectionStrategy'] = $v['connection_strategy'];
325 5
                            unset($v['connection_strategy']);
326
327 5
                            return $v;
328 35
                        })
329 35
                        ->end()
330
                        // If there is no connections array key defined, assume a single connection.
331 35
                        ->beforeNormalization()
332
                        ->ifTrue(function ($v) {
333 33
                            return is_array($v) && !array_key_exists('connections', $v);
334 35
                        })
335
                        ->then(function ($v) {
336
                            return [
337 33
                                'connections' => [$v],
338
                            ];
339 35
                        })
340 35
                        ->end()
341 35
                        ->children()
342 35
                            ->arrayNode('connections')
343 35
                                ->requiresAtLeastOneElement()
344 35
                                ->prototype('array')
345 35
                                    ->fixXmlConfig('header')
346 35
                                    ->children()
347 35
                                        ->scalarNode('url')
348 35
                                            ->validate()
349
                                                ->ifTrue(function ($url) {
350 18
                                                    return $url && '/' !== substr($url, -1);
351 35
                                                })
352
                                                ->then(function ($url) {
353 18
                                                    return $url.'/';
354 35
                                                })
355 35
                                            ->end()
356 35
                                        ->end()
357 35
                                        ->scalarNode('username')->end()
358 35
                                        ->scalarNode('password')->end()
359 35
                                        ->scalarNode('host')->end()
360 35
                                        ->scalarNode('port')->end()
361 35
                                        ->scalarNode('proxy')->end()
362 35
                                        ->arrayNode('http_error_codes')
363 35
                                            ->beforeNormalization()
364
                                                ->ifTrue(function ($v) { return !is_array($v); })
365
                                                ->then(function ($v) { return [$v]; })
366 35
                                            ->end()
367 35
                                            ->requiresAtLeastOneElement()
368 35
                                            ->defaultValue([400, 403, 404])
369 35
                                            ->prototype('scalar')->end()
370 35
                                        ->end()
371 35
                                        ->scalarNode('aws_access_key_id')->end()
372 35
                                        ->scalarNode('aws_secret_access_key')->end()
373 35
                                        ->scalarNode('aws_region')->end()
374 35
                                        ->scalarNode('aws_session_token')->end()
375 35
                                        ->booleanNode('ssl')->defaultValue(false)->end()
376 35
                                        ->scalarNode('logger')
377 35
                                            ->defaultValue($this->debug ? 'fos_elastica.logger' : false)
378 35
                                            ->treatNullLike('fos_elastica.logger')
379 35
                                            ->treatTrueLike('fos_elastica.logger')
380 35
                                        ->end()
381 35
                                        ->booleanNode('compression')->defaultValue(false)->end()
382 35
                                        ->arrayNode('headers')
383 35
                                            ->normalizeKeys(false)
384 35
                                            ->useAttributeAsKey('name')
385 35
                                            ->prototype('scalar')->end()
386 35
                                        ->end()
387 35
                                        ->arrayNode('curl')
388 35
                                            ->useAttributeAsKey(CURLOPT_SSL_VERIFYPEER)
389 35
                                            ->prototype('boolean')->end()
390 35
                                        ->end()
391 35
                                        ->scalarNode('transport')->end()
392 35
                                        ->scalarNode('timeout')->end()
393 35
                                        ->scalarNode('connectTimeout')->end()
394 35
                                        ->scalarNode('retryOnConflict')
395 35
                                            ->defaultValue(0)
396 35
                                        ->end()
397 35
                                        ->booleanNode('persistent')->defaultValue(true)->end()
398 35
                                    ->end()
399 35
                                ->end()
400 35
                            ->end()
401 35
                            ->scalarNode('timeout')->end()
402 35
                            ->scalarNode('connectTimeout')->end()
403 35
                            ->scalarNode('headers')->end()
404 35
                            ->scalarNode('connectionStrategy')->defaultValue('Simple')->end()
405 35
                        ->end()
406 35
                    ->end()
407 35
                ->end()
408 35
            ->end()
409
        ;
410 35
    }
411
412
    /**
413
     * Adds the configuration for the "indexes" key.
414
     */
415 35
    private function addIndexesSection(ArrayNodeDefinition $rootNode)
416
    {
417
        $rootNode
418 35
            ->fixXmlConfig('index')
419 35
            ->children()
420 35
                ->arrayNode('indexes')
421 35
                    ->useAttributeAsKey('name')
422 35
                    ->prototype('array')
423 35
                        ->treatNullLike([])
424 35
                        ->beforeNormalization()
425 35
                        ->ifNull()
426 35
                        ->thenEmptyArray()
427 35
                        ->end()
428
                        // Support multiple dynamic_template formats to match the old bundle style
429
                        // and the way ElasticSearch expects them
430 35
                        ->beforeNormalization()
431
                        ->ifTrue(function ($v) {
432 24
                            return isset($v['dynamic_templates']);
433 35
                        })
434
                        ->then(function ($v) {
435 5
                            $dt = [];
436 5
                            foreach ($v['dynamic_templates'] as $key => $type) {
437 5
                                if (is_int($key)) {
438 5
                                    $dt[] = $type;
439
                                } else {
440
                                    $dt[][$key] = $type;
441
                                }
442
                            }
443
444 5
                            $v['dynamic_templates'] = $dt;
445
446 5
                            return $v;
447 35
                        })
448 35
                        ->end()
449 35
                        ->children()
450 35
                            ->scalarNode('index_name')
451 35
                                ->info('Defaults to the name of the index, but can be modified if the index name is different in ElasticSearch')
452 35
                            ->end()
453 35
                            ->variableNode('indexable_callback')->end()
454 35
                            ->booleanNode('use_alias')->defaultValue(false)->end()
455 35
                            ->scalarNode('client')->end()
456 35
                            ->scalarNode('finder')
457 35
                                ->treatNullLike(true)
458 35
                                ->defaultFalse()
459 35
                            ->end()
460 35
                            ->append($this->getPersistenceNode())
461 35
                            ->append($this->getSerializerNode())
462 35
                            ->arrayNode('index_prototype')
463 35
                                ->children()
464 35
                                    ->scalarNode('analyzer')->end()
465 35
                                    ->append($this->getPersistenceNode())
466 35
                                    ->append($this->getSerializerNode())
467 35
                                ->end()
468 35
                            ->end()
469 35
                            ->variableNode('settings')->defaultValue([])->end()
470 35
                            ->booleanNode('date_detection')->end()
471 35
                            ->arrayNode('dynamic_date_formats')->prototype('scalar')->end()->end()
472 35
                            ->scalarNode('analyzer')->end()
473 35
                            ->booleanNode('numeric_detection')->end()
474 35
                            ->scalarNode('dynamic')->end()
475 35
                        ->end()
476 35
                        ->append($this->getIdNode())
477 35
                        ->append($this->getPropertiesNode())
478 35
                        ->append($this->getDynamicTemplateNode())
479 35
                        ->append($this->getSourceNode())
480 35
                        ->append($this->getRoutingNode())
481 35
                    ->end()
482 35
                ->end()
483 35
            ->end()
484
        ;
485 35
    }
486
487
    /**
488
     * @return ArrayNodeDefinition|\Symfony\Component\Config\Definition\Builder\NodeDefinition
489
     */
490 35
    private function createTreeBuilderNode($name)
491
    {
492 35
        return (new TreeBuilder($name))->getRootNode();
493
    }
494
495
    /**
496
     * Adds the configuration for the "index_templates" key.
497
     *
498
     * @return void
499
     */
500 35
    private function addIndexTemplatesSection(ArrayNodeDefinition $rootNode)
501
    {
502
        $rootNode
503 35
            ->fixXmlConfig('index_template')
504 35
            ->children()
505 35
                ->arrayNode('index_templates')
506 35
                    ->useAttributeAsKey('name')
507 35
                    ->prototype('array')
508 35
                        ->treatNullLike([])
509 35
                        ->beforeNormalization()
510 35
                        ->ifNull()
511 35
                        ->thenEmptyArray()
512 35
                        ->end()
513
                        // Support multiple dynamic_template formats to match the old bundle style
514
                        // and the way ElasticSearch expects them
515 35
                        ->beforeNormalization()
516
                        ->ifTrue(function ($v) {
517 7
                            return isset($v['dynamic_templates']);
518 35
                        })
519
                        ->then(function ($v) {
520
                            $dt = [];
521
                            foreach ($v['dynamic_templates'] as $key => $type) {
522
                                if (is_int($key)) {
523
                                    $dt[] = $type;
524
                                } else {
525
                                    $dt[][$key] = $type;
526
                                }
527
                            }
528
529
                            $v['dynamic_templates'] = $dt;
530
531
                            return $v;
532 35
                        })
533 35
                        ->end()
534 35
                        ->children()
535 35
                            ->scalarNode('template_name')
536 35
                                ->info('Defaults to the name of the index template, but can be modified if the index name is different in ElasticSearch')
537 35
                            ->end()
538 35
                            ->scalarNode('template')->isRequired()->end()
539 35
                            ->scalarNode('client')->end()
540 35
                            ->variableNode('settings')->defaultValue([])->end()
541 35
                            ->booleanNode('date_detection')->end()
542 35
                            ->arrayNode('dynamic_date_formats')->prototype('scalar')->end()->end()
543 35
                            ->scalarNode('analyzer')->end()
544 35
                            ->booleanNode('numeric_detection')->end()
545 35
                            ->scalarNode('dynamic')->end()
546 35
                        ->end()
547 35
                        ->append($this->getIdNode())
548 35
                        ->append($this->getPropertiesNode())
549 35
                        ->append($this->getDynamicTemplateNode())
550 35
                        ->append($this->getSourceNode())
551 35
                        ->append($this->getRoutingNode())
552 35
                    ->end()
553 35
                ->end()
554 35
            ->end()
555
        ;
556 35
    }
557
}
558