Completed
Pull Request — master (#7)
by Kamil
03:45
created

SymfonyExtension   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 266
Duplicated Lines 10.15 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 9
dl 27
loc 266
rs 10
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getConfigKey() 0 4 1
A initialize() 0 5 1
A configure() 0 15 1
A load() 0 13 1
A process() 0 3 1
A loadKernel() 0 13 1
A loadKernelContainer() 10 10 1
A loadDriverKernel() 0 4 1
A loadSharedKernel() 0 4 1
A loadSharedKernelContainer() 10 10 1
A loadKernelRebooter() 7 7 1
A declareSymfonyContainers() 0 14 2
A initializeCrossContainerProcessor() 0 8 2
A registerSymfonyDriverFactory() 0 13 2
A getKernelFile() 0 15 3
A requireKernelBootstrapFile() 0 21 4

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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\CrossContainerExtension\CrossContainerProcessor;
19
use FriendsOfBehat\CrossContainerExtension\KernelBasedContainerAccessor;
20
use FriendsOfBehat\CrossContainerExtension\ServiceContainer\CrossContainerExtension;
21
use FriendsOfBehat\SymfonyExtension\Driver\Factory\SymfonyDriverFactory;
22
use FriendsOfBehat\SymfonyExtension\Listener\KernelRebooter;
23
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
24
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
25
use Symfony\Component\DependencyInjection\Container;
26
use Symfony\Component\DependencyInjection\ContainerBuilder;
27
use Symfony\Component\DependencyInjection\Definition;
28
use Symfony\Component\DependencyInjection\Reference;
29
30
final class SymfonyExtension implements Extension
31
{
32
    /**
33
     * Kernel used inside Behat contexts or to create services injected to them.
34
     * Container is built before every scenario.
35
     */
36
    const KERNEL_ID = 'sylius_symfony_extension.kernel';
37
38
    /**
39
     * The current container used in scenario contexts.
40
     * To be used as a factory for current injected application services.
41
     */
42
    const KERNEL_CONTAINER_ID = 'sylius_symfony_extension.kernel.container';
43
44
    /**
45
     * Kernel used by Symfony2 driver to isolate web container from contexts' container.
46
     * Container is built before every request.
47
     */
48
    const DRIVER_KERNEL_ID = 'sylius_symfony_extension.driver_kernel';
49
50
    /**
51
     * Kernel that should be used by extensions only.
52
     * Container is built only once at the first use.
53
     */
54
    const SHARED_KERNEL_ID = 'sylius_symfony_extension.shared_kernel';
55
56
    /**
57
     * The only container built by shared kernel.
58
     * To be used as a factory for shared injected application services.
59
     */
60
    const SHARED_KERNEL_CONTAINER_ID = 'sylius_symfony_extension.shared_kernel.container';
61
62
    /**
63
     * @var CrossContainerProcessor|null
64
     */
65
    private $crossContainerProcessor;
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function getConfigKey()
71
    {
72
        return 'fob_symfony';
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78
    public function initialize(ExtensionManager $extensionManager)
79
    {
80
        $this->registerSymfonyDriverFactory($extensionManager);
81
        $this->initializeCrossContainerProcessor($extensionManager);
82
    }
83
84
    /**
85
     * {@inheritdoc}
86
     */
87
    public function configure(ArrayNodeDefinition $builder)
88
    {
89
        $builder
90
            ->addDefaultsIfNotSet()
91
                ->children()
92
                    ->arrayNode('kernel')
93
                        ->addDefaultsIfNotSet()
94
                        ->children()
95
                            ->scalarNode('bootstrap')->defaultValue('app/autoload.php')->end()
96
                            ->scalarNode('path')->defaultValue('app/AppKernel.php')->end()
97
                            ->scalarNode('class')->defaultValue('AppKernel')->end()
98
                            ->scalarNode('env')->defaultValue('test')->end()
99
                            ->booleanNode('debug')->defaultTrue()->end()
100
        ;
101
    }
102
103
    /**
104
     * {@inheritdoc}
105
     */
106
    public function load(ContainerBuilder $container, array $config)
107
    {
108
        $this->loadKernel($container, $config['kernel']);
109
        $this->loadKernelContainer($container);
110
111
        $this->loadDriverKernel($container);
112
113
        $this->loadSharedKernel($container);
114
        $this->loadSharedKernelContainer($container);
115
116
        $this->loadKernelRebooter($container);
117
        $this->declareSymfonyContainers($container);
118
    }
119
120
    /**
121
     * {@inheritdoc}
122
     */
123
    public function process(ContainerBuilder $container)
124
    {
125
    }
126
127
    /**
128
     * @param ContainerBuilder $container
129
     */
130
    private function loadKernel(ContainerBuilder $container, array $config)
131
    {
132
        $definition = new Definition($config['class'], array(
133
            $config['env'],
134
            $config['debug'],
135
        ));
136
        $definition->addMethodCall('boot');
137
        $definition->setFile($this->getKernelFile($container->getParameter('paths.base'), $config['path']));
138
139
        $container->setDefinition(self::KERNEL_ID, $definition);
140
141
        $this->requireKernelBootstrapFile($container->getParameter('paths.base'), $config['bootstrap']);
142
    }
143
144
    /**
145
     * @param ContainerBuilder $container
146
     */
147 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...
148
    {
149
        $containerDefinition = new Definition(Container::class);
150
        $containerDefinition->setFactory([
151
            new Reference(self::KERNEL_ID),
152
            'getContainer',
153
        ]);
154
155
        $container->setDefinition(self::KERNEL_CONTAINER_ID, $containerDefinition);
156
    }
157
158
    /**
159
     * @param ContainerBuilder $container
160
     */
161
    private function loadDriverKernel(ContainerBuilder $container)
162
    {
163
        $container->setDefinition(self::DRIVER_KERNEL_ID, $container->findDefinition(self::KERNEL_ID));
164
    }
165
166
    /**
167
     * @param ContainerBuilder $container
168
     */
169
    private function loadSharedKernel(ContainerBuilder $container)
170
    {
171
        $container->setDefinition(self::SHARED_KERNEL_ID, $container->findDefinition(self::KERNEL_ID));
172
    }
173
174
    /**
175
     * @param ContainerBuilder $container
176
     */
177 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...
178
    {
179
        $containerDefinition = new Definition(Container::class);
180
        $containerDefinition->setFactory([
181
            new Reference(self::SHARED_KERNEL_ID),
182
            'getContainer',
183
        ]);
184
185
        $container->setDefinition(self::SHARED_KERNEL_CONTAINER_ID, $containerDefinition);
186
    }
187
188
    /**
189
     * @param ContainerBuilder $container
190
     */
191 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...
192
    {
193
        $definition = new Definition(KernelRebooter::class, [new Reference(self::KERNEL_ID)]);
194
        $definition->addTag(EventDispatcherExtension::SUBSCRIBER_TAG);
195
196
        $container->setDefinition(self::KERNEL_ID . '.rebooter', $definition);
197
    }
198
199
    /**
200
     * @param ContainerBuilder $container
201
     */
202
    private function declareSymfonyContainers(ContainerBuilder $container)
203
    {
204
        if (null !== $this->crossContainerProcessor) {
205
            $this->crossContainerProcessor->addContainerAccessor(
206
                'symfony',
207
                new KernelBasedContainerAccessor($container->get(self::KERNEL_ID))
0 ignored issues
show
Documentation introduced by
$container->get(self::KERNEL_ID) is of type object|null, but the function expects a object<Symfony\Component...Kernel\KernelInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
208
            );
209
210
            $this->crossContainerProcessor->addContainerAccessor(
211
                'symfony',
212
                new KernelBasedContainerAccessor($container->get(self::SHARED_KERNEL_ID))
0 ignored issues
show
Documentation introduced by
$container->get(self::SHARED_KERNEL_ID) is of type object|null, but the function expects a object<Symfony\Component...Kernel\KernelInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
213
            );
214
        }
215
    }
216
217
    /**
218
     * @param ExtensionManager $extensionManager
219
     */
220
    private function initializeCrossContainerProcessor(ExtensionManager $extensionManager)
221
    {
222
        /** @var CrossContainerExtension $extension */
223
        $extension = $extensionManager->getExtension('fob_cross_container');
224
        if (null !== $extension) {
225
            $this->crossContainerProcessor = $extension->getCrossContainerProcessor();
226
        }
227
    }
228
229
    /**
230
     * @param ExtensionManager $extensionManager
231
     */
232
    private function registerSymfonyDriverFactory(ExtensionManager $extensionManager)
233
    {
234
        /** @var MinkExtension $minkExtension */
235
        $minkExtension = $extensionManager->getExtension('mink');
236
        if (null === $minkExtension) {
237
            return;
238
        }
239
240
        $minkExtension->registerDriverFactory(new SymfonyDriverFactory(
241
            'symfony',
242
            new Reference(self::DRIVER_KERNEL_ID)
243
        ));
244
    }
245
246
    /**
247
     * @param string $basePath
248
     * @param string $kernelPath
249
     *
250
     * @return string|null
251
     */
252
    private function getKernelFile($basePath, $kernelPath)
253
    {
254
        $possibleFiles = [
255
            sprintf('%s/%s', $basePath, $kernelPath),
256
            $kernelPath,
257
        ];
258
259
        foreach ($possibleFiles as $possibleFile) {
260
            if (file_exists($possibleFile)) {
261
                return $possibleFile;
262
            }
263
        }
264
265
        return null;
266
    }
267
268
    /**
269
     * @param string $basePath
270
     * @param string|null $bootstrapPath
271
     *
272
     * @throws \DomainException
273
     */
274
    private function requireKernelBootstrapFile($basePath, $bootstrapPath)
275
    {
276
        if (null === $bootstrapPath) {
277
            return;
278
        }
279
280
        $possiblePaths = [
281
            sprintf('%s/%s', $basePath, $bootstrapPath),
282
            $bootstrapPath,
283
        ];
284
285
        foreach ($possiblePaths as $possiblePath) {
286
            if (file_exists($possiblePath)) {
287
                require_once $possiblePath;
288
289
                return;
290
            }
291
        }
292
293
        throw new \DomainException('Could not load bootstrap file.');
294
    }
295
}
296