Completed
Pull Request — master (#6)
by Kamil
02:17
created

SymfonyExtension::getKernelFile()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 2
1
<?php
2
3
/*
4
 * This file is part of the SymfonyExtension package.
5
 *
6
 * (c) Kamil Kokot <[email protected]>
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 FriendsOfBehat\SymfonyExtension\ServiceContainer;
13
14
use Behat\MinkExtension\ServiceContainer\MinkExtension;
15
use Behat\Testwork\EventDispatcher\ServiceContainer\EventDispatcherExtension;
16
use Behat\Testwork\ServiceContainer\Extension;
17
use Behat\Testwork\ServiceContainer\ExtensionManager;
18
use FriendsOfBehat\SymfonyExtension\Driver\Factory\SymfonyDriverFactory;
19
use FriendsOfBehat\SymfonyExtension\Listener\KernelRebooter;
20
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
21
use Symfony\Component\DependencyInjection\Container;
22
use Symfony\Component\DependencyInjection\ContainerBuilder;
23
use Symfony\Component\DependencyInjection\Definition;
24
use Symfony\Component\DependencyInjection\Reference;
25
26
final class SymfonyExtension implements Extension
27
{
28
    /**
29
     * Kernel used inside Behat contexts or to create services injected to them.
30
     * Container is built before every scenario.
31
     */
32
    const KERNEL_ID = 'sylius_symfony_extension.kernel';
33
34
    /**
35
     * The current container used in scenario contexts.
36
     * To be used as a factory for current injected application services.
37
     */
38
    const KERNEL_CONTAINER_ID = 'sylius_symfony_extension.kernel.container';
39
40
    /**
41
     * Kernel used by Symfony2 driver to isolate web container from contexts' container.
42
     * Container is built before every request.
43
     */
44
    const DRIVER_KERNEL_ID = 'sylius_symfony_extension.driver_kernel';
45
46
    /**
47
     * Kernel that should be used by extensions only.
48
     * Container is built only once at the first use.
49
     */
50
    const SHARED_KERNEL_ID = 'sylius_symfony_extension.shared_kernel';
51
52
    /**
53
     * The only container built by shared kernel.
54
     * To be used as a factory for shared injected application services.
55
     */
56
    const SHARED_KERNEL_CONTAINER_ID = 'sylius_symfony_extension.shared_kernel.container';
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function getConfigKey()
62
    {
63
        return 'fob_symfony';
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function initialize(ExtensionManager $extensionManager)
70
    {
71
        $this->registerSymfonyDriverFactory($extensionManager);
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77
    public function configure(ArrayNodeDefinition $builder)
78
    {
79
        $builder
80
            ->addDefaultsIfNotSet()
81
                ->children()
82
                    ->arrayNode('kernel')
83
                        ->addDefaultsIfNotSet()
84
                        ->children()
85
                            ->scalarNode('bootstrap')->defaultValue('app/autoload.php')->end()
86
                            ->scalarNode('path')->defaultValue('app/AppKernel.php')->end()
87
                            ->scalarNode('class')->defaultValue('AppKernel')->end()
88
                            ->scalarNode('env')->defaultValue('test')->end()
89
                            ->booleanNode('debug')->defaultTrue()->end()
90
        ;
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96
    public function load(ContainerBuilder $container, array $config)
97
    {
98
        $this->loadKernel($container, $config['kernel']);
99
        $this->loadKernelContainer($container);
100
101
        $this->loadDriverKernel($container);
102
103
        $this->loadSharedKernel($container);
104
        $this->loadSharedKernelContainer($container);
105
106
        $this->loadKernelRebooter($container);
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function process(ContainerBuilder $container)
113
    {
114
    }
115
116
    /**
117
     * @param ContainerBuilder $container
118
     */
119
    private function loadKernel(ContainerBuilder $container, array $config)
120
    {
121
        $definition = new Definition($config['class'], array(
122
            $config['env'],
123
            $config['debug'],
124
        ));
125
        $definition->addMethodCall('boot');
126
        $definition->setFile($this->getKernelFile($container->getParameter('paths.base'), $config['path']));
127
128
        $container->setDefinition(self::KERNEL_ID, $definition);
129
130
        $this->requireKernelBootstrapFile($container->getParameter('paths.base'), $config['bootstrap']);
131
    }
132
133
    /**
134
     * @param ContainerBuilder $container
135
     */
136 View Code Duplication
    private function loadKernelContainer(ContainerBuilder $container)
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...
137
    {
138
        $containerDefinition = new Definition(Container::class);
139
        $containerDefinition->setFactory([
140
            new Reference(self::KERNEL_ID),
141
            'getContainer',
142
        ]);
143
144
        $container->setDefinition(self::KERNEL_CONTAINER_ID, $containerDefinition);
145
    }
146
147
    /**
148
     * @param ContainerBuilder $container
149
     */
150
    private function loadDriverKernel(ContainerBuilder $container)
151
    {
152
        $container->setDefinition(self::DRIVER_KERNEL_ID, $container->findDefinition(self::KERNEL_ID));
153
    }
154
155
    /**
156
     * @param ContainerBuilder $container
157
     */
158
    private function loadSharedKernel(ContainerBuilder $container)
159
    {
160
        $container->setDefinition(self::SHARED_KERNEL_ID, $container->findDefinition(self::KERNEL_ID));
161
    }
162
163
    /**
164
     * @param ContainerBuilder $container
165
     */
166 View Code Duplication
    private function loadSharedKernelContainer(ContainerBuilder $container)
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...
167
    {
168
        $containerDefinition = new Definition(Container::class);
169
        $containerDefinition->setFactory([
170
            new Reference(self::SHARED_KERNEL_ID),
171
            'getContainer',
172
        ]);
173
174
        $container->setDefinition(self::SHARED_KERNEL_CONTAINER_ID, $containerDefinition);
175
    }
176
177
    /**
178
     * @param ContainerBuilder $container
179
     */
180 View Code Duplication
    private function loadKernelRebooter(ContainerBuilder $container)
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...
181
    {
182
        $definition = new Definition(KernelRebooter::class, [new Reference(self::KERNEL_ID)]);
183
        $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG);
184
185
        $container->setDefinition(self::KERNEL_ID . '.rebooter', $definition);
186
    }
187
188
    /**
189
     * @param ExtensionManager $extensionManager
190
     */
191
    private function registerSymfonyDriverFactory(ExtensionManager $extensionManager)
192
    {
193
        /** @var MinkExtension $minkExtension */
194
        $minkExtension = $extensionManager->getExtension('mink');
195
        if (null === $minkExtension) {
196
            return;
197
        }
198
199
        $minkExtension->registerDriverFactory(new SymfonyDriverFactory(
200
            'symfony',
201
            new Reference(self::DRIVER_KERNEL_ID)
202
        ));
203
    }
204
205
    /**
206
     * @param string $basePath
207
     * @param string $kernelPath
208
     *
209
     * @return string|null
210
     */
211
    private function getKernelFile($basePath, $kernelPath)
212
    {
213
        $possibleFiles = [
214
            sprintf('%s/%s', $basePath, $kernelPath),
215
            $kernelPath,
216
        ];
217
218
        foreach ($possibleFiles as $possibleFile) {
219
            if (file_exists($possibleFile)) {
220
                return $possibleFile;
221
            }
222
        }
223
224
        return null;
225
    }
226
227
    /**
228
     * @param string $basePath
229
     * @param string|null $bootstrapPath
230
     *
231
     * @throws \DomainException
232
     */
233
    private function requireKernelBootstrapFile($basePath, $bootstrapPath)
234
    {
235
        if (null === $bootstrapPath) {
236
            return;
237
        }
238
239
        $possiblePaths = [
240
            sprintf('%s/%s', $basePath, $bootstrapPath),
241
            $bootstrapPath,
242
        ];
243
244
        foreach ($possiblePaths as $possiblePath) {
245
            if (file_exists($possiblePath)) {
246
                require_once $possiblePath;
247
248
                return;
249
            }
250
        }
251
252
        throw new \DomainException('Could not load bootstrap file.');
253
    }
254
}
255