Passed
Push — master ( d6988f...e83fc5 )
by Dominik
08:39
created

getOrmCacheLocatorDefinition()   C

Complexity

Conditions 8
Paths 1

Size

Total Lines 35
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 35
ccs 0
cts 27
cp 0
rs 5.3846
cc 8
eloc 18
nc 1
nop 1
crap 72
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * (c) Beau Simensen <[email protected]> (https://github.com/dflydev/dflydev-doctrine-orm-service-provider)
7
 */
8
9
namespace Chubbyphp\ServiceProvider;
10
11
use Doctrine\Common\Cache\ApcuCache;
12
use Doctrine\Common\Cache\ArrayCache;
13
use Doctrine\Common\Cache\CacheProvider;
14
use Doctrine\Common\Cache\FilesystemCache;
15
use Doctrine\Common\Cache\MemcacheCache;
16
use Doctrine\Common\Cache\MemcachedCache;
17
use Doctrine\Common\Cache\XcacheCache;
18
use Doctrine\Common\Cache\RedisCache;
19
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver;
20
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
21
use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver;
22
use Doctrine\DBAL\Types\Type;
23
use Doctrine\ORM\Configuration;
24
use Doctrine\ORM\EntityManager;
25
use Doctrine\ORM\EntityRepository;
26
use Doctrine\ORM\Mapping\ClassMetadataFactory;
27
use Doctrine\ORM\Mapping\DefaultEntityListenerResolver;
28
use Doctrine\ORM\Mapping\DefaultNamingStrategy;
29
use Doctrine\ORM\Mapping\DefaultQuoteStrategy;
30
use Doctrine\ORM\Mapping\Driver\SimplifiedXmlDriver;
31
use Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver;
32
use Doctrine\ORM\Mapping\Driver\XmlDriver;
33
use Doctrine\ORM\Mapping\Driver\YamlDriver;
34
use Doctrine\ORM\Repository\DefaultRepositoryFactory;
35
use Pimple\Container;
36
use Pimple\ServiceProviderInterface;
37
38
final class DoctrineOrmServiceProvider implements ServiceProviderInterface
39
{
40
    /**
41
     * Register ORM service.
42
     *
43
     * @param Container $container
44
     */
45
    public function register(Container $container)
46
    {
47
        $container['orm.em.default_options'] = $this->getOrmEmDefaultOptions();
48
        $container['orm.ems.options.initializer'] = $this->getOrmEmsOptionsInitializerDefinition($container);
49
        $container['orm.em_name_from_param_key'] = $this->getOrmEmNameFromParamKeyDefinition($container);
50
        $container['orm.ems'] = $this->getOrmEmsDefinition($container);
51
        $container['orm.ems.config'] = $this->getOrmEmsConfigServiceProvider($container);
52
        $container['orm.cache.configurer'] = $this->getOrmCacheLocatorDefinition($container);
53
        $container['orm.cache.factory.apcu'] = $this->getOrmCacheFactoryApcuDefinition($container);
54
        $container['orm.cache.factory.array'] = $this->getOrmCacheFactoryArrayDefinition($container);
55
        $container['orm.cache.factory.filesystem'] = $this->getOrmCacheFactoryFilesystemDefinition($container);
56
        $container['orm.cache.factory.memcache'] = $this->getOrmCacheFactoryMemcacheDefinition($container);
57
        $container['orm.cache.factory.memcached'] = $this->getOrmCacheFactoryMemcachedDefinition($container);
58
        $container['orm.cache.factory.redis'] = $this->getOrmCacheFactoryRedisDefinition($container);
59
        $container['orm.cache.factory.xcache'] = $this->getOrmCacheFactoryXCacheDefinition($container);
60
        $container['orm.cache.factory'] = $this->getOrmCacheFactoryDefinition($container);
61
        $container['orm.mapping_driver_chain.locator'] = $this->getOrmMappingDriverChainLocatorDefinition($container);
62
        $container['orm.mapping_driver_chain.factory'] = $this->getOrmMappingDriverChainFactoryDefinition($container);
63
64
        $container['orm.add_mapping_driver'] = $container->protect(function (MappingDriver $mappingDriver, $namespace, $name = null) use ($container) {
65
            $container['orm.ems.options.initializer']();
66
67
            if (null === $name) {
68
                $name = $container['orm.ems.default'];
69
            }
70
71
            /** @var MappingDriverChain $driverChain */
72
            $driverChain = $container['orm.mapping_driver_chain.locator']($name);
73
            $driverChain->addDriver($mappingDriver, $namespace);
74
        });
75
76
        $container['orm.strategy.naming'] = function ($container) {
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...
77
            return new DefaultNamingStrategy();
78
        };
79
80
        $container['orm.strategy.quote'] = function ($container) {
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...
81
            return new DefaultQuoteStrategy();
82
        };
83
84
        $container['orm.entity_listener_resolver'] = function ($container) {
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...
85
            return new DefaultEntityListenerResolver();
86
        };
87
88
        $container['orm.repository_factory'] = function ($container) {
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...
89
            return new DefaultRepositoryFactory();
90
        };
91
92
        $container['orm.em'] = function ($container) {
93
            $ems = $container['orm.ems'];
94
95
            return $ems[$container['orm.ems.default']];
96
        };
97
98
        $container['orm.em.config'] = function ($container) {
99
            $configs = $container['orm.ems.config'];
100
101
            return $configs[$container['orm.ems.default']];
102
        };
103
104
        $container['orm.proxies_dir'] = sys_get_temp_dir();
105
        $container['orm.proxies_namespace'] = 'DoctrineProxy';
106
        $container['orm.auto_generate_proxies'] = true;
107
        $container['orm.default_cache'] = ['driver' => 'array'];
108
        $container['orm.custom.functions.string'] = [];
109
        $container['orm.custom.functions.numeric'] = [];
110
        $container['orm.custom.functions.datetime'] = [];
111
        $container['orm.custom.hydration_modes'] = [];
112
        $container['orm.class_metadata_factory_name'] = ClassMetadataFactory::class;
113
        $container['orm.default_repository_class'] = EntityRepository::class;
114
    }
115
116
    /**
117
     * @return array
118
     */
119
    private function getOrmEmDefaultOptions(): array
120
    {
121
        return [
122
            'connection' => 'default',
123
            'mappings' => [],
124
            'types' => [],
125
        ];
126
    }
127
128
    /**
129
     * @param Container $container
130
     *
131
     * @return \Closure
132
     */
133
    private function getOrmEmsOptionsInitializerDefinition(Container $container): \Closure
134
    {
135
        return $container->protect(function () use ($container) {
136
            static $initialized = false;
137
138
            if ($initialized) {
139
                return;
140
            }
141
142
            $initialized = true;
143
144
            if (!isset($container['orm.ems.options'])) {
145
                $container['orm.ems.options'] = [
146
                    'default' => isset($container['orm.em.options']) ? $container['orm.em.options'] : [],
147
                ];
148
            }
149
150
            $tmp = $container['orm.ems.options'];
151
            foreach ($tmp as $name => &$options) {
152
                $options = array_replace($container['orm.em.default_options'], $options);
153
154
                if (!isset($container['orm.ems.default'])) {
155
                    $container['orm.ems.default'] = $name;
156
                }
157
            }
158
159
            $container['orm.ems.options'] = $tmp;
160
        });
161
    }
162
163
    /**
164
     * @param Container $container
165
     *
166
     * @return \Closure
167
     */
168
    private function getOrmEmNameFromParamKeyDefinition(Container $container): \Closure
169
    {
170
        return $container->protect(function ($paramKey) use ($container) {
171
            $container['orm.ems.options.initializer']();
172
173
            if (isset($container[$paramKey])) {
174
                return $container[$paramKey];
175
            }
176
177
            return $container['orm.ems.default'];
178
        });
179
    }
180
181
    /**
182
     * @param Container $container
183
     *
184
     * @return \Closure
185
     */
186
    private function getOrmEmsDefinition(Container $container): \Closure
187
    {
188
        return function () use ($container) {
189
            $container['orm.ems.options.initializer']();
190
191
            $ems = new Container();
192
            foreach ($container['orm.ems.options'] as $name => $options) {
193
                if ($container['orm.ems.default'] === $name) {
194
                    // we use shortcuts here in case the default has been overridden
195
                    $config = $container['orm.em.config'];
196
                } else {
197
                    $config = $container['orm.ems.config'][$name];
198
                }
199
200
                $ems[$name] = function ($ems) use ($container, $options, $config) {
0 ignored issues
show
Unused Code introduced by
The parameter $ems 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...
201
                    return EntityManager::create(
202
                        $container['dbs'][$options['connection']],
203
                        $config,
204
                        $container['dbs.event_manager'][$options['connection']]
205
                    );
206
                };
207
            }
208
209
            return $ems;
210
        };
211
    }
212
213
    /**
214
     * @param Container $container
215
     *
216
     * @return \Closure
217
     */
218
    private function getOrmEmsConfigServiceProvider(Container $container): \Closure
219
    {
220
        return function () use ($container) {
221
            $container['orm.ems.options.initializer']();
222
223
            $configs = new Container();
224
            foreach ($container['orm.ems.options'] as $name => $options) {
225
                $config = new Configuration();
226
227
                $container['orm.cache.configurer']($name, $config, $options);
228
229
                $config->setProxyDir($container['orm.proxies_dir']);
230
                $config->setProxyNamespace($container['orm.proxies_namespace']);
231
                $config->setAutoGenerateProxyClasses($container['orm.auto_generate_proxies']);
232
233
                $config->setCustomStringFunctions($container['orm.custom.functions.string']);
234
                $config->setCustomNumericFunctions($container['orm.custom.functions.numeric']);
235
                $config->setCustomDatetimeFunctions($container['orm.custom.functions.datetime']);
236
                $config->setCustomHydrationModes($container['orm.custom.hydration_modes']);
237
238
                $config->setClassMetadataFactoryName($container['orm.class_metadata_factory_name']);
239
                $config->setDefaultRepositoryClassName($container['orm.default_repository_class']);
240
241
                $config->setEntityListenerResolver($container['orm.entity_listener_resolver']);
242
                $config->setRepositoryFactory($container['orm.repository_factory']);
243
244
                $config->setNamingStrategy($container['orm.strategy.naming']);
245
                $config->setQuoteStrategy($container['orm.strategy.quote']);
246
247
                /** @var MappingDriverChain $chain */
248
                $chain = $container['orm.mapping_driver_chain.locator']($name);
249
250
                foreach ((array) $options['mappings'] as $entity) {
251
                    if (!is_array($entity)) {
252
                        throw new \InvalidArgumentException(
253
                            "The 'orm.em.options' option 'mappings' should be an array of arrays."
254
                        );
255
                    }
256
257
                    if (isset($entity['alias'])) {
258
                        $config->addEntityNamespace($entity['alias'], $entity['namespace']);
259
                    }
260
261
                    switch ($entity['type']) {
262
                        case 'annotation':
263
                            $useSimpleAnnotationReader = $entity['use_simple_annotation_reader'] ?? true;
264
                            $driver = $config->newDefaultAnnotationDriver(
265
                                (array) $entity['path'],
266
                                $useSimpleAnnotationReader
267
                            );
268
                            $chain->addDriver($driver, $entity['namespace']);
269
                            break;
270 View Code Duplication
                        case 'yml':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
271
                            $driver = new YamlDriver($entity['path']);
272
                            $chain->addDriver($driver, $entity['namespace']);
273
                            break;
274 View Code Duplication
                        case 'simple_yml':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
275
                            $driver = new SimplifiedYamlDriver([$entity['path'] => $entity['namespace']]);
276
                            $chain->addDriver($driver, $entity['namespace']);
277
                            break;
278 View Code Duplication
                        case 'xml':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
279
                            $driver = new XmlDriver($entity['path']);
280
                            $chain->addDriver($driver, $entity['namespace']);
281
                            break;
282 View Code Duplication
                        case 'simple_xml':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
283
                            $driver = new SimplifiedXmlDriver([$entity['path'] => $entity['namespace']]);
284
                            $chain->addDriver($driver, $entity['namespace']);
285
                            break;
286 View Code Duplication
                        case 'php':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
287
                            $driver = new StaticPHPDriver($entity['path']);
288
                            $chain->addDriver($driver, $entity['namespace']);
289
                            break;
290
                        default:
291
                            throw new \InvalidArgumentException(
292
                                sprintf('"%s" is not a recognized driver', $entity['type'])
293
                            );
294
                            break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
295
                    }
296
                }
297
298
                $config->setMetadataDriverImpl($chain);
299
300
                foreach ((array) $options['types'] as $typeName => $typeClass) {
301
                    if (Type::hasType($typeName)) {
302
                        Type::overrideType($typeName, $typeClass);
303
                    } else {
304
                        Type::addType($typeName, $typeClass);
305
                    }
306
                }
307
308
                $configs[$name] = $config;
309
            }
310
311
            return $configs;
312
        };
313
    }
314
315
    /**
316
     * @param Container $container
317
     *
318
     * @return \Closure
319
     */
320
    private function getOrmCacheConfigurerDefinition(Container $container): \Closure
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
321
    {
322
        return $container->protect(function ($name, Configuration $config, $options) use ($container) {
323
            $config->setMetadataCacheImpl($container['orm.cache.locator']($name, 'metadata', $options));
324
            $config->setQueryCacheImpl($container['orm.cache.locator']($name, 'query', $options));
325
            $config->setResultCacheImpl($container['orm.cache.locator']($name, 'result', $options));
326
            $config->setHydrationCacheImpl($container['orm.cache.locator']($name, 'hydration', $options));
327
        });
328
    }
329
330
    /**
331
     * @param Container $container
332
     *
333
     * @return \Closure
334
     */
335
    private function getOrmCacheLocatorDefinition(Container $container): \Closure
336
    {
337
        return $container->protect(function ($name, $cacheName, $options) use ($container) {
338
            $cacheNameKey = $cacheName.'_cache';
339
340
            if (!isset($options[$cacheNameKey])) {
341
                $options[$cacheNameKey] = $container['orm.default_cache'];
342
            }
343
344
            if (isset($options[$cacheNameKey]) && !is_array($options[$cacheNameKey])) {
345
                $options[$cacheNameKey] = [
346
                    'driver' => $options[$cacheNameKey],
347
                ];
348
            }
349
350
            if (!isset($options[$cacheNameKey]['driver'])) {
351
                throw new \RuntimeException("No driver specified for '$cacheName'");
352
            }
353
354
            $driver = $options[$cacheNameKey]['driver'];
355
356
            $cacheInstanceKey = 'orm.cache.instances.'.$name.'.'.$cacheName;
357
            if (isset($container[$cacheInstanceKey])) {
358
                return $container[$cacheInstanceKey];
359
            }
360
361
            $cache = $container['orm.cache.factory']($driver, $options[$cacheNameKey]);
362
363
            if (isset($options['cache_namespace']) && $cache instanceof CacheProvider) {
364
                $cache->setNamespace($options['cache_namespace']);
365
            }
366
367
            return $container[$cacheInstanceKey] = $cache;
368
        });
369
    }
370
371
    /**
372
     * @param Container $container
373
     *
374
     * @return \Closure
375
     */
376
    private function getOrmCacheFactoryApcuDefinition(Container $container): \Closure
377
    {
378
        return $container->protect(function () use ($container) {
379
            return new ApcuCache();
380
        });
381
    }
382
383
    /**
384
     * @param Container $container
385
     *
386
     * @return \Closure
387
     */
388
    private function getOrmCacheFactoryArrayDefinition(Container $container): \Closure
389
    {
390
        return $container->protect(function () use ($container) {
391
            return new ArrayCache();
392
        });
393
    }
394
395
    /**
396
     * @param Container $container
397
     *
398
     * @return \Closure
399
     */
400
    private function getOrmCacheFactoryFilesystemDefinition(Container $container): \Closure
401
    {
402
        return $container->protect(function ($cacheOptions) {
403
            if (empty($cacheOptions['path'])) {
404
                throw new \RuntimeException('FilesystemCache path not defined');
405
            }
406
407
            $cacheOptions += [
408
                'extension' => FilesystemCache::EXTENSION,
409
                'umask' => 0002,
410
            ];
411
412
            return new FilesystemCache($cacheOptions['path'], $cacheOptions['extension'], $cacheOptions['umask']);
413
        });
414
    }
415
416
    /**
417
     * @param Container $container
418
     *
419
     * @return \Closure
420
     */
421
    private function getOrmCacheFactoryMemcacheDefinition(Container $container): \Closure
422
    {
423
        return $container->protect(function ($cacheOptions) use ($container) {
424
            if (empty($cacheOptions['host']) || empty($cacheOptions['port'])) {
425
                throw new \RuntimeException('Host and port options need to be specified for memcache cache');
426
            }
427
428
            $memcache = new \Memcache();
429
            $memcache->connect($cacheOptions['host'], $cacheOptions['port']);
430
431
            $cache = new MemcacheCache();
432
            $cache->setMemcache($memcache);
433
434
            return $cache;
435
        });
436
    }
437
438
    /**
439
     * @param Container $container
440
     *
441
     * @return \Closure
442
     */
443
    private function getOrmCacheFactoryMemcachedDefinition(Container $container): \Closure
444
    {
445
        return $container->protect(function ($cacheOptions) use ($container) {
446
            if (empty($cacheOptions['host']) || empty($cacheOptions['port'])) {
447
                throw new \RuntimeException('Host and port options need to be specified for memcached cache');
448
            }
449
450
            $memcached = new \Memcached();
451
            $memcached->addServer($cacheOptions['host'], $cacheOptions['port']);
452
453
            $cache = new MemcachedCache();
454
            $cache->setMemcached($memcached);
455
456
            return $cache;
457
        });
458
    }
459
460
    /**
461
     * @param Container $container
462
     *
463
     * @return \Closure
464
     */
465
    private function getOrmCacheFactoryRedisDefinition(Container $container): \Closure
466
    {
467
        return $container->protect(function ($cacheOptions) use ($container) {
468
            if (empty($cacheOptions['host']) || empty($cacheOptions['port'])) {
469
                throw new \RuntimeException('Host and port options need to be specified for redis cache');
470
            }
471
472
            $redis = new \Redis();
473
            $redis->connect($cacheOptions['host'], $cacheOptions['port']);
474
475
            if (isset($cacheOptions['password'])) {
476
                $redis->auth($cacheOptions['password']);
477
            }
478
479
            $cache = new RedisCache();
480
            $cache->setRedis($redis);
481
482
            return $cache;
483
        });
484
    }
485
486
    /**
487
     * @param Container $container
488
     *
489
     * @return \Closure
490
     */
491
    private function getOrmCacheFactoryXCacheDefinition(Container $container): \Closure
492
    {
493
        return $container->protect(function () use ($container) {
494
            return new XcacheCache();
495
        });
496
    }
497
498
    /**
499
     * @param Container $container
500
     *
501
     * @return \Closure
502
     */
503
    private function getOrmCacheFactoryDefinition(Container $container): \Closure
504
    {
505
        return $container->protect(function ($driver, $cacheOptions) use ($container) {
506
            $cacheFactoryKey = 'orm.cache.factory.'.$driver;
507
            if (!isset($container[$cacheFactoryKey])) {
508
                throw new \RuntimeException(
509
                    sprintf('Factory "%s" for cache type "%s" not defined', $cacheFactoryKey, $driver)
510
                );
511
            }
512
513
            return $container[$cacheFactoryKey]($cacheOptions);
514
        });
515
    }
516
517
    /**
518
     * @param Container $container
519
     *
520
     * @return \Closure
521
     */
522
    private function getOrmMappingDriverChainLocatorDefinition(Container $container): \Closure
523
    {
524
        return $container->protect(function ($name = null) use ($container) {
525
            $container['orm.ems.options.initializer']();
526
527
            if (null === $name) {
528
                $name = $container['orm.ems.default'];
529
            }
530
531
            $cacheInstanceKey = 'orm.mapping_driver_chain.instances.'.$name;
532
            if (isset($container[$cacheInstanceKey])) {
533
                return $container[$cacheInstanceKey];
534
            }
535
536
            return $container[$cacheInstanceKey] = $container['orm.mapping_driver_chain.factory']($name);
537
        });
538
    }
539
540
    /**
541
     * @param Container $container
542
     *
543
     * @return \Closure
544
     */
545
    private function getOrmMappingDriverChainFactoryDefinition(Container $container): \Closure
546
    {
547
        return $container->protect(function () use ($container) {
548
            return new MappingDriverChain();
549
        });
550
    }
551
}
552