Completed
Push — master ( c6dba3...3cdfc2 )
by Maksim
05:14
created

FOSElasticaExtension::loadSerializer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0625

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 6
cts 8
cp 0.75
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 2
crap 2.0625
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\FileLocator;
15
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
16
use Symfony\Component\DependencyInjection\ContainerBuilder;
17
use Symfony\Component\DependencyInjection\DefinitionDecorator;
18
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
19
use Symfony\Component\DependencyInjection\Reference;
20
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
21
22
class FOSElasticaExtension extends Extension
23
{
24
    /**
25
     * Definition of elastica clients as configured by this extension.
26
     *
27
     * @var array
28
     */
29
    private $clients = [];
30
31
    /**
32
     * An array of indexes as configured by the extension.
33
     *
34
     * @var array
35
     */
36
    private $indexConfigs = [];
37
38
    /**
39
     * If we've encountered a type mapped to a specific persistence driver, it will be loaded
40
     * here.
41
     *
42
     * @var array
43
     */
44
    private $loadedDrivers = [];
45
46 13
    public function load(array $configs, ContainerBuilder $container)
47
    {
48 13
        $configuration = $this->getConfiguration($configs, $container);
49 13
        $config = $this->processConfiguration($configuration, $configs);
50
51 13
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
52
53 13
        if (empty($config['clients']) || empty($config['indexes'])) {
54
            // No Clients or indexes are defined
55
            return;
56
        }
57
58 13
        foreach (['config', 'index', 'persister', 'provider', 'source', 'transformer', 'event_listener'] as $basename) {
59 13
            $loader->load(sprintf('%s.xml', $basename));
60 13
        }
61
62 13
        if (empty($config['default_client'])) {
63 13
            $keys = array_keys($config['clients']);
64 13
            $config['default_client'] = reset($keys);
65 13
        }
66
67 13
        if (empty($config['default_index'])) {
68 13
            $keys = array_keys($config['indexes']);
69 13
            $config['default_index'] = reset($keys);
70 13
        }
71
72 13
        if (isset($config['serializer'])) {
73 1
            $loader->load('serializer.xml');
74
75 1
            $this->loadSerializer($config['serializer'], $container);
76 1
        }
77
78 13
        $this->loadClients($config['clients'], $container);
79 13
        $container->setAlias('fos_elastica.client', sprintf('fos_elastica.client.%s', $config['default_client']));
80
81 13
        $this->loadIndexes($config['indexes'], $container);
82 13
        $container->setAlias('fos_elastica.index', sprintf('fos_elastica.index.%s', $config['default_index']));
83 13
        $container->setParameter('fos_elastica.default_index', $config['default_index']);
84
85 13
        $container->getDefinition('fos_elastica.config_source.container')->replaceArgument(0, $this->indexConfigs);
86
87 13
        $this->loadIndexManager($container);
88
89 13
        $this->createDefaultManagerAlias($config['default_manager'], $container);
90 13
    }
91
92
    /**
93
     * @param array            $config
94
     * @param ContainerBuilder $container
95
     *
96
     * @return Configuration
97
     */
98 13
    public function getConfiguration(array $config, ContainerBuilder $container)
99
    {
100 13
        return new Configuration($container->getParameter('kernel.debug'));
101
    }
102
103
    /**
104
     * Loads the configured clients.
105
     *
106
     * @param array            $clients   An array of clients configurations
107
     * @param ContainerBuilder $container A ContainerBuilder instance
108
     *
109
     * @return array
110
     */
111 13
    private function loadClients(array $clients, ContainerBuilder $container)
112
    {
113 13
        foreach ($clients as $name => $clientConfig) {
114 13
            $clientId = sprintf('fos_elastica.client.%s', $name);
115
116 13
            $clientDef = new DefinitionDecorator('fos_elastica.client_prototype');
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
117 13
            $clientDef->replaceArgument(0, $clientConfig);
118
119 13
            $logger = $clientConfig['connections'][0]['logger'];
120 13
            if (false !== $logger) {
121 13
                $clientDef->addMethodCall('setLogger', [new Reference($logger)]);
122 13
            }
123
124 13
            $clientDef->addTag('fos_elastica.client');
125
126 13
            $container->setDefinition($clientId, $clientDef);
127
128 13
            $this->clients[$name] = [
129 13
                'id' => $clientId,
130 13
                'reference' => new Reference($clientId),
131
            ];
132 13
        }
133 13
    }
134
135
    /**
136
     * Loads the configured indexes.
137
     *
138
     * @param array            $indexes   An array of indexes configurations
139
     * @param ContainerBuilder $container A ContainerBuilder instance
140
     *
141
     * @throws \InvalidArgumentException
142
     *
143
     * @return array
144
     */
145 13
    private function loadIndexes(array $indexes, ContainerBuilder $container)
146
    {
147 13
        $indexableCallbacks = [];
148
149 13
        foreach ($indexes as $name => $index) {
150 13
            $indexId = sprintf('fos_elastica.index.%s', $name);
151 13
            $indexName = isset($index['index_name']) ? $index['index_name'] : $name;
152
153 13
            $indexDef = new DefinitionDecorator('fos_elastica.index_prototype');
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
154 13
            $indexDef->setFactory([new Reference('fos_elastica.client'), 'getIndex']);
155 13
            $indexDef->replaceArgument(0, $indexName);
156 13
            $indexDef->addTag('fos_elastica.index', [
157 13
                'name' => $name,
158 13
            ]);
159
160 13
            if (isset($index['client'])) {
161 2
                $client = $this->getClient($index['client']);
162
163 2
                $indexDef->setFactory([$client, 'getIndex']);
164 2
            }
165
166 13
            $container->setDefinition($indexId, $indexDef);
167 13
            $reference = new Reference($indexId);
168
169 13
            $this->indexConfigs[$name] = [
170 13
                'elasticsearch_name' => $indexName,
171 13
                'reference' => $reference,
172 13
                'name' => $name,
173 13
                'settings' => $index['settings'],
174 13
                'type_prototype' => isset($index['type_prototype']) ? $index['type_prototype'] : [],
175 13
                'use_alias' => $index['use_alias'],
176
            ];
177
178 13
            if ($index['finder']) {
179
                $this->loadIndexFinder($container, $name, $reference);
180
            }
181
182 13
            $this->loadTypes((array) $index['types'], $container, $this->indexConfigs[$name], $indexableCallbacks);
183 13
        }
184
185 13
        $indexable = $container->getDefinition('fos_elastica.indexable');
186 13
        $indexable->replaceArgument(0, $indexableCallbacks);
187 13
    }
188
189
    /**
190
     * Loads the configured index finders.
191
     *
192
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
193
     * @param string                                                  $name      The index name
194
     * @param Reference                                               $index     Reference to the related index
195
     *
196
     * @return string
197
     */
198
    private function loadIndexFinder(ContainerBuilder $container, $name, Reference $index)
199
    {
200
        /* Note: transformer services may conflict with "collection.index", if
201
         * an index and type names were "collection" and an index, respectively.
202
         */
203
        $transformerId = sprintf('fos_elastica.elastica_to_model_transformer.collection.%s', $name);
204
        $transformerDef = new DefinitionDecorator('fos_elastica.elastica_to_model_transformer.collection');
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
205
        $container->setDefinition($transformerId, $transformerDef);
206
207
        $finderId = sprintf('fos_elastica.finder.%s', $name);
208
        $finderDef = new DefinitionDecorator('fos_elastica.finder');
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
209
        $finderDef->replaceArgument(0, $index);
210
        $finderDef->replaceArgument(1, new Reference($transformerId));
211
212
        $container->setDefinition($finderId, $finderDef);
213
    }
214
215
    /**
216
     * Loads the configured types.
217
     *
218
     * @param array            $types
219
     * @param ContainerBuilder $container
220
     * @param array            $indexConfig
221
     * @param array            $indexableCallbacks
222
     */
223 13
    private function loadTypes(array $types, ContainerBuilder $container, array $indexConfig, array &$indexableCallbacks)
224
    {
225 13
        foreach ($types as $name => $type) {
226 13
            $indexName = $indexConfig['name'];
227
228 13
            $typeId = sprintf('%s.%s', $indexConfig['reference'], $name);
229 13
            $typeDef = new DefinitionDecorator('fos_elastica.type_prototype');
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
230 13
            $typeDef->setFactory([$indexConfig['reference'], 'getType']);
231 13
            $typeDef->replaceArgument(0, $name);
232
233 13
            $container->setDefinition($typeId, $typeDef);
234
235
            $typeConfig = [
236 13
                'name' => $name,
237 13
                'mapping' => [], // An array containing anything that gets sent directly to ElasticSearch
238 13
                'config' => [],
239 13
            ];
240
241
            foreach ([
242 13
                'dynamic_templates',
243 13
                'properties',
244 13
                '_all',
245 13
                '_id',
246 13
                '_parent',
247 13
                '_routing',
248 13
                '_source',
249 13
            ] as $field) {
250 13
                if (isset($type[$field])) {
251 13
                    $typeConfig['mapping'][$field] = $type[$field];
252 13
                }
253 13
            }
254
255
            foreach ([
256 13
                'persistence',
257 13
                'serializer',
258 13
                'analyzer',
259 13
                'search_analyzer',
260 13
                'dynamic',
261 13
                'date_detection',
262 13
                'dynamic_date_formats',
263 13
                'numeric_detection',
264 13
            ] as $field) {
265 13
                $typeConfig['config'][$field] = array_key_exists($field, $type) ?
266 13
                    $type[$field] :
267 13
                    null;
268 13
            }
269
270 13
            $this->indexConfigs[$indexName]['types'][$name] = $typeConfig;
271
272 13
            if (isset($type['persistence'])) {
273 12
                $this->loadTypePersistenceIntegration($type['persistence'], $container, new Reference($typeId), $indexName, $name);
274
275 12
                $typeConfig['persistence'] = $type['persistence'];
276 12
            }
277
278 13
            if (isset($type['_parent'])) {
279
                // _parent mapping cannot contain `property` and `identifier`, so removing them after building `persistence`
280 2
                unset($indexConfig['types'][$name]['mapping']['_parent']['property'], $indexConfig['types'][$name]['mapping']['_parent']['identifier']);
281 2
            }
282
283 13
            if (isset($type['indexable_callback'])) {
284 1
                $indexableCallbacks[sprintf('%s/%s', $indexName, $name)] = $type['indexable_callback'];
285 1
            }
286
287 13
            if ($container->hasDefinition('fos_elastica.serializer_callback_prototype')) {
288 1
                $typeSerializerId = sprintf('%s.serializer.callback', $typeId);
289 1
                $typeSerializerDef = new DefinitionDecorator('fos_elastica.serializer_callback_prototype');
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
290
291 1
                if (isset($type['serializer']['groups'])) {
292 1
                    $typeSerializerDef->addMethodCall('setGroups', [$type['serializer']['groups']]);
293 1
                }
294
295 1
                if (isset($type['serializer']['serialize_null'])) {
296 1
                    $typeSerializerDef->addMethodCall('setSerializeNull', [$type['serializer']['serialize_null']]);
297 1
                }
298
299 1
                if (isset($type['serializer']['version'])) {
300 1
                    $typeSerializerDef->addMethodCall('setVersion', [$type['serializer']['version']]);
301 1
                }
302
303 1
                $typeDef->addMethodCall('setSerializer', [[new Reference($typeSerializerId), 'serialize']]);
304 1
                $container->setDefinition($typeSerializerId, $typeSerializerDef);
305 1
            }
306 13
        }
307 13
    }
308
309
    /**
310
     * Loads the optional provider and finder for a type.
311
     *
312
     * @param array            $typeConfig
313
     * @param ContainerBuilder $container
314
     * @param Reference        $typeRef
315
     * @param string           $indexName
316
     * @param string           $typeName
317
     */
318 12
    private function loadTypePersistenceIntegration(array $typeConfig, ContainerBuilder $container, Reference $typeRef, $indexName, $typeName)
319
    {
320 12
        if (isset($typeConfig['driver'])) {
321 12
            $this->loadDriver($container, $typeConfig['driver']);
322 12
        }
323
324 12
        $elasticaToModelTransformerId = $this->loadElasticaToModelTransformer($typeConfig, $container, $indexName, $typeName);
325 12
        $modelToElasticaTransformerId = $this->loadModelToElasticaTransformer($typeConfig, $container, $indexName, $typeName);
326 12
        $objectPersisterId = $this->loadObjectPersister($typeConfig, $typeRef, $container, $indexName, $typeName, $modelToElasticaTransformerId);
327
328 12
        if (isset($typeConfig['provider'])) {
329 12
            $this->loadTypePagerProvider($typeConfig, $container, $indexName, $typeName);
330 12
        }
331 12
        if (isset($typeConfig['finder'])) {
332 12
            $this->loadTypeFinder($typeConfig, $container, $elasticaToModelTransformerId, $typeRef, $indexName, $typeName);
333 12
        }
334 12
        if (isset($typeConfig['listener'])) {
335 12
            $this->loadTypeListener($typeConfig, $container, $objectPersisterId, $indexName, $typeName);
336 12
        }
337 12
    }
338
339
    /**
340
     * Creates and loads an ElasticaToModelTransformer.
341
     *
342
     * @param array            $typeConfig
343
     * @param ContainerBuilder $container
344
     * @param string           $indexName
345
     * @param string           $typeName
346
     *
347
     * @return string
348
     */
349 12
    private function loadElasticaToModelTransformer(array $typeConfig, ContainerBuilder $container, $indexName, $typeName)
350
    {
351 12
        if (isset($typeConfig['elastica_to_model_transformer']['service'])) {
352 1
            return $typeConfig['elastica_to_model_transformer']['service'];
353
        }
354
355
        /* Note: transformer services may conflict with "prototype.driver", if
356
         * the index and type names were "prototype" and a driver, respectively.
357
         */
358 11
        $abstractId = sprintf('fos_elastica.elastica_to_model_transformer.prototype.%s', $typeConfig['driver']);
359 11
        $serviceId = sprintf('fos_elastica.elastica_to_model_transformer.%s.%s', $indexName, $typeName);
360 11
        $serviceDef = new DefinitionDecorator($abstractId);
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
361 11
        $serviceDef->addTag('fos_elastica.elastica_to_model_transformer', ['type' => $typeName, 'index' => $indexName]);
362
363
        // Doctrine has a mandatory service as first argument
364 11
        $argPos = ('propel' === $typeConfig['driver']) ? 0 : 1;
365
366 11
        $serviceDef->replaceArgument($argPos, $typeConfig['model']);
367 11
        $serviceDef->replaceArgument($argPos + 1, array_merge($typeConfig['elastica_to_model_transformer'], [
368 11
            'identifier' => $typeConfig['identifier'],
369 11
        ]));
370 11
        $container->setDefinition($serviceId, $serviceDef);
371
372 11
        return $serviceId;
373
    }
374
375
    /**
376
     * Creates and loads a ModelToElasticaTransformer for an index/type.
377
     *
378
     * @param array            $typeConfig
379
     * @param ContainerBuilder $container
380
     * @param string           $indexName
381
     * @param string           $typeName
382
     *
383
     * @return string
384
     */
385 12
    private function loadModelToElasticaTransformer(array $typeConfig, ContainerBuilder $container, $indexName, $typeName)
386
    {
387 12
        if (isset($typeConfig['model_to_elastica_transformer']['service'])) {
388
            return $typeConfig['model_to_elastica_transformer']['service'];
389
        }
390
391 12
        $abstractId = $container->hasDefinition('fos_elastica.serializer_callback_prototype') ?
392 12
            'fos_elastica.model_to_elastica_identifier_transformer' :
393 12
            'fos_elastica.model_to_elastica_transformer';
394
395 12
        $serviceId = sprintf('fos_elastica.model_to_elastica_transformer.%s.%s', $indexName, $typeName);
396 12
        $serviceDef = new DefinitionDecorator($abstractId);
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
397 12
        $serviceDef->replaceArgument(0, [
398 12
            'identifier' => $typeConfig['identifier'],
399 12
        ]);
400 12
        $container->setDefinition($serviceId, $serviceDef);
401
402 12
        return $serviceId;
403
    }
404
405
    /**
406
     * Creates and loads an object persister for a type.
407
     *
408
     * @param array            $typeConfig
409
     * @param Reference        $typeRef
410
     * @param ContainerBuilder $container
411
     * @param string           $indexName
412
     * @param string           $typeName
413
     * @param string           $transformerId
414
     *
415
     * @return string
416
     */
417 12
    private function loadObjectPersister(array $typeConfig, Reference $typeRef, ContainerBuilder $container, $indexName, $typeName, $transformerId)
418
    {
419 12
        if (isset($typeConfig['persister']['service'])) {
420 1
            return $typeConfig['persister']['service'];
421
        }
422
423
        $arguments = [
424 11
            $typeRef,
425 11
            new Reference($transformerId),
426 11
            $typeConfig['model'],
427 11
        ];
428
429 11
        if ($container->hasDefinition('fos_elastica.serializer_callback_prototype')) {
430 1
            $abstractId = 'fos_elastica.object_serializer_persister';
431 1
            $callbackId = sprintf('%s.%s.serializer.callback', $this->indexConfigs[$indexName]['reference'], $typeName);
432 1
            $arguments[] = [new Reference($callbackId), 'serialize'];
433 1
        } else {
434 10
            $abstractId = 'fos_elastica.object_persister';
435 10
            $mapping = $this->indexConfigs[$indexName]['types'][$typeName]['mapping'];
436 10
            $argument = $mapping['properties'];
437 10
            if (isset($mapping['_parent'])) {
438 1
                $argument['_parent'] = $mapping['_parent'];
439 1
            }
440 10
            $arguments[] = $argument;
441
        }
442
443 11
        $serviceId = sprintf('fos_elastica.object_persister.%s.%s', $indexName, $typeName);
444 11
        $serviceDef = new DefinitionDecorator($abstractId);
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
445 11
        foreach ($arguments as $i => $argument) {
446 11
            $serviceDef->replaceArgument($i, $argument);
447 11
        }
448
449 11
        $serviceDef->addTag('fos_elastica.persister', ['index' => $indexName, 'type' => $typeName]);
450
451 11
        $container->setDefinition($serviceId, $serviceDef);
452
453 11
        return $serviceId;
454
    }
455
456
    /**
457
     * Loads a pager provider for a type.
458
     *
459
     * @param array            $typeConfig
460
     * @param ContainerBuilder $container
461
     * @param string           $indexName
462
     * @param string           $typeName
463
     *
464
     * @return string
465
     */
466 12
    private function loadTypePagerProvider(array $typeConfig, ContainerBuilder $container, $indexName, $typeName)
467
    {
468 12
        if (isset($typeConfig['provider']['service'])) {
469
            return $typeConfig['provider']['service'];
470
        }
471
472 12
        $baseConfig = $typeConfig['provider'];
473 12
        unset($baseConfig['service']);
474
475 12
        $driver = $typeConfig['driver'];
476
477
        switch ($driver) {
478 12
            case 'orm':
479 6
                $providerDef = new DefinitionDecorator('fos_elastica.pager_provider.prototype.'.$driver);
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
480 6
                $providerDef->replaceArgument(2, $typeConfig['model']);
481 6
                $providerDef->replaceArgument(3, $baseConfig);
482
483 6
                break;
484 6 View Code Duplication
            case 'mongodb':
485 1
                $providerDef = new DefinitionDecorator('fos_elastica.pager_provider.prototype.'.$driver);
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
486 1
                $providerDef->replaceArgument(2, $typeConfig['model']);
487 1
                $providerDef->replaceArgument(3, $baseConfig);
488
489 1
                break;
490 5 View Code Duplication
            case 'phpcr':
491 1
                $providerDef = new DefinitionDecorator('fos_elastica.pager_provider.prototype.'.$driver);
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
492 1
                $providerDef->replaceArgument(2, $typeConfig['model']);
493 1
                $providerDef->replaceArgument(3, $baseConfig);
494
495 1
                break;
496 4 View Code Duplication
            case 'propel':
497 4
                $providerDef = new DefinitionDecorator('fos_elastica.pager_provider.prototype.'.$driver);
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
498 4
                $providerDef->replaceArgument(0, $typeConfig['model']);
499 4
                $providerDef->replaceArgument(1, $baseConfig);
500
501 4
                break;
502
            default:
503
                throw new \LogicException(sprintf('The pager provider for driver "%s" does not exist.', $driver));
504
        }
505
506
        /* Note: provider services may conflict with "prototype.driver", if the
507
         * index and type names were "prototype" and a driver, respectively.
508
         */
509 12
        $providerId = sprintf('fos_elastica.pager_provider.%s.%s', $indexName, $typeName);
510 12
        $providerDef->addTag('fos_elastica.pager_provider', ['index' => $indexName, 'type' => $typeName]);
511
512 12
        $container->setDefinition($providerId, $providerDef);
513
514 12
        return $providerId;
515
    }
516
517
    /**
518
     * Loads doctrine listeners to handle indexing of new or updated objects.
519
     *
520
     * @param array            $typeConfig
521
     * @param ContainerBuilder $container
522
     * @param string           $objectPersisterId
523
     * @param string           $indexName
524
     * @param string           $typeName
525
     *
526
     * @return string
527
     */
528 12
    private function loadTypeListener(array $typeConfig, ContainerBuilder $container, $objectPersisterId, $indexName, $typeName)
529
    {
530 12
        if (isset($typeConfig['listener']['service'])) {
531
            return $typeConfig['listener']['service'];
532
        }
533
534
        /* Note: listener services may conflict with "prototype.driver", if the
535
         * index and type names were "prototype" and a driver, respectively.
536
         */
537 12
        $abstractListenerId = sprintf('fos_elastica.listener.prototype.%s', $typeConfig['driver']);
538 12
        $listenerId = sprintf('fos_elastica.listener.%s.%s', $indexName, $typeName);
539 12
        $listenerDef = new DefinitionDecorator($abstractListenerId);
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
540 12
        $listenerDef->replaceArgument(0, new Reference($objectPersisterId));
541 12
        $listenerDef->replaceArgument(3, $typeConfig['listener']['logger'] ?
542 12
            new Reference($typeConfig['listener']['logger']) :
543
            null
544 12
        );
545
        $listenerConfig = [
546 12
            'identifier' => $typeConfig['identifier'],
547 12
            'indexName' => $indexName,
548 12
            'typeName' => $typeName,
549 12
        ];
550
551 12
        $tagName = null;
552 12
        switch ($typeConfig['driver']) {
553 12
            case 'orm':
554 6
                $tagName = 'doctrine.event_listener';
555 6
                break;
556 6
            case 'phpcr':
557 1
                $tagName = 'doctrine_phpcr.event_listener';
558 1
                break;
559 5
            case 'mongodb':
560 1
                $tagName = 'doctrine_mongodb.odm.event_listener';
561 1
                break;
562 12
        }
563
564 12
        if ($typeConfig['listener']['defer']) {
565
            $listenerDef->setPublic(true);
566
            $listenerDef->addTag(
567
                'kernel.event_listener',
568
                ['event' => 'kernel.terminate', 'method' => 'onTerminate']
569
            );
570
            $listenerDef->addTag(
571
                'kernel.event_listener',
572
                ['event' => 'console.terminate', 'method' => 'onTerminate']
573
            );
574
            $listenerConfig['defer'] = true;
575
        }
576
577 12
        $listenerDef->replaceArgument(2, $listenerConfig);
578
579 12
        if (null !== $tagName) {
580 8
            foreach ($this->getDoctrineEvents($typeConfig) as $event) {
581 8
                $listenerDef->addTag($tagName, ['event' => $event]);
582 8
            }
583 8
        }
584
585 12
        $container->setDefinition($listenerId, $listenerDef);
586
587 12
        return $listenerId;
588
    }
589
590
    /**
591
     * Map Elastica to Doctrine events for the current driver.
592
     */
593 8
    private function getDoctrineEvents(array $typeConfig)
594
    {
595 8
        switch ($typeConfig['driver']) {
596 8
            case 'orm':
597 6
                $eventsClass = '\Doctrine\ORM\Events';
598 6
                break;
599 2
            case 'phpcr':
600 1
                $eventsClass = '\Doctrine\ODM\PHPCR\Event';
601 1
                break;
602 1
            case 'mongodb':
603 1
                $eventsClass = '\Doctrine\ODM\MongoDB\Events';
604 1
                break;
605
            default:
606
                throw new \InvalidArgumentException(sprintf('Cannot determine events for driver "%s"', $typeConfig['driver']));
607 8
        }
608
609 8
        $events = [];
610
        $eventMapping = [
611 8
            'insert' => [constant($eventsClass.'::postPersist')],
612 8
            'update' => [constant($eventsClass.'::postUpdate')],
613 8
            'delete' => [constant($eventsClass.'::preRemove')],
614 8
            'flush' => [constant($eventsClass.'::postFlush')],
615 8
        ];
616
617 8
        foreach ($eventMapping as $event => $doctrineEvents) {
618 8
            if (isset($typeConfig['listener'][$event]) && $typeConfig['listener'][$event]) {
619 8
                $events = array_merge($events, $doctrineEvents);
620 8
            }
621 8
        }
622
623 8
        return $events;
624
    }
625
626
    /**
627
     * Loads a Type specific Finder.
628
     *
629
     * @param array            $typeConfig
630
     * @param ContainerBuilder $container
631
     * @param string           $elasticaToModelId
632
     * @param Reference        $typeRef
633
     * @param string           $indexName
634
     * @param string           $typeName
635
     *
636
     * @return string
637
     */
638 12
    private function loadTypeFinder(array $typeConfig, ContainerBuilder $container, $elasticaToModelId, Reference $typeRef, $indexName, $typeName)
639
    {
640 12
        if (isset($typeConfig['finder']['service'])) {
641
            $finderId = $typeConfig['finder']['service'];
642
        } else {
643 12
            $finderId = sprintf('fos_elastica.finder.%s.%s', $indexName, $typeName);
644 12
            $finderDef = new DefinitionDecorator('fos_elastica.finder');
0 ignored issues
show
Deprecated Code introduced by
The class Symfony\Component\Depend...ion\DefinitionDecorator has been deprecated with message: The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.

This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.

Loading history...
645 12
            $finderDef->replaceArgument(0, $typeRef);
646 12
            $finderDef->replaceArgument(1, new Reference($elasticaToModelId));
647 12
            $container->setDefinition($finderId, $finderDef);
648
        }
649
650 12
        $indexTypeName = "$indexName/$typeName";
651 12
        $arguments = [$indexTypeName, new Reference($finderId)];
652 12
        if (isset($typeConfig['repository'])) {
653 1
            $arguments[] = $typeConfig['repository'];
654 1
        }
655
656 12
        $container->getDefinition('fos_elastica.repository_manager')
657 12
            ->addMethodCall('addType', $arguments);
658
659 12
        $managerId = sprintf('fos_elastica.manager.%s', $typeConfig['driver']);
660 12
        $container->getDefinition($managerId)
661 12
            ->addMethodCall('addEntity', [$typeConfig['model'], $indexTypeName]);
662
663 12
        return $finderId;
664
    }
665
666
    /**
667
     * Loads the index manager.
668
     *
669
     * @param ContainerBuilder $container
670
     **/
671
    private function loadIndexManager(ContainerBuilder $container)
672
    {
673 13
        $indexRefs = array_map(function ($index) {
674 13
            return $index['reference'];
675 13
        }, $this->indexConfigs);
676
677 13
        $managerDef = $container->getDefinition('fos_elastica.index_manager');
678 13
        $managerDef->replaceArgument(0, $indexRefs);
679 13
    }
680
681
    /**
682
     * Makes sure a specific driver has been loaded.
683
     *
684
     * @param ContainerBuilder $container
685
     * @param string           $driver
686
     */
687 12
    private function loadDriver(ContainerBuilder $container, $driver)
688
    {
689 12
        if (in_array($driver, $this->loadedDrivers)) {
690 3
            return;
691
        }
692
693 12
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
694 12
        $loader->load($driver.'.xml');
695 12
        $this->loadedDrivers[] = $driver;
696 12
    }
697
698
    /**
699
     * Loads and configures the serializer prototype.
700
     *
701
     * @param array            $config
702
     * @param ContainerBuilder $container
703
     */
704 1
    private function loadSerializer($config, ContainerBuilder $container)
705
    {
706 1
        $container->setAlias('fos_elastica.serializer', $config['serializer']);
707
708 1
        $serializer = $container->getDefinition('fos_elastica.serializer_callback_prototype');
709 1
        $serializer->setClass($config['callback_class']);
710
711 1
        if (is_subclass_of($config['callback_class'], ContainerAwareInterface::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Symfony\Component\Depen...erAwareInterface::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
712
            $serializer->addMethodCall('setContainer', [new Reference('service_container')]);
713
        }
714 1
    }
715
716
    /**
717
     * Creates a default manager alias for defined default manager or the first loaded driver.
718
     *
719
     * @param string           $defaultManager
720
     * @param ContainerBuilder $container
721
     */
722 13
    private function createDefaultManagerAlias($defaultManager, ContainerBuilder $container)
723
    {
724 13
        if (0 == count($this->loadedDrivers)) {
725 1
            return;
726
        }
727
728 12
        if (count($this->loadedDrivers) > 1
729 12
            && in_array($defaultManager, $this->loadedDrivers)
730 12
        ) {
731
            $defaultManagerService = $defaultManager;
732
        } else {
733 12
            $defaultManagerService = $this->loadedDrivers[0];
734
        }
735
736 12
        $container->setAlias('fos_elastica.manager', sprintf('fos_elastica.manager.%s', $defaultManagerService));
737 12
    }
738
739
    /**
740
     * Returns a reference to a client given its configured name.
741
     *
742
     * @param string $clientName
743
     *
744
     * @return Reference
745
     *
746
     * @throws \InvalidArgumentException
747
     */
748 2
    private function getClient($clientName)
749
    {
750 2
        if (!array_key_exists($clientName, $this->clients)) {
751
            throw new \InvalidArgumentException(sprintf('The elastica client with name "%s" is not defined', $clientName));
752
        }
753
754 2
        return $this->clients[$clientName]['reference'];
755
    }
756
}
757