Completed
Push — master ( fbad76...76f1b8 )
by Dominik
04:09 queued 55s
created

getOrmEmsOptionsInitializerDefinition()   A

Complexity

Conditions 5
Paths 1

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 29
ccs 15
cts 15
cp 1
rs 9.1448
c 0
b 0
f 0
cc 5
nc 1
nop 1
crap 5
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\Persistence\Mapping\Driver\MappingDriverChain;
11
use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver;
12
use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver;
13
use Doctrine\ORM\Cache\CacheConfiguration;
14
use Doctrine\ORM\Cache\DefaultCacheFactory;
15
use Doctrine\ORM\Cache\RegionsConfiguration;
16
use Doctrine\ORM\Configuration;
17
use Doctrine\ORM\EntityManager;
18
use Doctrine\ORM\EntityRepository;
19
use Doctrine\ORM\Mapping\ClassMetadataFactory;
20
use Doctrine\ORM\Mapping\DefaultEntityListenerResolver;
21
use Doctrine\ORM\Mapping\DefaultNamingStrategy;
22
use Doctrine\ORM\Mapping\DefaultQuoteStrategy;
23
use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver;
24
use Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver;
25
use Doctrine\ORM\Mapping\Driver\XmlDriver;
26
use Doctrine\ORM\Mapping\Driver\YamlDriver;
27
use Doctrine\ORM\Repository\DefaultRepositoryFactory;
28
use Pimple\Container;
29
use Pimple\ServiceProviderInterface;
30
31
/**
32
 * This provider is heavily inspired by
33
 * https://github.com/dflydev/dflydev-doctrine-orm-service-provider/blob/master/src/Dflydev/Provider/DoctrineOrm/DoctrineOrmServiceProvider.php.
34
 */
35
final class DoctrineOrmServiceProvider implements ServiceProviderInterface
36
{
37
    /**
38
     * Register ORM service.
39
     *
40
     * @param Container $container
41
     */
42 3
    public function register(Container $container)
43
    {
44 3
        $container['doctrine.orm.em'] = $this->getOrmEmDefinition($container);
45 3
        $container['doctrine.orm.em.config'] = $this->getOrmEmConfigDefinition($container);
46 3
        $container['doctrine.orm.em.default_options'] = $this->getOrmEmDefaultOptions();
47 3
        $container['doctrine.orm.ems'] = $this->getOrmEmsDefinition($container);
48 3
        $container['doctrine.orm.ems.config'] = $this->getOrmEmsConfigServiceProvider($container);
49 3
        $container['doctrine.orm.ems.options.initializer'] = $this->getOrmEmsOptionsInitializerDefinition($container);
50 3
        $container['doctrine.orm.entity.listener_resolver.default'] = $this->getOrmEntityListenerResolverDefinition($container);
51 3
        $container['doctrine.orm.manager_registry'] = $this->getOrmManagerRegistryDefintion($container);
52 3
        $container['doctrine.orm.mapping_driver.factory.annotation'] = $this->getOrmMappingDriverFactoryAnnotation($container);
53 3
        $container['doctrine.orm.mapping_driver.factory.class_map'] = $this->getOrmMappingDriverFactoryClassMap($container);
54 3
        $container['doctrine.orm.mapping_driver.factory.php'] = $this->getOrmMappingDriverFactoryPhp($container);
55 3
        $container['doctrine.orm.mapping_driver.factory.simple_xml'] = $this->getOrmMappingDriverFactorySimpleXml($container);
56 3
        $container['doctrine.orm.mapping_driver.factory.simple_yaml'] = $this->getOrmMappingDriverFactorySimpleYaml($container);
57 3
        $container['doctrine.orm.mapping_driver.factory.static_php'] = $this->getOrmMappingDriverFactoryStaticPhp($container);
58 3
        $container['doctrine.orm.mapping_driver.factory.xml'] = $this->getOrmMappingDriverFactoryXml($container);
59 3
        $container['doctrine.orm.mapping_driver.factory.yaml'] = $this->getOrmMappingDriverFactoryYaml($container);
60 3
        $container['doctrine.orm.mapping_driver_chain'] = $this->getOrmMappingDriverChainDefinition($container);
61 3
        $container['doctrine.orm.repository.factory.default'] = $this->getOrmRepositoryFactoryDefinition($container);
62 3
        $container['doctrine.orm.strategy.naming.default'] = $this->getOrmNamingStrategyDefinition($container);
63 3
        $container['doctrine.orm.strategy.quote.default'] = $this->getOrmQuoteStrategyDefinition($container);
64 3
    }
65
66
    /**
67
     * @param Container $container
68
     *
69
     * @return callable
70
     */
71
    private function getOrmEmDefinition(Container $container): callable
72
    {
73 3
        return function () use ($container) {
74 2
            $ems = $container['doctrine.orm.ems'];
75
76 2
            return $ems[$container['doctrine.orm.ems.default']];
77 3
        };
78
    }
79
80
    /**
81
     * @param Container $container
82
     *
83
     * @return callable
84
     */
85
    private function getOrmEmConfigDefinition(Container $container): callable
86
    {
87 3
        return function () use ($container) {
88 3
            $configs = $container['doctrine.orm.ems.config'];
89
90 3
            return $configs[$container['doctrine.orm.ems.default']];
91 3
        };
92
    }
93
94
    /**
95
     * @return array
96
     */
97 3
    private function getOrmEmDefaultOptions(): array
98
    {
99
        return [
100 3
            'cache.hydration' => ['type' => 'array'],
101
            'cache.metadata' => ['type' => 'array'],
102
            'cache.query' => ['type' => 'array'],
103
            'class_metadata.factory.name' => ClassMetadataFactory::class,
104 3
            'connection' => 'default',
105
            'custom.functions.datetime' => [],
106
            'custom.functions.numeric' => [],
107
            'custom.functions.string' => [],
108
            'custom.hydration_modes' => [],
109 3
            'entity.listener_resolver' => 'default',
110
            'mappings' => [],
111
            'proxies.auto_generate' => true,
112 3
            'proxies.dir' => sys_get_temp_dir().'/doctrine/orm/proxies',
113 3
            'proxies.namespace' => 'DoctrineProxy',
114
            'query_hints' => [],
115
            'repository.default.class' => EntityRepository::class,
116 3
            'repository.factory' => 'default',
117
            'second_level_cache' => ['type' => 'array'],
118
            'second_level_cache.enabled' => false,
119 3
            'strategy.naming' => 'default',
120 3
            'strategy.quote' => 'default',
121
        ];
122
    }
123
124
    /**
125
     * @param Container $container
126
     *
127
     * @return callable
128
     */
129
    private function getOrmEmsDefinition(Container $container): callable
130
    {
131 3
        return function () use ($container) {
132 3
            $container['doctrine.orm.ems.options.initializer']();
133
134 3
            $ems = new Container();
135 3
            foreach ($container['doctrine.orm.ems.options'] as $name => $options) {
136 3
                if ($container['doctrine.orm.ems.default'] === $name) {
137 3
                    $config = $container['doctrine.orm.em.config'];
138
                } else {
139 1
                    $config = $container['doctrine.orm.ems.config'][$name];
140
                }
141
142 3
                $ems[$name] = function () use ($container, $options, $config) {
143 3
                    return EntityManager::create(
144 3
                        $container['doctrine.dbal.dbs'][$options['connection']],
145 3
                        $config,
146 3
                        $container['doctrine.dbal.dbs.event_manager'][$options['connection']]
147
                    );
148 3
                };
149
            }
150
151 3
            return $ems;
152 3
        };
153
    }
154
155
    /**
156
     * @param Container $container
157
     *
158
     * @return callable
159
     */
160
    private function getOrmEmsConfigServiceProvider(Container $container): callable
161
    {
162 3
        return function () use ($container) {
163 3
            $container['doctrine.orm.ems.options.initializer']();
164
165 3
            $configs = new Container();
166 3
            foreach ($container['doctrine.orm.ems.options'] as $name => $options) {
167 3
                $connectionName = $options['connection'];
168
169 3
                $config = new Configuration();
170
171 3
                $config->setSQLLogger($container['doctrine.dbal.dbs.config'][$connectionName]->getSQLLogger());
172
173 3
                $config->setQueryCacheImpl($this->getCache($container, $options['cache.query']));
174 3
                $config->setHydrationCacheImpl($this->getCache($container, $options['cache.hydration']));
175 3
                $config->setMetadataCacheImpl($this->getCache($container, $options['cache.metadata']));
176
177 3
                $config->setResultCacheImpl(
178 3
                    $container['doctrine.dbal.dbs.config'][$connectionName]->getResultCacheImpl()
179
                );
180
181 3
                $config->setClassMetadataFactoryName($options['class_metadata.factory.name']);
182
183 3
                $config->setCustomDatetimeFunctions($options['custom.functions.datetime']);
184 3
                $config->setCustomHydrationModes($options['custom.hydration_modes']);
185 3
                $config->setCustomNumericFunctions($options['custom.functions.numeric']);
186 3
                $config->setCustomStringFunctions($options['custom.functions.string']);
187
188 3
                $config->setEntityListenerResolver(
189
                    $container[
190 3
                        sprintf('doctrine.orm.entity.listener_resolver.%s', $options['entity.listener_resolver'])
191
                    ]
192
                );
193
194 3
                $config->setMetadataDriverImpl(
195 3
                    $container['doctrine.orm.mapping_driver_chain']($config, $options['mappings'])
196
                );
197
198 3
                $config->setAutoGenerateProxyClasses($options['proxies.auto_generate']);
199 3
                $config->setProxyDir($options['proxies.dir']);
200 3
                $config->setProxyNamespace($options['proxies.namespace']);
201
202 3
                $config->setDefaultQueryHints($options['query_hints']);
203
204 3
                $config->setRepositoryFactory(
205 3
                    $container[sprintf('doctrine.orm.repository.factory.%s', $options['repository.factory'])]
206
                );
207 3
                $config->setDefaultRepositoryClassName($options['repository.default.class']);
208
209 3
                $this->assignSecondLevelCache($container, $config, $options);
210
211 3
                $config->setNamingStrategy(
212 3
                    $container[sprintf('doctrine.orm.strategy.naming.%s', $options['strategy.naming'])]
213
                );
214 3
                $config->setQuoteStrategy(
215 3
                    $container[sprintf('doctrine.orm.strategy.quote.%s', $options['strategy.quote'])]
216
                );
217
218 3
                $configs[$name] = $config;
219
            }
220
221 3
            return $configs;
222 3
        };
223
    }
224
225
    /**
226
     * @param Container    $container
227
     * @param string|array $cacheDefinition
228
     *
229
     * @return Cache
230
     */
231 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...
232
    {
233 3
        $cacheType = $cacheDefinition['type'];
234 3
        $cacheOptions = $cacheDefinition['options'] ?? [];
235
236 3
        $cacheFactory = $container[sprintf('doctrine.dbal.db.cache_factory.%s', $cacheType)];
237
238 3
        return $cacheFactory($cacheOptions);
239
    }
240
241
    /**
242
     * @param Container     $container
243
     * @param Configuration $config
244
     * @param array         $options
245
     */
246 3
    private function assignSecondLevelCache(Container $container, Configuration $config, array $options)
247
    {
248 3
        if (!$options['second_level_cache.enabled']) {
249 2
            $config->setSecondLevelCacheEnabled(false);
250
251 2
            return;
252
        }
253
254 1
        $regionsCacheConfiguration = new RegionsConfiguration();
255 1
        $factory = new DefaultCacheFactory(
256 1
            $regionsCacheConfiguration,
257 1
            $this->getCache($container, $options['second_level_cache'])
258
        );
259
260 1
        $cacheConfiguration = new CacheConfiguration();
261 1
        $cacheConfiguration->setCacheFactory($factory);
262 1
        $cacheConfiguration->setRegionsConfiguration($regionsCacheConfiguration);
263
264 1
        $config->setSecondLevelCacheEnabled(true);
265 1
        $config->setSecondLevelCacheConfiguration($cacheConfiguration);
266 1
    }
267
268
    /**
269
     * @param Container $container
270
     *
271
     * @return callable
272
     */
273
    private function getOrmEmsOptionsInitializerDefinition(Container $container): callable
274
    {
275 3
        return $container->protect(function () use ($container) {
276 3
            static $initialized = false;
277
278 3
            if ($initialized) {
279 3
                return;
280
            }
281
282 3
            $initialized = true;
283
284 3
            if (!isset($container['doctrine.orm.ems.options'])) {
285 2
                $container['doctrine.orm.ems.options'] = [
286 2
                    'default' => $container['doctrine.orm.em.options'] ?? [],
287
                ];
288
            }
289
290 3
            $tmp = $container['doctrine.orm.ems.options'];
291 3
            foreach ($tmp as $name => &$options) {
292 3
                $options = array_replace($container['doctrine.orm.em.default_options'], $options);
293
294 3
                if (!isset($container['doctrine.orm.ems.default'])) {
295 3
                    $container['doctrine.orm.ems.default'] = $name;
296
                }
297
            }
298
299 3
            $container['doctrine.orm.ems.options'] = $tmp;
300 3
        });
301
    }
302
303
    /**
304
     * @param Container $container
305
     *
306
     * @return callable
307
     */
308
    private function getOrmEntityListenerResolverDefinition(Container $container): callable
309
    {
310 3
        return function () use ($container) {
311 2
            return new DefaultEntityListenerResolver();
312 3
        };
313
    }
314
315
    /**
316
     * @param Container $container
317
     *
318
     * @return callable
319
     */
320
    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...
321
    {
322 3
        return function ($container) {
323 1
            return new DoctrineOrmManagerRegistry($container);
324 3
        };
325
    }
326
327
    /**
328
     * @param Container $container
329
     *
330
     * @return callable
331
     */
332
    private function getOrmMappingDriverFactoryAnnotation(Container $container): callable
333
    {
334 3
        return $container->protect(function (array $mapping, Configuration $config) {
335 2
            return $config->newDefaultAnnotationDriver((array) $mapping['path'], false);
336 3
        });
337
    }
338
339
    /**
340
     * @param Container $container
341
     *
342
     * @return callable
343
     */
344
    private function getOrmMappingDriverFactoryClassMap(Container $container): callable
345
    {
346 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...
347 1
            return new ClassMapDriver($mapping['map']);
348 3
        });
349
    }
350
351
    /**
352
     * @param Container $container
353
     *
354
     * @return callable
355
     */
356
    private function getOrmMappingDriverFactoryPhp(Container $container): callable
357
    {
358 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...
359 1
            return new PHPDriver($mapping['path']);
360 3
        });
361
    }
362
363
    /**
364
     * @param Container $container
365
     *
366
     * @return callable
367
     */
368 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...
369
    {
370 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...
371 1
            return new SimplifiedYamlDriver(
372 1
                [$mapping['path'] => $mapping['namespace']],
373 1
                $mapping['extension'] ?? SimplifiedYamlDriver::DEFAULT_FILE_EXTENSION
374
            );
375 3
        });
376
    }
377
378
    /**
379
     * @param Container $container
380
     *
381
     * @return callable
382
     */
383 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...
384
    {
385 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...
386 1
            return new SimplifiedXmlDriver(
387 1
                [$mapping['path'] => $mapping['namespace']],
388 1
                $mapping['extension'] ?? SimplifiedXmlDriver::DEFAULT_FILE_EXTENSION
389
            );
390 3
        });
391
    }
392
393
    /**
394
     * @param Container $container
395
     *
396
     * @return callable
397
     */
398
    private function getOrmMappingDriverFactoryStaticPhp(Container $container): callable
399
    {
400 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...
401 1
            return new StaticPHPDriver($mapping['path']);
402 3
        });
403
    }
404
405
    /**
406
     * @param Container $container
407
     *
408
     * @return callable
409
     */
410
    private function getOrmMappingDriverFactoryYaml(Container $container): callable
411
    {
412 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...
413 1
            return new YamlDriver($mapping['path'], $mapping['extension'] ?? YamlDriver::DEFAULT_FILE_EXTENSION);
414 3
        });
415
    }
416
417
    /**
418
     * @param Container $container
419
     *
420
     * @return callable
421
     */
422
    private function getOrmMappingDriverFactoryXml(Container $container): callable
423
    {
424 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...
425 1
            return new XmlDriver($mapping['path'], $mapping['extension'] ?? XmlDriver::DEFAULT_FILE_EXTENSION);
426 3
        });
427
    }
428
429
    /**
430
     * @param Container $container
431
     *
432
     * @return callable
433
     */
434
    private function getOrmMappingDriverChainDefinition(Container $container): callable
435
    {
436 3
        return $container->protect(function (Configuration $config, array $mappings) use ($container) {
437 3
            $chain = new MappingDriverChain();
438 3
            foreach ($mappings as $mapping) {
439 2
                if (isset($mapping['alias'])) {
440 1
                    $config->addEntityNamespace($mapping['alias'], $mapping['namespace']);
441
                }
442
443 2
                $factoryKey = sprintf('doctrine.orm.mapping_driver.factory.%s', $mapping['type']);
444
445 2
                $chain->addDriver($container[$factoryKey]($mapping, $config), $mapping['namespace']);
446
            }
447
448 3
            return $chain;
449 3
        });
450
    }
451
452
    /**
453
     * @param Container $container
454
     *
455
     * @return callable
456
     */
457
    private function getOrmRepositoryFactoryDefinition(Container $container): callable
458
    {
459 3
        return function () use ($container) {
460 2
            return new DefaultRepositoryFactory();
461 3
        };
462
    }
463
464
    /**
465
     * @param Container $container
466
     *
467
     * @return callable
468
     */
469
    private function getOrmNamingStrategyDefinition(Container $container): callable
470
    {
471 3
        return function () use ($container) {
472 2
            return new DefaultNamingStrategy();
473 3
        };
474
    }
475
476
    /**
477
     * @param Container $container
478
     *
479
     * @return callable
480
     */
481
    private function getOrmQuoteStrategyDefinition(Container $container): callable
482
    {
483 3
        return function () use ($container) {
484 2
            return new DefaultQuoteStrategy();
485 3
        };
486
    }
487
}
488