Completed
Pull Request — master (#1569)
by
unknown
03:33
created

FOSElasticaExtension::loadIndexPagerProvider()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5.0291

Importance

Changes 0
Metric Value
dl 0
loc 33
ccs 17
cts 19
cp 0.8947
rs 9.0808
c 0
b 0
f 0
cc 5
nc 5
nop 3
crap 5.0291
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 Elastica\Client as ElasticaClient;
15
use FOS\ElasticaBundle\Elastica\Client;
16
use FOS\ElasticaBundle\Manager\RepositoryManagerInterface;
17
use Symfony\Component\Config\FileLocator;
18
use Symfony\Component\DependencyInjection\Alias;
19
use Symfony\Component\DependencyInjection\ChildDefinition;
20
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
21
use Symfony\Component\DependencyInjection\ContainerBuilder;
22
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
23
use Symfony\Component\DependencyInjection\Reference;
24
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
25
26
class FOSElasticaExtension extends Extension
27
{
28
    /**
29
     * Definition of elastica clients as configured by this extension.
30
     *
31
     * @var array
32
     */
33
    private $clients = [];
34
35
    /**
36
     * An array of indexes as configured by the extension.
37
     *
38
     * @var array
39
     */
40
    private $indexConfigs = [];
41
42
    /**
43
     * An array of index templates as configured by the extension.
44
     *
45
     * @var array
46
     */
47
    private $indexTemplateConfigs = array();
48
49
    /**
50
     * If we've encountered a type mapped to a specific persistence driver, it will be loaded
51
     * here.
52
     *
53
     * @var array
54
     */
55
    private $loadedDrivers = [];
56
57 20
    public function load(array $configs, ContainerBuilder $container)
58
    {
59 20
        $configuration = $this->getConfiguration($configs, $container);
60 20
        $config = $this->processConfiguration($configuration, $configs);
61
62 20
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
63
64 20
        if (empty($config['clients']) || empty($config['indexes'])) {
65
            // No Clients or indexes are defined
66
            return;
67
        }
68
69 20
        foreach (['config', 'index', 'persister', 'provider', 'source', 'transformer', 'event_listener', 'commands'] as $basename) {
70 20
            $loader->load(sprintf('%s.xml', $basename));
71
        }
72
73 20
        if (empty($config['default_client'])) {
74 20
            $keys = array_keys($config['clients']);
75 20
            $config['default_client'] = reset($keys);
76
        }
77
78 20
        if (empty($config['default_index'])) {
79 20
            $keys = array_keys($config['indexes']);
80 20
            $config['default_index'] = reset($keys);
81
        }
82
83 20
        if (isset($config['serializer'])) {
84 1
            $loader->load('serializer.xml');
85
86 1
            $this->loadSerializer($config['serializer'], $container);
87
        }
88
89 20
        $this->loadClients($config['clients'], $container);
90 20
        $container->setAlias('fos_elastica.client', sprintf('fos_elastica.client.%s', $config['default_client']));
91 20
        $container->getAlias('fos_elastica.client')->setPublic(true);
92 20
        $container->setAlias(ElasticaClient::class, new Alias('fos_elastica.client', false));
93 20
        $container->setAlias(Client::class, 'fos_elastica.client');
94 20
        $container->getAlias(Client::class)->setPublic(false);
95
96 20
        $this->loadIndexes($config['indexes'], $container);
97 20
        $container->setAlias('fos_elastica.index', sprintf('fos_elastica.index.%s', $config['default_index']));
98 20
        $container->getAlias('fos_elastica.index')->setPublic(true);
99 20
        $container->setParameter('fos_elastica.default_index', $config['default_index']);
100
101 20
        if ($usedIndexNames = \array_intersect_key($config['indexes'], $config['index_templates'])) {
102
            throw new \DomainException(
103
                \sprintf(
104
                    'Index names "%s" are already in use and can not be used for index templates names',
105
                    \implode('","', \array_keys($usedIndexNames))
106
                )
107
            );
108
        }
109 20
        $this->loadIndexTemplates($config['index_templates'], $container);
110
111 20
        $container->getDefinition('fos_elastica.config_source.container')->replaceArgument(0, $this->indexConfigs);
112
        $container
113 20
            ->getDefinition('fos_elastica.config_source.template_container')
114 20
            ->replaceArgument(0, $this->indexTemplateConfigs);
115
116 20
        $this->loadIndexManager($container);
117 20
        $this->loadIndexTemplateManager($container);
118
119 20
        $this->createDefaultManagerAlias($config['default_manager'], $container);
120 20
    }
121
122
    /**
123
     * @param array            $config
124
     * @param ContainerBuilder $container
125
     *
126
     * @return Configuration
127
     */
128 20
    public function getConfiguration(array $config, ContainerBuilder $container)
129
    {
130 20
        return new Configuration($container->getParameter('kernel.debug'));
131
    }
132
133
    /**
134
     * Loads the configured clients.
135
     *
136
     * @param array            $clients   An array of clients configurations
137
     * @param ContainerBuilder $container A ContainerBuilder instance
138
     *
139
     * @return array
140
     */
141 20
    private function loadClients(array $clients, ContainerBuilder $container)
142
    {
143 20
        foreach ($clients as $name => $clientConfig) {
144 20
            $clientId = sprintf('fos_elastica.client.%s', $name);
145
146 20
            $clientDef = new ChildDefinition('fos_elastica.client_prototype');
147 20
            $clientDef->replaceArgument(0, $clientConfig);
148 20
            $clientDef->replaceArgument(1, null);
149
150 20
            $logger = $clientConfig['connections'][0]['logger'];
151 20
            if (false !== $logger) {
152 20
                $clientDef->addMethodCall('setLogger', [new Reference($logger)]);
153
            }
154
155 20
            $clientDef->addTag('fos_elastica.client');
156
157 20
            $container->setDefinition($clientId, $clientDef);
158
159 20
            $this->clients[$name] = [
160 20
                'id' => $clientId,
161 20
                'reference' => new Reference($clientId),
162
            ];
163
        }
164 20
    }
165
166
    /**
167
     * Loads the configured indexes.
168
     *
169
     * @param array            $indexes   An array of indexes configurations
170
     * @param ContainerBuilder $container A ContainerBuilder instance
171
     *
172
     * @throws \InvalidArgumentException
173
     *
174
     * @return array
175
     */
176 20
    private function loadIndexes(array $indexes, ContainerBuilder $container)
177
    {
178 20
        $indexableCallbacks = [];
179
180 20
        foreach ($indexes as $name => $index) {
181 20
            $indexId = sprintf('fos_elastica.index.%s', $name);
182 20
            $indexName = isset($index['index_name']) ? $index['index_name'] : $name;
183
184 20
            $indexDef = new ChildDefinition('fos_elastica.index_prototype');
185 20
            $indexDef->setFactory([new Reference('fos_elastica.client'), 'getIndex']);
186 20
            $indexDef->replaceArgument(0, $indexName);
187 20
            $indexDef->addTag('fos_elastica.index', [
188 20
                'name' => $name,
189
            ]);
190
191 20 View Code Duplication
            if (isset($index['client'])) {
192 1
                $client = $this->getClient($index['client']);
193
194 1
                $indexDef->setFactory([$client, 'getIndex']);
195
            }
196
197 20
            $container->setDefinition($indexId, $indexDef);
198 20
            $reference = new Reference($indexId);
199
200 20
            $this->indexConfigs[$name] = [
201 20
                'elasticsearch_name' => $indexName,
202 20
                'reference' => $reference,
203 20
                'model' => $index['persistence']['model'] ?? null,
204 20
                'name' => $name,
205 20
                'settings' => $index['settings'],
206 20
                'type_prototype' => isset($index['type_prototype']) ? $index['type_prototype'] : [],
207 20
                'use_alias' => $index['use_alias'],
208
            ];
209
210 20
            if ($index['finder']) {
211
                $this->loadIndexFinder($container, $name, $reference);
212
            }
213
214 20
            $this->loadIndexConfig((array) $index, $this->indexConfigs[$name]);
215
216 20
            if (isset($index['indexable_callback'])) {
217 4
                $indexableCallbacks[$name] = $this->buildCallback($index['indexable_callback'], $name);
218
            }
219
220 20
            $this->loadIndexSerializerIntegration($index['serializer'] ?? [], $container, $reference);
221
222 20
            if (isset($index['persistence'])) {
223 14
                $this->loadIndexPersistenceIntegration($index['persistence'], $container, $reference, $name);
224
            }
225
        }
226
227 20
        $indexable = $container->getDefinition('fos_elastica.indexable');
228 20
        $indexable->replaceArgument(0, $indexableCallbacks);
229 20
    }
230
231
    /**
232
     * Loads the configured indexes.
233
     *
234
     * @param array            $indexTemplates   An array of indexes configurations
235
     * @param ContainerBuilder $container A ContainerBuilder instance
236
     *
237
     * @throws \InvalidArgumentException
238
     *
239
     * @return void
240
     */
241 20
    private function loadIndexTemplates(array $indexTemplates, ContainerBuilder $container)
242
    {
243 20
        foreach ($indexTemplates as $name => $indexTemplate) {
244 6
            $indexId = sprintf('fos_elastica.index_template.%s', $name);
245 6
            $indexTemplateName = isset($indexTemplate['template_name']) ? $indexTemplate['template_name'] : $name;
246
247 6
            $indexDef = new ChildDefinition('fos_elastica.index_template_prototype');
248 6
            $indexDef->setFactory([new Reference('fos_elastica.client'), 'getIndexTemplate']);
249 6
            $indexDef->replaceArgument(0, $indexTemplateName);
250 6
            $indexDef->addTag('fos_elastica.index_template', array(
251 6
                'name' => $name,
252
            ));
253
254 6 View Code Duplication
            if (isset($indexTemplate['client'])) {
255 6
                $client = $this->getClient($indexTemplate['client']);
256 6
                $indexDef->setFactory([$client, 'getIndexTemplate']);
257
            }
258
259 6
            $container->setDefinition($indexId, $indexDef);
260 6
            $reference = new Reference($indexId);
261
262 6
            $this->indexTemplateConfigs[$name] = array(
263 6
                'elasticsearch_name' => $indexTemplateName,
264 6
                'reference' => $reference,
265 6
                'name' => $name,
266 6
                'settings' => $indexTemplate['settings'],
267 6
                'template' => $indexTemplate['template'],
268
            );
269
270 6
            $this->loadIndexConfig((array) $indexTemplate, $this->indexTemplateConfigs[$name]);
271
        }
272 20
    }
273
274
    /**
275
     * Loads the configured index finders.
276
     *
277
     * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
278
     * @param string                                                  $name      The index name
279
     * @param Reference                                               $index     Reference to the related index
280
     *
281
     * @return string
282
     */
283
    private function loadIndexFinder(ContainerBuilder $container, string $name, Reference $index): void
284
    {
285
        $finderId = sprintf('fos_elastica.finder.%s', $name);
286
        $finderDef = new ChildDefinition('fos_elastica.finder');
287
        $finderDef->replaceArgument(0, $index);
288
        $finderDef->replaceArgument(1, new Reference(sprintf('fos_elastica.elastica_to_model_transformer.%s', $name)));
289
290
        $container->setDefinition($finderId, $finderDef);
291
    }
292
293
    /**
294
     * Loads the configured $index.
295
     */
296 20
    private function loadIndexConfig(array $index, array &$indexConfig): void
297
    {
298 20
        $indexConfig = array_merge($indexConfig, [
299 20
            'mapping' => [], // An array containing anything that gets sent directly to ElasticSearch
300
            'config' => [],
301
        ]);
302
303
        foreach ([
304 20
            'dynamic_templates',
305
            'properties',
306
            '_id',
307
            '_routing',
308
            '_source',
309
        ] as $field) {
310 20
            if (isset($index[$field])) {
311 20
                $indexConfig['mapping'][$field] = $index[$field];
312
            }
313
        }
314
315
        foreach ([
316 20
            'analyzer',
317
            'search_analyzer',
318
            'dynamic',
319
            'date_detection',
320
            'dynamic_date_formats',
321
            'numeric_detection',
322
        ] as $field) {
323 20
            $indexConfig['config'][$field] = array_key_exists($field, $index) ? $index[$field] : null;
324
        }
325 20
    }
326
327 4
    private function buildCallback($indexCallback, $indexName)
328
    {
329 4
        if (is_array($indexCallback)) {
330 4
            if (!isset($indexCallback[0])) {
331
                throw new \InvalidArgumentException(sprintf('Invalid indexable_callback for index %s', $indexName));
332
            }
333
334 4
            $classOrServiceRef = $this->transformServiceReference($indexCallback[0]);
335 4
            if ($classOrServiceRef instanceof Reference && !isset($indexCallback[1])) {
336
                return $classOrServiceRef; // __invoke
337
            }
338
339 4
            if (!isset($indexCallback[1])) {
340
                throw new \InvalidArgumentException(sprintf('Invalid indexable_callback for index %s', $indexName));
341
            }
342
343 4
            return [$classOrServiceRef, $indexCallback[1]];
344
        }
345
346 4
        if (is_string($indexCallback)) {
347 4
            return $this->transformServiceReference($indexCallback);
348
        }
349
350
        throw new \InvalidArgumentException(sprintf('Invalid indexable_callback for index %s', $indexName));
351
    }
352
353 4
    private function transformServiceReference($classOrService)
354
    {
355 4
        return 0 === strpos($classOrService, '@') ? new Reference(substr($classOrService, 1)) : $classOrService;
356
    }
357
358 20
    private function loadIndexSerializerIntegration(array $config, ContainerBuilder $container, Reference $indexRef): void
359
    {
360 20
        if ($container->hasDefinition('fos_elastica.serializer_callback_prototype')) {
361 1
            $indexSerializerId = sprintf('%s.serializer.callback', $indexRef);
362 1
            $indexSerializerDef = new ChildDefinition('fos_elastica.serializer_callback_prototype');
363
364 1
            if (isset($config['groups'])) {
365 1
                $indexSerializerDef->addMethodCall('setGroups', [$config['groups']]);
366
            }
367
368 1
            if (isset($config['serialize_null'])) {
369 1
                $indexSerializerDef->addMethodCall('setSerializeNull', [$config['serialize_null']]);
370
            }
371
372 1
            if (isset($config['version'])) {
373 1
                $indexSerializerDef->addMethodCall('setVersion', [$config['version']]);
374
            }
375
376 1
            $container->setDefinition($indexSerializerId, $indexSerializerDef);
377
        }
378 20
    }
379
380
    /**
381
     * Loads the optional provider and finder for a type.
382
     */
383 14
    private function loadIndexPersistenceIntegration(array $config, ContainerBuilder $container, Reference $indexRef, string $indexName): void
384
    {
385 14
        if (isset($config['driver'])) {
386 14
            $this->loadDriver($container, $config['driver']);
387
        }
388
389 14
        $elasticaToModelTransformerId = $this->loadElasticaToModelTransformer($config, $container, $indexName);
390 14
        $modelToElasticaTransformerId = $this->loadModelToElasticaTransformer($config, $container, $indexName);
391 14
        $objectPersisterId = $this->loadObjectPersister($config, $indexRef, $container, $indexName, $modelToElasticaTransformerId);
392
393 14
        if (isset($config['provider'])) {
394 14
            $this->loadIndexPagerProvider($config, $container, $indexName);
395
        }
396 14
        if (isset($config['finder'])) {
397 14
            $this->loadTypeFinder($config, $container, $elasticaToModelTransformerId, $indexRef, $indexName);
398
        }
399 14
        if (isset($config['listener']) && $config['listener']['enabled']) {
400 13
            $this->loadIndexListener($config, $container, $objectPersisterId, $indexName);
401
        }
402 14
    }
403
404
    /**
405
     * Creates and loads an ElasticaToModelTransformer.
406
     */
407 14
    private function loadElasticaToModelTransformer(array $persistenceConfig, ContainerBuilder $container, string $indexName): string
408
    {
409 14
        if (isset($persistenceConfig['elastica_to_model_transformer']['service'])) {
410 1
            return $persistenceConfig['elastica_to_model_transformer']['service'];
411
        }
412
413
        /* Note: transformer services may conflict with "prototype.driver", if
414
         * the index and type names were "prototype" and a driver, respectively.
415
         */
416 13
        $abstractId = sprintf('fos_elastica.elastica_to_model_transformer.prototype.%s', $persistenceConfig['driver']);
417 13
        $serviceId = sprintf('fos_elastica.elastica_to_model_transformer.%s', $indexName);
418 13
        $serviceDef = new ChildDefinition($abstractId);
419 13
        $serviceDef->addTag('fos_elastica.elastica_to_model_transformer', ['index' => $indexName]);
420
421 13
        $serviceDef->replaceArgument(1, $persistenceConfig['model']);
422 13
        $serviceDef->replaceArgument(2, array_merge($persistenceConfig['elastica_to_model_transformer'], [
423 13
            'identifier' => $persistenceConfig['identifier'],
424
        ]));
425 13
        $container->setDefinition($serviceId, $serviceDef);
426
427 13
        return $serviceId;
428
    }
429
430
    /**
431
     * Creates and loads a ModelToElasticaTransformer for an index.
432
     */
433 14
    private function loadModelToElasticaTransformer(array $config, ContainerBuilder $container, string $indexName): string
434
    {
435 14
        if (isset($config['model_to_elastica_transformer']['service'])) {
436
            return $config['model_to_elastica_transformer']['service'];
437
        }
438
439 14
        $abstractId = $container->hasDefinition('fos_elastica.serializer_callback_prototype') ?
440 1
            'fos_elastica.model_to_elastica_identifier_transformer' :
441 14
            'fos_elastica.model_to_elastica_transformer';
442
443 14
        $serviceId = sprintf('fos_elastica.model_to_elastica_transformer.%s', $indexName);
444 14
        $serviceDef = new ChildDefinition($abstractId);
445 14
        $serviceDef->replaceArgument(0, [
446 14
            'identifier' => $config['identifier'],
447 14
            'index' => $indexName,
448
        ]);
449 14
        $container->setDefinition($serviceId, $serviceDef);
450
451 14
        return $serviceId;
452
    }
453
454
    /**
455
     * Creates and loads an object persister for a index.
456
     */
457 14
    private function loadObjectPersister(array $config, Reference $indexRef, ContainerBuilder $container, string $indexName, string $transformerId): string
458
    {
459 14
        if (isset($config['persister']['service'])) {
460 1
            return $config['persister']['service'];
461
        }
462
463
        $arguments = [
464 13
            $indexRef,
465 13
            new Reference($transformerId),
466 13
            $config['model'],
467
        ];
468
469 13
        if ($container->hasDefinition('fos_elastica.serializer_callback_prototype')) {
470 1
            $abstractId = 'fos_elastica.object_serializer_persister';
471 1
            $callbackId = sprintf('%s.serializer.callback', $indexRef);
472 1
            $arguments[] = [new Reference($callbackId), 'serialize'];
473
        } else {
474 12
            $abstractId = 'fos_elastica.object_persister';
475 12
            $mapping = $this->indexConfigs[$indexName]['mapping'];
476 12
            $argument = $mapping['properties'];
477 12
            $arguments[] = $argument;
478
        }
479
480 13
        $arguments[] = array_intersect_key($config['persister'], array_flip(['refresh']));
481
482 13
        $serviceId = sprintf('fos_elastica.object_persister.%s', $indexName);
483 13
        $serviceDef = new ChildDefinition($abstractId);
484 13
        foreach ($arguments as $i => $argument) {
485 13
            $serviceDef->replaceArgument($i, $argument);
486
        }
487
488 13
        $serviceDef->addTag('fos_elastica.persister', ['index' => $indexName]);
489
490 13
        $container->setDefinition($serviceId, $serviceDef);
491
492 13
        return $serviceId;
493
    }
494
495
    /**
496
     * Loads a pager provider for a index.
497
     */
498 14
    private function loadIndexPagerProvider(array $indexConfig, ContainerBuilder $container, string $indexName): string
499
    {
500 14
        if (isset($indexConfig['provider']['service'])) {
501
            return $indexConfig['provider']['service'];
502
        }
503
504 14
        $baseConfig = $indexConfig['provider'];
505 14
        unset($baseConfig['service']);
506
507 14
        $driver = $indexConfig['driver'];
508
509 14
        switch ($driver) {
510 14
            case 'orm':
511 1
            case 'mongodb':
512 1
            case 'phpcr':
513 14
                $providerDef = new ChildDefinition('fos_elastica.pager_provider.prototype.'.$driver);
514 14
                $providerDef->replaceArgument(2, $indexConfig['model']);
515 14
                $providerDef->replaceArgument(3, $baseConfig);
516 14
                break;
517
            default:
518
                throw new \LogicException(sprintf('The pager provider for driver "%s" does not exist.', $driver));
519
        }
520
521
        /* Note: provider services may conflict with "prototype.driver", if the
522
         * index and type names were "prototype" and a driver, respectively.
523
         */
524 14
        $providerId = sprintf('fos_elastica.pager_provider.%s', $indexName);
525 14
        $providerDef->addTag('fos_elastica.pager_provider', ['index' => $indexName]);
526
527 14
        $container->setDefinition($providerId, $providerDef);
528
529 14
        return $providerId;
530
    }
531
532
    /**
533
     * Loads doctrine listeners to handle indexing of new or updated objects.
534
     */
535 13
    private function loadIndexListener(array $indexConfig, ContainerBuilder $container, string $objectPersisterId, string $indexName): string
536
    {
537 13
        if (isset($indexConfig['listener']['service'])) {
538
            return $indexConfig['listener']['service'];
539
        }
540
541
        /* Note: listener services may conflict with "prototype.driver", if the
542
         * index names were "prototype" and a driver, respectively.
543
         */
544 13
        $abstractListenerId = sprintf('fos_elastica.listener.prototype.%s', $indexConfig['driver']);
545 13
        $listenerId = sprintf('fos_elastica.listener.%s', $indexName);
546 13
        $listenerDef = new ChildDefinition($abstractListenerId);
547 13
        $listenerDef->replaceArgument(0, new Reference($objectPersisterId));
548 13
        $listenerDef->replaceArgument(3, $indexConfig['listener']['logger'] ?
549
            new Reference($indexConfig['listener']['logger']) :
550 13
            null
551
        );
552
        $listenerConfig = [
553 13
            'identifier' => $indexConfig['identifier'],
554 13
            'indexName' => $indexName,
555
        ];
556
557 13
        $tagName = null;
558 13
        switch ($indexConfig['driver']) {
559 13
            case 'orm':
560 12
                $tagName = 'doctrine.event_listener';
561 12
                break;
562 1
            case 'phpcr':
563 1
                $tagName = 'doctrine_phpcr.event_listener';
564 1
                break;
565
            case 'mongodb':
566
                $tagName = 'doctrine_mongodb.odm.event_listener';
567
                break;
568
        }
569
570 13
        if ($indexConfig['listener']['defer']) {
571
            $listenerDef->setPublic(true);
572
            $listenerDef->addTag(
573
                'kernel.event_listener',
574
                ['event' => 'kernel.terminate', 'method' => 'onTerminate']
575
            );
576
            $listenerDef->addTag(
577
                'kernel.event_listener',
578
                ['event' => 'console.terminate', 'method' => 'onTerminate']
579
            );
580
            $listenerConfig['defer'] = true;
581
        }
582
583 13
        $listenerDef->replaceArgument(2, $listenerConfig);
584
585 13
        if (null !== $tagName) {
586 13
            foreach ($this->getDoctrineEvents($indexConfig) as $event) {
587 13
                $listenerDef->addTag($tagName, ['event' => $event]);
588
            }
589
        }
590
591 13
        $container->setDefinition($listenerId, $listenerDef);
592
593 13
        return $listenerId;
594
    }
595
596
    /**
597
     * Map Elastica to Doctrine events for the current driver.
598
     */
599 13
    private function getDoctrineEvents(array $indexConfig)
600
    {
601 13
        switch ($indexConfig['driver']) {
602 13
            case 'orm':
603 12
                $eventsClass = '\Doctrine\ORM\Events';
604 12
                break;
605 1
            case 'phpcr':
606 1
                $eventsClass = '\Doctrine\ODM\PHPCR\Event';
607 1
                break;
608
            case 'mongodb':
609
                $eventsClass = '\Doctrine\ODM\MongoDB\Events';
610
                break;
611
            default:
612
                throw new \InvalidArgumentException(sprintf('Cannot determine events for driver "%s"', $indexConfig['driver']));
613
        }
614
615 13
        $events = [];
616
        $eventMapping = [
617 13
            'insert' => [constant($eventsClass.'::postPersist')],
618 13
            'update' => [constant($eventsClass.'::postUpdate')],
619 13
            'delete' => [constant($eventsClass.'::preRemove')],
620 13
            'flush' => [constant($eventsClass.'::postFlush')],
621
        ];
622
623 13
        foreach ($eventMapping as $event => $doctrineEvents) {
624 13
            if (isset($indexConfig['listener'][$event]) && $indexConfig['listener'][$event]) {
625 13
                $events = array_merge($events, $doctrineEvents);
626
            }
627
        }
628
629 13
        return $events;
630
    }
631
632
    /**
633
     * Loads a Type specific Finder.
634
     */
635 14
    private function loadTypeFinder(array $typeConfig, ContainerBuilder $container, string $elasticaToModelId, Reference $indexRef, string $indexName): string
636
    {
637 14
        if (isset($typeConfig['finder']['service'])) {
638
            $finderId = $typeConfig['finder']['service'];
639
        } else {
640 14
            $finderId = sprintf('fos_elastica.finder.%s', $indexName);
641 14
            $finderDef = new ChildDefinition('fos_elastica.finder');
642 14
            $finderDef->replaceArgument(0, $indexRef);
643 14
            $finderDef->replaceArgument(1, new Reference($elasticaToModelId));
644 14
            $container->setDefinition($finderId, $finderDef);
645
        }
646
647 14
        $arguments = [$indexName, new Reference($finderId)];
648 14
        if (isset($typeConfig['repository'])) {
649 4
            $arguments[] = $typeConfig['repository'];
650
        }
651
652 14
        $container->getDefinition('fos_elastica.repository_manager')
653 14
            ->addMethodCall('addType', $arguments);
654
655 14
        $managerId = sprintf('fos_elastica.manager.%s', $typeConfig['driver']);
656 14
        $container->getDefinition($managerId)
657 14
            ->addMethodCall('addEntity', [$typeConfig['model'], $indexName]);
658
659 14
        return $finderId;
660
    }
661
662
    /**
663
     * Loads the index manager.
664
     **/
665 20 View Code Duplication
    private function loadIndexManager(ContainerBuilder $container): void
666
    {
667
        $indexRefs = array_map(function ($index) {
668 20
            return $index['reference'];
669 20
        }, $this->indexConfigs);
670
671 20
        $managerDef = $container->getDefinition('fos_elastica.index_manager');
672 20
        $managerDef->replaceArgument(0, $indexRefs);
673 20
    }
674
675
    /**
676
     * Load index template manager
677
     */
678 20 View Code Duplication
    private function loadIndexTemplateManager(ContainerBuilder $container): void
679
    {
680
        $indexTemplateRefs = array_map(function ($index) {
681 6
            return $index['reference'];
682 20
        }, $this->indexTemplateConfigs);
683
684 20
        $managerDef = $container->getDefinition('fos_elastica.index_template_manager');
685 20
        $managerDef->replaceArgument(0, $indexTemplateRefs);
686 20
    }
687
688
    /**
689
     * Makes sure a specific driver has been loaded.
690
     */
691 14
    private function loadDriver(ContainerBuilder $container, string $driver): void
692
    {
693 14
        if (in_array($driver, $this->loadedDrivers, true)) {
694 5
            return;
695
        }
696
697 14
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
698 14
        $loader->load($driver.'.xml');
699 14
        $this->loadedDrivers[] = $driver;
700 14
    }
701
702
    /**
703
     * Loads and configures the serializer prototype.
704
     */
705 1
    private function loadSerializer(array $config, ContainerBuilder $container): void
706
    {
707 1
        $container->setAlias('fos_elastica.serializer', $config['serializer']);
708
709 1
        $serializer = $container->getDefinition('fos_elastica.serializer_callback_prototype');
710 1
        $serializer->setClass($config['callback_class']);
711
712 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...
713
            $serializer->addMethodCall('setContainer', [new Reference('service_container')]);
714
        }
715 1
    }
716
717
    /**
718
     * Creates a default manager alias for defined default manager or the first loaded driver.
719
     */
720 20
    private function createDefaultManagerAlias(string $defaultManager, ContainerBuilder $container): void
721
    {
722 20
        if (0 == count($this->loadedDrivers)) {
723 6
            return;
724
        }
725
726 14
        if (count($this->loadedDrivers) > 1
727 14
            && in_array($defaultManager, $this->loadedDrivers, true)
728
        ) {
729
            $defaultManagerService = $defaultManager;
730
        } else {
731 14
            $defaultManagerService = $this->loadedDrivers[0];
732
        }
733
734 14
        $container->setAlias('fos_elastica.manager', sprintf('fos_elastica.manager.%s', $defaultManagerService));
735 14
        $container->getAlias('fos_elastica.manager')->setPublic(true);
736 14
        $container->setAlias(RepositoryManagerInterface::class, 'fos_elastica.manager');
737 14
        $container->getAlias(RepositoryManagerInterface::class)->setPublic(false);
738 14
    }
739
740
    /**
741
     * Returns a reference to a client given its configured name.
742
     *
743
     * @throws \InvalidArgumentException
744
     */
745 7
    private function getClient(string $clientName): Reference
746
    {
747 7
        if (!array_key_exists($clientName, $this->clients)) {
748
            throw new \InvalidArgumentException(sprintf('The elastica client with name "%s" is not defined', $clientName));
749
        }
750
751 7
        return $this->clients[$clientName]['reference'];
752
    }
753
}
754