1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Mathielen\ImportEngineBundle\DependencyInjection; |
4
|
|
|
|
5
|
|
|
use Mathielen\ImportEngine\Exception\InvalidConfigurationException; |
6
|
|
|
use Mathielen\ImportEngine\Storage\Provider\Connection\DefaultConnectionFactory; |
7
|
|
|
use Symfony\Component\DependencyInjection\ContainerBuilder; |
8
|
|
|
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; |
9
|
|
|
use Symfony\Component\DependencyInjection\Extension\Extension; |
10
|
|
|
use Symfony\Component\Config\FileLocator; |
11
|
|
|
use Symfony\Component\DependencyInjection\Reference; |
12
|
|
|
use Symfony\Component\DependencyInjection\Definition; |
13
|
|
|
use Symfony\Component\ExpressionLanguage\Expression; |
14
|
|
|
|
15
|
|
|
class MathielenImportEngineExtension extends Extension |
16
|
|
|
{ |
17
|
11 |
|
public function load(array $configs, ContainerBuilder $container) |
18
|
|
|
{ |
19
|
11 |
|
$config = $this->processConfiguration(new Configuration(), $configs); |
20
|
|
|
|
21
|
11 |
|
if (!empty($config['importers'])) { |
22
|
9 |
|
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); |
23
|
9 |
|
$loader->load('services.xml'); |
24
|
|
|
|
25
|
9 |
|
$this->parseConfig($config, $container); |
26
|
|
|
} |
27
|
11 |
|
} |
28
|
|
|
|
29
|
9 |
|
private function parseConfig(array $config, ContainerBuilder $container) |
30
|
|
|
{ |
31
|
9 |
|
$storageLocatorDef = $container->findDefinition('mathielen_importengine.import.storagelocator'); |
32
|
9 |
|
foreach ($config['storageprovider'] as $name => $sourceConfig) { |
33
|
5 |
|
$this->addStorageProviderDef($storageLocatorDef, $sourceConfig, $name); |
34
|
|
|
} |
35
|
|
|
|
36
|
9 |
|
$importerRepositoryDef = $container->findDefinition('mathielen_importengine.importer.repository'); |
37
|
9 |
|
foreach ($config['importers'] as $name => $importConfig) { |
38
|
9 |
|
$finderDef = null; |
39
|
9 |
|
if (isset($importConfig['preconditions'])) { |
40
|
5 |
|
$finderDef = $this->generateFinderDef($importConfig['preconditions']); |
41
|
|
|
} |
42
|
|
|
|
43
|
9 |
|
$objectFactoryDef = null; |
44
|
9 |
|
if (isset($importConfig['object_factory'])) { |
45
|
5 |
|
$objectFactoryDef = $this->generateObjectFactoryDef($importConfig['object_factory']); |
46
|
|
|
} |
47
|
|
|
|
48
|
9 |
|
$importerRepositoryDef->addMethodCall('register', array( |
49
|
9 |
|
$name, |
50
|
9 |
|
$this->generateImporterDef($importConfig, $objectFactoryDef), |
51
|
9 |
|
$finderDef, |
52
|
|
|
)); |
53
|
|
|
} |
54
|
9 |
|
} |
55
|
|
|
|
56
|
5 |
|
private function generateObjectFactoryDef(array $config) |
57
|
|
|
{ |
58
|
5 |
|
if (!class_exists($config['class'])) { |
59
|
|
|
throw new InvalidConfigurationException("Object-Factory target-class '".$config['class']."' does not exist."); |
60
|
|
|
} |
61
|
|
|
|
62
|
5 |
|
if ($config['type'] == 'jms_serializer') { |
63
|
5 |
|
return new Definition('Mathielen\DataImport\Writer\ObjectWriter\JmsSerializerObjectFactory', array( |
64
|
5 |
|
$config['class'], |
65
|
5 |
|
new Reference('jms_serializer'), )); |
66
|
|
|
} |
67
|
|
|
|
68
|
5 |
|
return new Definition('Mathielen\DataImport\Writer\ObjectWriter\DefaultObjectFactory', array($config['class'])); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @return \Symfony\Component\DependencyInjection\Definition |
73
|
|
|
*/ |
74
|
5 |
|
private function generateFinderDef(array $finderConfig) |
75
|
|
|
{ |
76
|
5 |
|
$finderDef = new Definition('Mathielen\ImportEngine\Importer\ImporterPrecondition'); |
77
|
|
|
|
78
|
5 |
|
if (isset($finderConfig['filename'])) { |
79
|
5 |
|
foreach ($finderConfig['filename'] as $conf) { |
80
|
5 |
|
$finderDef->addMethodCall('filename', array($conf)); |
81
|
|
|
} |
82
|
|
|
} |
83
|
|
|
|
84
|
5 |
View Code Duplication |
if (isset($finderConfig['format'])) { |
|
|
|
|
85
|
5 |
|
foreach ($finderConfig['format'] as $conf) { |
86
|
5 |
|
$finderDef->addMethodCall('format', array($conf)); |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
|
90
|
5 |
|
if (isset($finderConfig['fieldcount'])) { |
91
|
5 |
|
$finderDef->addMethodCall('fieldcount', array($finderConfig['fieldcount'])); |
92
|
|
|
} |
93
|
|
|
|
94
|
5 |
View Code Duplication |
if (isset($finderConfig['fields'])) { |
|
|
|
|
95
|
5 |
|
foreach ($finderConfig['fields'] as $conf) { |
96
|
5 |
|
$finderDef->addMethodCall('field', array($conf)); |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
|
100
|
5 |
|
if (isset($finderConfig['fieldset'])) { |
101
|
5 |
|
$finderDef->addMethodCall('fieldset', array($finderConfig['fieldset'])); |
102
|
|
|
} |
103
|
|
|
|
104
|
5 |
|
return $finderDef; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @return \Symfony\Component\DependencyInjection\Definition |
109
|
|
|
*/ |
110
|
9 |
|
private function generateImporterDef(array $importConfig, Definition $objectFactoryDef = null) |
111
|
|
|
{ |
112
|
9 |
|
$importerDef = new Definition('Mathielen\ImportEngine\Importer\Importer', array( |
113
|
9 |
|
$this->getStorageDef($importConfig['target'], $objectFactoryDef), |
114
|
|
|
)); |
115
|
|
|
|
116
|
9 |
|
if (isset($importConfig['source'])) { |
117
|
5 |
|
$this->setSourceStorageDef($importConfig['source'], $importerDef); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
//enable validation? |
121
|
9 |
|
if (isset($importConfig['validation']) && !empty($importConfig['validation'])) { |
122
|
7 |
|
$this->generateValidationDef($importConfig['validation'], $importerDef, $objectFactoryDef); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
//add converters? |
126
|
9 |
|
if (isset($importConfig['mappings']) && !empty($importConfig['mappings'])) { |
127
|
5 |
|
$this->generateTransformerDef($importConfig['mappings'], $importerDef); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
//add filters? |
131
|
9 |
|
if (isset($importConfig['filters']) && !empty($importConfig['filters'])) { |
132
|
|
|
$this->generateFiltersDef($importConfig['filters'], $importerDef); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
//has static context? |
136
|
9 |
|
if (isset($importConfig['context'])) { |
137
|
9 |
|
$importerDef->addMethodCall('setContext', array( |
138
|
9 |
|
$importConfig['context'], |
139
|
|
|
)); |
140
|
|
|
} |
141
|
|
|
|
142
|
9 |
|
return $importerDef; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
private function generateFiltersDef(array $filtersOptions, Definition $importerDef) |
146
|
|
|
{ |
147
|
|
|
$filtersDef = new Definition('Mathielen\ImportEngine\Filter\Filters'); |
148
|
|
|
|
149
|
|
|
foreach ($filtersOptions as $filtersOption) { |
150
|
|
|
$filtersDef->addMethodCall('add', array( |
151
|
|
|
new Reference($filtersOption), |
152
|
|
|
)); |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
$importerDef->addMethodCall('filters', array( |
156
|
|
|
$filtersDef, |
157
|
|
|
)); |
158
|
|
|
} |
159
|
|
|
|
160
|
5 |
|
private function generateTransformerDef(array $mappingOptions, Definition $importerDef) |
161
|
|
|
{ |
162
|
5 |
|
$mappingsDef = new Definition('Mathielen\ImportEngine\Mapping\Mappings'); |
163
|
|
|
|
164
|
|
|
//set converters |
165
|
5 |
|
foreach ($mappingOptions as $field => $fieldMapping) { |
166
|
5 |
|
$converter = null; |
167
|
5 |
|
if (isset($fieldMapping['converter'])) { |
168
|
5 |
|
$converter = $fieldMapping['converter']; |
169
|
|
|
} |
170
|
|
|
|
171
|
5 |
|
if (isset($fieldMapping['to'])) { |
172
|
5 |
|
$mappingsDef->addMethodCall('add', array( |
173
|
5 |
|
$field, |
174
|
5 |
|
$fieldMapping['to'], |
175
|
5 |
|
$converter, |
176
|
|
|
)); |
177
|
5 |
|
} elseif ($converter) { |
178
|
5 |
|
$mappingsDef->addMethodCall('setConverter', array( |
179
|
5 |
|
$converter, |
180
|
5 |
|
$field, |
181
|
|
|
)); |
182
|
|
|
} |
183
|
|
|
} |
184
|
|
|
|
185
|
5 |
|
$mappingFactoryDef = new Definition('Mathielen\ImportEngine\Mapping\DefaultMappingFactory', array( |
186
|
5 |
|
$mappingsDef, |
187
|
|
|
)); |
188
|
5 |
|
$converterProviderDef = new Definition('Mathielen\ImportEngine\Mapping\Converter\Provider\ContainerAwareConverterProvider', array( |
189
|
5 |
|
new Reference('service_container'), |
190
|
|
|
)); |
191
|
|
|
|
192
|
5 |
|
$transformerDef = new Definition('Mathielen\ImportEngine\Transformation\Transformation'); |
193
|
5 |
|
$transformerDef->addMethodCall('setMappingFactory', array( |
194
|
5 |
|
$mappingFactoryDef, |
195
|
|
|
)); |
196
|
5 |
|
$transformerDef->addMethodCall('setConverterProvider', array( |
197
|
5 |
|
$converterProviderDef, |
198
|
|
|
)); |
199
|
|
|
|
200
|
5 |
|
$importerDef->addMethodCall('transformation', array( |
201
|
5 |
|
$transformerDef, |
202
|
|
|
)); |
203
|
5 |
|
} |
204
|
|
|
|
205
|
7 |
|
private function generateValidatorDef(array $options) |
206
|
|
|
{ |
207
|
|
|
//eventdispatcher aware source validatorfilter |
208
|
7 |
|
$validatorFilterDef = new Definition('Mathielen\DataImport\Filter\ValidatorFilter', array( |
209
|
7 |
|
new Reference('validator'), |
210
|
7 |
|
$options, |
211
|
7 |
|
new Reference('event_dispatcher'), |
212
|
|
|
)); |
213
|
|
|
|
214
|
7 |
|
return $validatorFilterDef; |
215
|
|
|
} |
216
|
|
|
|
217
|
7 |
|
private function generateValidationDef(array $validationConfig, Definition $importerDef, Definition $objectFactoryDef = null) |
218
|
|
|
{ |
219
|
7 |
|
$validationDef = new Definition('Mathielen\ImportEngine\Validation\ValidatorValidation', array( |
220
|
7 |
|
new Reference('validator'), |
221
|
|
|
)); |
222
|
7 |
|
$importerDef->addMethodCall('validation', array( |
223
|
7 |
|
$validationDef, |
224
|
|
|
)); |
225
|
|
|
|
226
|
7 |
|
$validatorFilterDef = $this->generateValidatorDef( |
227
|
7 |
|
isset($validationConfig['options']) ? $validationConfig['options'] : array() |
228
|
|
|
); |
229
|
|
|
|
230
|
7 |
|
if (isset($validationConfig['source'])) { |
231
|
3 |
|
$validationDef->addMethodCall('setSourceValidatorFilter', array( |
232
|
3 |
|
$validatorFilterDef, |
233
|
|
|
)); |
234
|
|
|
|
235
|
3 |
|
foreach ($validationConfig['source']['constraints'] as $field => $constraint) { |
236
|
3 |
|
$validationDef->addMethodCall('addSourceConstraint', array( |
237
|
3 |
|
$field, |
238
|
3 |
|
new Reference($constraint), |
239
|
|
|
)); |
240
|
|
|
} |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
//automatically apply class validation |
244
|
7 |
|
if (isset($validationConfig['target'])) { |
245
|
|
|
|
246
|
|
|
//using objects as result |
247
|
7 |
|
if ($objectFactoryDef) { |
248
|
|
|
|
249
|
|
|
//set eventdispatcher aware target CLASS-validatorfilter |
250
|
5 |
|
$validatorFilterDef = new Definition('Mathielen\DataImport\Filter\ClassValidatorFilter', array( |
251
|
5 |
|
new Reference('validator'), |
252
|
5 |
|
$objectFactoryDef, |
253
|
5 |
|
new Reference('event_dispatcher'), |
254
|
|
|
)); |
255
|
|
|
} else { |
256
|
3 |
|
foreach ($validationConfig['target']['constraints'] as $field => $constraint) { |
257
|
3 |
|
$validationDef->addMethodCall('addTargetConstraint', array( |
258
|
3 |
|
$field, |
259
|
3 |
|
new Reference($constraint), |
260
|
|
|
)); |
261
|
|
|
} |
262
|
|
|
} |
263
|
|
|
|
264
|
7 |
|
$validationDef->addMethodCall('setTargetValidatorFilter', array( |
265
|
7 |
|
$validatorFilterDef, |
266
|
|
|
)); |
267
|
|
|
} |
268
|
|
|
|
269
|
7 |
|
return $validationDef; |
270
|
|
|
} |
271
|
|
|
|
272
|
5 |
|
private function setSourceStorageDef(array $sourceConfig, Definition $importerDef) |
273
|
|
|
{ |
274
|
5 |
|
$sDef = $this->getStorageDef($sourceConfig, $importerDef); |
275
|
5 |
|
$importerDef->addMethodCall('setSourceStorage', array( |
276
|
5 |
|
$sDef, |
277
|
|
|
)); |
278
|
5 |
|
} |
279
|
|
|
|
280
|
5 |
|
private function addStorageProviderDef(Definition $storageLocatorDef, $config, $id = 'default') |
281
|
|
|
{ |
282
|
5 |
|
$formatDiscoverLocalFileStorageFactoryDef = new Definition('Mathielen\ImportEngine\Storage\Factory\FormatDiscoverLocalFileStorageFactory', array( |
283
|
5 |
|
new Definition('Mathielen\ImportEngine\Storage\Format\Discovery\MimeTypeDiscoverStrategy', array( |
284
|
|
|
array( |
285
|
5 |
|
'text/plain' => new Definition('Mathielen\ImportEngine\Storage\Format\Factory\CsvAutoDelimiterFormatFactory'), |
286
|
5 |
|
'text/csv' => new Definition('Mathielen\ImportEngine\Storage\Format\Factory\CsvAutoDelimiterFormatFactory'), |
287
|
|
|
), |
288
|
|
|
)), |
289
|
5 |
|
new Reference('logger'), |
290
|
|
|
)); |
291
|
|
|
|
292
|
5 |
|
switch ($config['type']) { |
293
|
5 |
|
case 'directory': |
294
|
5 |
|
$spFinderDef = new Definition('Symfony\Component\Finder\Finder'); |
295
|
5 |
|
$spFinderDef->addMethodCall('in', array( |
296
|
5 |
|
$config['uri'], |
297
|
|
|
)); |
298
|
5 |
|
$spDef = new Definition('Mathielen\ImportEngine\Storage\Provider\FinderFileStorageProvider', array( |
299
|
5 |
|
$spFinderDef, |
300
|
5 |
|
$formatDiscoverLocalFileStorageFactoryDef, |
301
|
|
|
)); |
302
|
5 |
|
break; |
303
|
5 |
|
case 'upload': |
304
|
5 |
|
$spDef = new Definition('Mathielen\ImportEngine\Storage\Provider\UploadFileStorageProvider', array( |
305
|
5 |
|
$config['uri'], |
306
|
5 |
|
$formatDiscoverLocalFileStorageFactoryDef, |
307
|
|
|
)); |
308
|
5 |
|
break; |
309
|
5 |
View Code Duplication |
case 'dbal': |
|
|
|
|
310
|
|
|
$listResolverDef = new Definition(StringOrFileList::class, array($config['queries'])); |
311
|
|
|
if (!isset($config['connection_factory'])) { |
312
|
|
|
$connectionFactoryDef = new Definition(DefaultConnectionFactory::class, array(array('default' => new Reference('doctrine.dbal.default_connection')))); |
313
|
|
|
} else { |
314
|
|
|
$connectionFactoryDef = new Reference($config['connection_factory']); |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
$spDef = new Definition('Mathielen\ImportEngine\Storage\Provider\DbalStorageProvider', array( |
318
|
|
|
$connectionFactoryDef, |
319
|
|
|
$listResolverDef, |
320
|
|
|
)); |
321
|
|
|
break; |
322
|
5 |
View Code Duplication |
case 'doctrine': |
|
|
|
|
323
|
5 |
|
$listResolverDef = new Definition(StringOrFileList::class, array($config['queries'])); |
324
|
5 |
|
if (!isset($config['connection_factory'])) { |
325
|
5 |
|
$connectionFactoryDef = new Definition(DefaultConnectionFactory::class, array(array('default' => new Reference('doctrine.orm.entity_manager')))); |
326
|
|
|
} else { |
327
|
|
|
$connectionFactoryDef = new Reference($config['connection_factory']); |
328
|
|
|
} |
329
|
|
|
|
330
|
5 |
|
$spDef = new Definition('Mathielen\ImportEngine\Storage\Provider\DoctrineQueryStorageProvider', array( |
331
|
5 |
|
$connectionFactoryDef, |
332
|
5 |
|
$listResolverDef, |
333
|
|
|
)); |
334
|
5 |
|
break; |
335
|
5 |
|
case 'service': |
336
|
5 |
|
$spDef = new Definition('Mathielen\ImportEngine\Storage\Provider\ServiceStorageProvider', array( |
337
|
5 |
|
new Reference('service_container'), |
338
|
5 |
|
$config['services'], |
339
|
|
|
)); |
340
|
5 |
|
break; |
341
|
5 |
|
case 'file': |
342
|
5 |
|
$spDef = new Definition('Mathielen\ImportEngine\Storage\Provider\FileStorageProvider', array( |
343
|
5 |
|
$formatDiscoverLocalFileStorageFactoryDef, |
344
|
|
|
)); |
345
|
5 |
|
break; |
346
|
|
|
default: |
347
|
|
|
throw new InvalidConfigurationException('Unknown type for storage provider: '.$config['type']); |
348
|
|
|
} |
349
|
|
|
|
350
|
5 |
|
$storageLocatorDef->addMethodCall('register', array( |
351
|
5 |
|
$id, |
352
|
5 |
|
$spDef, |
353
|
|
|
)); |
354
|
5 |
|
} |
355
|
|
|
|
356
|
9 |
|
private function getStorageFileDefinitionFromUri($uri) |
357
|
|
|
{ |
358
|
9 |
|
if (substr($uri, 0, 2) === '@=') { |
359
|
|
|
$uri = new Expression(substr($uri, 2)); |
360
|
|
|
} |
361
|
|
|
|
362
|
9 |
|
return new Definition('SplFileInfo', array( |
363
|
9 |
|
$uri, |
364
|
|
|
)); |
365
|
|
|
} |
366
|
|
|
|
367
|
|
|
/** |
368
|
|
|
* @return Definition |
369
|
|
|
*/ |
370
|
9 |
|
private function getStorageDef(array $config, Definition $objectFactoryDef = null) |
371
|
|
|
{ |
372
|
9 |
|
switch ($config['type']) { |
373
|
9 |
|
case 'file': |
374
|
9 |
|
$fileDef = $this->getStorageFileDefinitionFromUri($config['uri']); |
375
|
|
|
|
376
|
9 |
|
$format = $config['format']; |
377
|
9 |
|
$storageDef = new Definition('Mathielen\ImportEngine\Storage\LocalFileStorage', array( |
378
|
9 |
|
$fileDef, |
379
|
9 |
|
new Definition('Mathielen\ImportEngine\Storage\Format\\'.ucfirst($format['type']).'Format', $format['arguments']), |
380
|
|
|
)); |
381
|
|
|
|
382
|
9 |
|
break; |
383
|
5 |
|
case 'doctrine': |
384
|
5 |
|
$storageDef = new Definition('Mathielen\ImportEngine\Storage\DoctrineStorage', array( |
385
|
5 |
|
new Reference('doctrine.orm.entity_manager'), |
386
|
5 |
|
$config['entity'], |
387
|
|
|
)); |
388
|
|
|
|
389
|
5 |
|
break; |
390
|
|
|
//@deprecated |
391
|
5 |
|
case 'service': |
392
|
5 |
|
$storageDef = new Definition('Mathielen\ImportEngine\Storage\ServiceStorage', array( |
393
|
5 |
|
[new Reference($config['service']), $config['method']], //callable |
394
|
|
|
[], |
395
|
5 |
|
$objectFactoryDef, //from parameter array |
396
|
|
|
)); |
397
|
|
|
|
398
|
5 |
|
break; |
399
|
|
|
case 'callable': |
400
|
|
|
$config['callable'][0] = new Reference($config['callable'][0]); |
401
|
|
|
$storageDef = new Definition('Mathielen\ImportEngine\Storage\ServiceStorage', array( |
402
|
|
|
$config['callable'], |
403
|
|
|
[], |
404
|
|
|
$objectFactoryDef, //from parameter array |
405
|
|
|
)); |
406
|
|
|
|
407
|
|
|
break; |
408
|
|
|
default: |
409
|
|
|
throw new InvalidConfigurationException('Unknown type for storage: '.$config['type']); |
410
|
|
|
} |
411
|
|
|
|
412
|
9 |
|
return $storageDef; |
413
|
|
|
} |
414
|
|
|
|
415
|
11 |
|
public function getAlias() |
416
|
|
|
{ |
417
|
11 |
|
return 'mathielen_import_engine'; |
418
|
|
|
} |
419
|
|
|
} |
420
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.