Completed
Pull Request — master (#1706)
by Karel
05:02
created

FOSElasticaExtension::load()   B

Complexity

Conditions 9
Paths 65

Size

Total Lines 64

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 37
CRAP Score 9.0341

Importance

Changes 0
Metric Value
dl 0
loc 64
ccs 37
cts 40
cp 0.925
rs 7.2298
c 0
b 0
f 0
cc 9
nc 65
nop 2
crap 9.0341

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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