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