Completed
Pull Request — master (#1354)
by
unknown
06:57
created

loadElasticaToModelTransformer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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