Configuration::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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