Completed
Push — master ( 01e9a3...b0156c )
by Kamil
18:54
created

MultiContainerExtension   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 17
c 3
b 1
f 0
lcom 1
cbo 11
dl 0
loc 150
rs 10

13 Methods

Rating   Name   Duplication   Size   Complexity  
A getConfigKey() 0 4 1
A initialize() 0 4 1
A configure() 0 5 1
A load() 0 13 1
A process() 0 12 2
A addContainer() 0 4 1
A registerAutoloader() 0 8 2
A loadImportedServicesFiles() 0 8 2
A declareScenarioScope() 0 6 2
A loadEnvironmentHandler() 0 10 1
A enableLazyServicesSupport() 0 4 1
A loadContextRegistry() 0 4 1
A loadScopeManipulator() 0 7 1
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Behat\MultiContainerExtension\ServiceContainer;
13
14
use Behat\Testwork\Environment\ServiceContainer\EnvironmentExtension;
15
use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension;
16
use Behat\Testwork\ServiceContainer\Extension;
17
use Behat\Testwork\ServiceContainer\ExtensionManager;
18
use Sylius\Behat\MultiContainerExtension\ContainerConfiguration;
19
use Sylius\Behat\MultiContainerExtension\Context\Environment\Handler\ContextServiceEnvironmentHandler;
20
use Sylius\Behat\MultiContainerExtension\ContextRegistry;
21
use Sylius\Behat\MultiContainerExtension\Loader\XmlFileLoader;
22
use Sylius\Behat\MultiContainerExtension\ScopeManipulator;
23
use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
24
use Symfony\Component\ClassLoader\ClassLoader;
25
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
26
use Symfony\Component\Config\FileLocator;
27
use Symfony\Component\DependencyInjection\ContainerBuilder;
28
use Symfony\Component\DependencyInjection\Definition;
29
use Symfony\Component\DependencyInjection\Reference;
30
use Symfony\Component\DependencyInjection\Scope;
31
32
/**
33
 * @author Kamil Kokot <[email protected]>
34
 */
35
final class MultiContainerExtension implements Extension
36
{
37
    /**
38
     * @var ContainerConfiguration
39
     */
40
    private $containerConfiguration;
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function getConfigKey()
46
    {
47
        return 'sylius_multi_container';
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function initialize(ExtensionManager $extensionManager)
54
    {
55
        $this->containerConfiguration = new ContainerConfiguration('behat');
56
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function configure(ArrayNodeDefinition $builder)
62
    {
63
        $config = $builder->children();
64
        $config->arrayNode('imports')->prototype('scalar');
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function load(ContainerBuilder $container, array $config)
71
    {
72
        $this->enableLazyServicesSupport($container);
73
74
        $this->registerAutoloader($container);
75
        $this->loadImportedServicesFiles($container, $config);
76
77
        $this->loadContextRegistry($container);
78
        $this->loadScopeManipulator($container);
79
80
        $this->declareScenarioScope($container);
81
        $this->loadEnvironmentHandler($container);
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87
    public function process(ContainerBuilder $container)
88
    {
89
        $contextRegistryDefinition = $container->findDefinition('sylius_multi_container.context_registry');
90
        $taggedServices = $container->findTaggedServiceIds('sylius.behat.context');
91
92
        foreach ($taggedServices as $id => $tags) {
93
            $contextRegistryDefinition->addMethodCall(
94
                'add',
95
                [$id, $container->findDefinition($id)->getClass()]
96
            );
97
        }
98
    }
99
100
    /**
101
     * @param string $containerName
102
     * @param string $containerId
103
     */
104
    public function addContainer($containerName, $containerId)
105
    {
106
        $this->containerConfiguration->addContainer($containerName, $containerId);
107
    }
108
109
    /**
110
     * @param ContainerBuilder $container
111
     */
112
    private function registerAutoloader(ContainerBuilder $container)
113
    {
114
        $classLoader = new ClassLoader();
115
        foreach ($container->getParameter('class_loader.prefixes') as $namespace => $path) {
116
            $classLoader->addPrefix($namespace, str_replace('%paths.base%', $container->getParameter('paths.base'), $path));
117
        }
118
        $classLoader->register();
119
    }
120
121
    /**
122
     * @param ContainerBuilder $container
123
     * @param array $config
124
     */
125
    private function loadImportedServicesFiles(ContainerBuilder $container, array $config)
126
    {
127
        $basePath = $container->getParameter('paths.base');
128
        $xmlLoader = new XmlFileLoader($container, new FileLocator($basePath), $this->containerConfiguration);
129
        foreach ($config['imports'] as $file) {
130
            $xmlLoader->load($file);
131
        }
132
    }
133
134
    /**
135
     * @param ContainerBuilder $container
136
     */
137
    private function declareScenarioScope(ContainerBuilder $container)
138
    {
139
        if (!$container->hasScope('scenario')) {
140
            $container->addScope(new Scope('scenario'));
141
        }
142
    }
143
144
    /**
145
     * @param ContainerBuilder $container
146
     */
147
    private function loadEnvironmentHandler(ContainerBuilder $container)
148
    {
149
        $definition = new Definition(ContextServiceEnvironmentHandler::class, [
150
            new Reference('sylius_multi_container.context_registry'),
151
            new Reference('service_container')
152
        ]);
153
        $definition->addTag(EnvironmentExtension::HANDLER_TAG, ['priority' => 128]);
154
155
        $container->setDefinition('sylius_multi_container.environment_handler.context_service', $definition);
156
    }
157
158
    /**
159
     * @param ContainerBuilder $container
160
     */
161
    private function enableLazyServicesSupport(ContainerBuilder $container)
162
    {
163
        $container->setProxyInstantiator(new RuntimeInstantiator());
164
    }
165
166
    /**
167
     * @param ContainerBuilder $container
168
     */
169
    private function loadContextRegistry(ContainerBuilder $container)
170
    {
171
        $container->setDefinition('sylius_multi_container.context_registry', new Definition(ContextRegistry::class));
172
    }
173
174
    /**
175
     * @param ContainerBuilder $container
176
     */
177
    private function loadScopeManipulator(ContainerBuilder $container)
178
    {
179
        $definition = new Definition(ScopeManipulator::class, [new Reference('service_container')]);
180
        $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG);
181
182
        $container->setDefinition('sylius_multi_container.scope_manipulator', $definition);
183
    }
184
}
185