Completed
Pull Request — master (#1569)
by
unknown
04:40
created

Configuration::getSerializerNode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 1

Importance

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