Completed
Push — master ( 80d3da...0d64d6 )
by Karel
14s
created

FOSElasticaExtension::loadIndexManager()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 9
Ratio 100 %

Code Coverage

Tests 7
CRAP Score 1

Importance

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