Passed
Push — master ( 76f1b8...781818 )
by
unknown
51s queued 10s
created

DoctrineOrmServiceProvider::getOrmEmFactory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\DoctrineDbServiceProvider\ServiceProvider;
6
7
use Chubbyphp\DoctrineDbServiceProvider\Driver\ClassMapDriver;
8
use Chubbyphp\DoctrineDbServiceProvider\Registry\DoctrineOrmManagerRegistry;
9
use Doctrine\Common\Cache\Cache;
10
use Doctrine\Common\EventManager;
11
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
12
use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver;
13
use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver;
14
use Doctrine\DBAL\Connection;
15
use Doctrine\ORM\Cache\CacheConfiguration;
16
use Doctrine\ORM\Cache\DefaultCacheFactory;
17
use Doctrine\ORM\Cache\RegionsConfiguration;
18
use Doctrine\ORM\Configuration;
19
use Doctrine\ORM\EntityManager;
20
use Doctrine\ORM\EntityRepository;
21
use Doctrine\ORM\Mapping\ClassMetadataFactory;
22
use Doctrine\ORM\Mapping\DefaultEntityListenerResolver;
23
use Doctrine\ORM\Mapping\DefaultNamingStrategy;
24
use Doctrine\ORM\Mapping\DefaultQuoteStrategy;
25
use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver;
26
use Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver;
27
use Doctrine\ORM\Mapping\Driver\XmlDriver;
28
use Doctrine\ORM\Mapping\Driver\YamlDriver;
29
use Doctrine\ORM\Repository\DefaultRepositoryFactory;
30
use Pimple\Container;
31
use Pimple\ServiceProviderInterface;
32
33
/**
34
 * This provider is heavily inspired by
35
 * https://github.com/dflydev/dflydev-doctrine-orm-service-provider/blob/master/src/Dflydev/Provider/DoctrineOrm/DoctrineOrmServiceProvider.php.
36
 */
37
final class DoctrineOrmServiceProvider implements ServiceProviderInterface
38
{
39
    /**
40
     * Register ORM service.
41
     *
42
     * @param Container $container
43
     */
44 3
    public function register(Container $container)
45
    {
46 3
        $container['doctrine.orm.em'] = $this->getOrmEmDefinition($container);
47 3
        $container['doctrine.orm.em.config'] = $this->getOrmEmConfigDefinition($container);
48 3
        $container['doctrine.orm.em.default_options'] = $this->getOrmEmDefaultOptions();
49 3
        $container['doctrine.orm.em.factory'] = $this->getOrmEmFactory($container);
50 3
        $container['doctrine.orm.ems'] = $this->getOrmEmsDefinition($container);
51 3
        $container['doctrine.orm.ems.config'] = $this->getOrmEmsConfigServiceProvider($container);
52 3
        $container['doctrine.orm.ems.options.initializer'] = $this->getOrmEmsOptionsInitializerDefinition($container);
53 3
        $container['doctrine.orm.entity.listener_resolver.default'] = $this->getOrmEntityListenerResolverDefinition($container);
54 3
        $container['doctrine.orm.manager_registry'] = $this->getOrmManagerRegistryDefintion($container);
55 3
        $container['doctrine.orm.mapping_driver.factory.annotation'] = $this->getOrmMappingDriverFactoryAnnotation($container);
56 3
        $container['doctrine.orm.mapping_driver.factory.class_map'] = $this->getOrmMappingDriverFactoryClassMap($container);
57 3
        $container['doctrine.orm.mapping_driver.factory.php'] = $this->getOrmMappingDriverFactoryPhp($container);
58 3
        $container['doctrine.orm.mapping_driver.factory.simple_xml'] = $this->getOrmMappingDriverFactorySimpleXml($container);
59 3
        $container['doctrine.orm.mapping_driver.factory.simple_yaml'] = $this->getOrmMappingDriverFactorySimpleYaml($container);
60 3
        $container['doctrine.orm.mapping_driver.factory.static_php'] = $this->getOrmMappingDriverFactoryStaticPhp($container);
61 3
        $container['doctrine.orm.mapping_driver.factory.xml'] = $this->getOrmMappingDriverFactoryXml($container);
62 3
        $container['doctrine.orm.mapping_driver.factory.yaml'] = $this->getOrmMappingDriverFactoryYaml($container);
63 3
        $container['doctrine.orm.mapping_driver_chain'] = $this->getOrmMappingDriverChainDefinition($container);
64 3
        $container['doctrine.orm.repository.factory.default'] = $this->getOrmRepositoryFactoryDefinition($container);
65 3
        $container['doctrine.orm.strategy.naming.default'] = $this->getOrmNamingStrategyDefinition($container);
66 3
        $container['doctrine.orm.strategy.quote.default'] = $this->getOrmQuoteStrategyDefinition($container);
67 3
    }
68
69
    /**
70
     * @param Container $container
71
     *
72
     * @return callable
73
     */
74
    private function getOrmEmDefinition(Container $container): callable
75
    {
76 3
        return function () use ($container) {
77 2
            $ems = $container['doctrine.orm.ems'];
78
79 2
            return $ems[$container['doctrine.orm.ems.default']];
80 3
        };
81
    }
82
83
    /**
84
     * @param Container $container
85
     *
86
     * @return callable
87
     */
88
    private function getOrmEmConfigDefinition(Container $container): callable
89
    {
90 3
        return function () use ($container) {
91 3
            $configs = $container['doctrine.orm.ems.config'];
92
93 3
            return $configs[$container['doctrine.orm.ems.default']];
94 3
        };
95
    }
96
97
    /**
98
     * @return array
99
     */
100 3
    private function getOrmEmDefaultOptions(): array
101
    {
102
        return [
103 3
            'cache.hydration' => ['type' => 'array'],
104
            'cache.metadata' => ['type' => 'array'],
105
            'cache.query' => ['type' => 'array'],
106
            'class_metadata.factory.name' => ClassMetadataFactory::class,
107 3
            'connection' => 'default',
108
            'custom.functions.datetime' => [],
109
            'custom.functions.numeric' => [],
110
            'custom.functions.string' => [],
111
            'custom.hydration_modes' => [],
112 3
            'entity.listener_resolver' => 'default',
113
            'mappings' => [],
114
            'proxies.auto_generate' => true,
115 3
            'proxies.dir' => sys_get_temp_dir().'/doctrine/orm/proxies',
116 3
            'proxies.namespace' => 'DoctrineProxy',
117
            'query_hints' => [],
118
            'repository.default.class' => EntityRepository::class,
119 3
            'repository.factory' => 'default',
120
            'second_level_cache' => ['type' => 'array'],
121
            'second_level_cache.enabled' => false,
122 3
            'strategy.naming' => 'default',
123 3
            'strategy.quote' => 'default',
124
        ];
125
    }
126
127
    /**
128
     * @param Container $container
129
     *
130
     * @return callable
131
     */
132 3
    private function getOrmEmFactory(Container $container): callable
133
    {
134 3
        return $container->protect(
135 3
            function (Connection $connection, Configuration $config, EventManager $eventManager) {
136 3
                return EntityManager::create($connection, $config, $eventManager);
137 3
            }
138
        );
139
    }
140
141
    /**
142
     * @param Container $container
143
     *
144
     * @return callable
145
     */
146
    private function getOrmEmsDefinition(Container $container): callable
147
    {
148 3
        return function () use ($container) {
149 3
            $container['doctrine.orm.ems.options.initializer']();
150
151 3
            $ems = new Container();
152 3
            foreach ($container['doctrine.orm.ems.options'] as $name => $options) {
153 3
                if ($container['doctrine.orm.ems.default'] === $name) {
154 3
                    $config = $container['doctrine.orm.em.config'];
155
                } else {
156 1
                    $config = $container['doctrine.orm.ems.config'][$name];
157
                }
158
159 3
                $ems[$name] = function () use ($container, $options, $config) {
160 3
                    return $container['doctrine.orm.em.factory'](
161 3
                        $container['doctrine.dbal.dbs'][$options['connection']],
162 3
                        $config,
163 3
                        $container['doctrine.dbal.dbs.event_manager'][$options['connection']]
164
                    );
165 3
                };
166
            }
167
168 3
            return $ems;
169 3
        };
170
    }
171
172
    /**
173
     * @param Container $container
174
     *
175
     * @return callable
176
     */
177
    private function getOrmEmsConfigServiceProvider(Container $container): callable
178
    {
179 3
        return function () use ($container) {
180 3
            $container['doctrine.orm.ems.options.initializer']();
181
182 3
            $configs = new Container();
183 3
            foreach ($container['doctrine.orm.ems.options'] as $name => $options) {
184 3
                $connectionName = $options['connection'];
185
186 3
                $config = new Configuration();
187
188 3
                $config->setSQLLogger($container['doctrine.dbal.dbs.config'][$connectionName]->getSQLLogger());
189
190 3
                $config->setQueryCacheImpl($this->getCache($container, $options['cache.query']));
191 3
                $config->setHydrationCacheImpl($this->getCache($container, $options['cache.hydration']));
192 3
                $config->setMetadataCacheImpl($this->getCache($container, $options['cache.metadata']));
193
194 3
                $config->setResultCacheImpl(
195 3
                    $container['doctrine.dbal.dbs.config'][$connectionName]->getResultCacheImpl()
196
                );
197
198 3
                $config->setClassMetadataFactoryName($options['class_metadata.factory.name']);
199
200 3
                $config->setCustomDatetimeFunctions($options['custom.functions.datetime']);
201 3
                $config->setCustomHydrationModes($options['custom.hydration_modes']);
202 3
                $config->setCustomNumericFunctions($options['custom.functions.numeric']);
203 3
                $config->setCustomStringFunctions($options['custom.functions.string']);
204
205 3
                $config->setEntityListenerResolver(
206
                    $container[
207 3
                        sprintf('doctrine.orm.entity.listener_resolver.%s', $options['entity.listener_resolver'])
208
                    ]
209
                );
210
211 3
                $config->setMetadataDriverImpl(
212 3
                    $container['doctrine.orm.mapping_driver_chain']($config, $options['mappings'])
213
                );
214
215 3
                $config->setAutoGenerateProxyClasses($options['proxies.auto_generate']);
216 3
                $config->setProxyDir($options['proxies.dir']);
217 3
                $config->setProxyNamespace($options['proxies.namespace']);
218
219 3
                $config->setDefaultQueryHints($options['query_hints']);
220
221 3
                $config->setRepositoryFactory(
222 3
                    $container[sprintf('doctrine.orm.repository.factory.%s', $options['repository.factory'])]
223
                );
224 3
                $config->setDefaultRepositoryClassName($options['repository.default.class']);
225
226 3
                $this->assignSecondLevelCache($container, $config, $options);
227
228 3
                $config->setNamingStrategy(
229 3
                    $container[sprintf('doctrine.orm.strategy.naming.%s', $options['strategy.naming'])]
230
                );
231 3
                $config->setQuoteStrategy(
232 3
                    $container[sprintf('doctrine.orm.strategy.quote.%s', $options['strategy.quote'])]
233
                );
234
235 3
                $configs[$name] = $config;
236
            }
237
238 3
            return $configs;
239 3
        };
240
    }
241
242
    /**
243
     * @param Container    $container
244
     * @param string|array $cacheDefinition
245
     *
246
     * @return Cache
247
     */
248 3 View Code Duplication
    private function getCache(Container $container, $cacheDefinition): Cache
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
249
    {
250 3
        $cacheType = $cacheDefinition['type'];
251 3
        $cacheOptions = $cacheDefinition['options'] ?? [];
252
253 3
        $cacheFactory = $container[sprintf('doctrine.dbal.db.cache_factory.%s', $cacheType)];
254
255 3
        return $cacheFactory($cacheOptions);
256
    }
257
258
    /**
259
     * @param Container     $container
260
     * @param Configuration $config
261
     * @param array         $options
262
     */
263 3
    private function assignSecondLevelCache(Container $container, Configuration $config, array $options)
264
    {
265 3
        if (!$options['second_level_cache.enabled']) {
266 2
            $config->setSecondLevelCacheEnabled(false);
267
268 2
            return;
269
        }
270
271 1
        $regionsCacheConfiguration = new RegionsConfiguration();
272 1
        $factory = new DefaultCacheFactory(
273 1
            $regionsCacheConfiguration,
274 1
            $this->getCache($container, $options['second_level_cache'])
275
        );
276
277 1
        $cacheConfiguration = new CacheConfiguration();
278 1
        $cacheConfiguration->setCacheFactory($factory);
279 1
        $cacheConfiguration->setRegionsConfiguration($regionsCacheConfiguration);
280
281 1
        $config->setSecondLevelCacheEnabled(true);
282 1
        $config->setSecondLevelCacheConfiguration($cacheConfiguration);
283 1
    }
284
285
    /**
286
     * @param Container $container
287
     *
288
     * @return callable
289
     */
290
    private function getOrmEmsOptionsInitializerDefinition(Container $container): callable
291
    {
292 3
        return $container->protect(function () use ($container) {
293 3
            static $initialized = false;
294
295 3
            if ($initialized) {
296 3
                return;
297
            }
298
299 3
            $initialized = true;
300
301 3
            if (!isset($container['doctrine.orm.ems.options'])) {
302 2
                $container['doctrine.orm.ems.options'] = [
303 2
                    'default' => $container['doctrine.orm.em.options'] ?? [],
304
                ];
305
            }
306
307 3
            $tmp = $container['doctrine.orm.ems.options'];
308 3
            foreach ($tmp as $name => &$options) {
309 3
                $options = array_replace($container['doctrine.orm.em.default_options'], $options);
310
311 3
                if (!isset($container['doctrine.orm.ems.default'])) {
312 3
                    $container['doctrine.orm.ems.default'] = $name;
313
                }
314
            }
315
316 3
            $container['doctrine.orm.ems.options'] = $tmp;
317 3
        });
318
    }
319
320
    /**
321
     * @param Container $container
322
     *
323
     * @return callable
324
     */
325
    private function getOrmEntityListenerResolverDefinition(Container $container): callable
326
    {
327 3
        return function () use ($container) {
328 2
            return new DefaultEntityListenerResolver();
329 3
        };
330
    }
331
332
    /**
333
     * @param Container $container
334
     *
335
     * @return callable
336
     */
337
    private function getOrmManagerRegistryDefintion(Container $container): callable
0 ignored issues
show
Unused Code introduced by
The parameter $container is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
338
    {
339 3
        return function ($container) {
340 1
            return new DoctrineOrmManagerRegistry($container);
341 3
        };
342
    }
343
344
    /**
345
     * @param Container $container
346
     *
347
     * @return callable
348
     */
349
    private function getOrmMappingDriverFactoryAnnotation(Container $container): callable
350
    {
351 3
        return $container->protect(function (array $mapping, Configuration $config) {
352 2
            return $config->newDefaultAnnotationDriver((array) $mapping['path'], false);
353 3
        });
354
    }
355
356
    /**
357
     * @param Container $container
358
     *
359
     * @return callable
360
     */
361
    private function getOrmMappingDriverFactoryClassMap(Container $container): callable
362
    {
363 3
        return $container->protect(function (array $mapping, Configuration $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
364 1
            return new ClassMapDriver($mapping['map']);
365 3
        });
366
    }
367
368
    /**
369
     * @param Container $container
370
     *
371
     * @return callable
372
     */
373
    private function getOrmMappingDriverFactoryPhp(Container $container): callable
374
    {
375 3
        return $container->protect(function (array $mapping, Configuration $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
376 1
            return new PHPDriver($mapping['path']);
377 3
        });
378
    }
379
380
    /**
381
     * @param Container $container
382
     *
383
     * @return callable
384
     */
385 View Code Duplication
    private function getOrmMappingDriverFactorySimpleYaml(Container $container): callable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
386
    {
387 3
        return $container->protect(function (array $mapping, Configuration $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
388 1
            return new SimplifiedYamlDriver(
389 1
                [$mapping['path'] => $mapping['namespace']],
390 1
                $mapping['extension'] ?? SimplifiedYamlDriver::DEFAULT_FILE_EXTENSION
391
            );
392 3
        });
393
    }
394
395
    /**
396
     * @param Container $container
397
     *
398
     * @return callable
399
     */
400 View Code Duplication
    private function getOrmMappingDriverFactorySimpleXml(Container $container): callable
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
401
    {
402 3
        return $container->protect(function (array $mapping, Configuration $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
403 1
            return new SimplifiedXmlDriver(
404 1
                [$mapping['path'] => $mapping['namespace']],
405 1
                $mapping['extension'] ?? SimplifiedXmlDriver::DEFAULT_FILE_EXTENSION
406
            );
407 3
        });
408
    }
409
410
    /**
411
     * @param Container $container
412
     *
413
     * @return callable
414
     */
415
    private function getOrmMappingDriverFactoryStaticPhp(Container $container): callable
416
    {
417 3
        return $container->protect(function (array $mapping, Configuration $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
418 1
            return new StaticPHPDriver($mapping['path']);
419 3
        });
420
    }
421
422
    /**
423
     * @param Container $container
424
     *
425
     * @return callable
426
     */
427
    private function getOrmMappingDriverFactoryYaml(Container $container): callable
428
    {
429 3
        return $container->protect(function (array $mapping, Configuration $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
430 1
            return new YamlDriver($mapping['path'], $mapping['extension'] ?? YamlDriver::DEFAULT_FILE_EXTENSION);
431 3
        });
432
    }
433
434
    /**
435
     * @param Container $container
436
     *
437
     * @return callable
438
     */
439
    private function getOrmMappingDriverFactoryXml(Container $container): callable
440
    {
441 3
        return $container->protect(function (array $mapping, Configuration $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $config is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
442 1
            return new XmlDriver($mapping['path'], $mapping['extension'] ?? XmlDriver::DEFAULT_FILE_EXTENSION);
443 3
        });
444
    }
445
446
    /**
447
     * @param Container $container
448
     *
449
     * @return callable
450
     */
451
    private function getOrmMappingDriverChainDefinition(Container $container): callable
452
    {
453 3
        return $container->protect(function (Configuration $config, array $mappings) use ($container) {
454 3
            $chain = new MappingDriverChain();
455 3
            foreach ($mappings as $mapping) {
456 2
                if (isset($mapping['alias'])) {
457 1
                    $config->addEntityNamespace($mapping['alias'], $mapping['namespace']);
458
                }
459
460 2
                $factoryKey = sprintf('doctrine.orm.mapping_driver.factory.%s', $mapping['type']);
461
462 2
                $chain->addDriver($container[$factoryKey]($mapping, $config), $mapping['namespace']);
463
            }
464
465 3
            return $chain;
466 3
        });
467
    }
468
469
    /**
470
     * @param Container $container
471
     *
472
     * @return callable
473
     */
474
    private function getOrmRepositoryFactoryDefinition(Container $container): callable
475
    {
476 3
        return function () use ($container) {
477 2
            return new DefaultRepositoryFactory();
478 3
        };
479
    }
480
481
    /**
482
     * @param Container $container
483
     *
484
     * @return callable
485
     */
486
    private function getOrmNamingStrategyDefinition(Container $container): callable
487
    {
488 3
        return function () use ($container) {
489 2
            return new DefaultNamingStrategy();
490 3
        };
491
    }
492
493
    /**
494
     * @param Container $container
495
     *
496
     * @return callable
497
     */
498
    private function getOrmQuoteStrategyDefinition(Container $container): callable
499
    {
500 3
        return function () use ($container) {
501 2
            return new DefaultQuoteStrategy();
502 3
        };
503
    }
504
}
505