Completed
Push — master ( 562a05...91dae5 )
by
unknown
18:11 queued 08:09
created

loadIndexPersistenceIntegration()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

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