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