Completed
Pull Request — master (#1343)
by Dmitry
09:10
created

Configuration::addIndexTemplatesSection()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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