Failed Conditions
Push — feature/improve ( 14cb7b )
by Yo
06:33
created

KernelSubExtension::initialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 2
1
<?php
2
namespace Yoanm\Behat3SymfonyExtension\ServiceContainer\SubExtension;
3
4
use Behat\Testwork\ServiceContainer\Exception\ProcessingException;
5
use Behat\Testwork\ServiceContainer\ExtensionManager;
6
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
7
use Symfony\Component\DependencyInjection\ContainerBuilder;
8
use Yoanm\Behat3SymfonyExtension\ServiceContainer\AbstractExtension;
9
use Yoanm\Behat3SymfonyExtension\ServiceContainer\Driver\Behat3SymfonyDriverFactory;
10
11
class KernelSubExtension extends AbstractExtension
12
{
13
    /**
14
     * @inheritDoc
15
     */
16 3
    public function getConfigKey()
17
    {
18 3
        return 'kernel';
19
    }
20
21
    /**
22
     * @inheritDoc
23
     */
24
    public function initialize(ExtensionManager $extensionManager)
25
    {
26
        $extensionManager->getExtension('mink')
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Behat\Testwork\ServiceContainer\Extension as the method registerDriverFactory() does only exist in the following implementations of said interface: Behat\MinkExtension\ServiceContainer\MinkExtension.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
27
            ->registerDriverFactory(new Behat3SymfonyDriverFactory());
28
    }
29
30
    /**
31
     * @inheritDoc
32
     */
33
    public function configure(ArrayNodeDefinition $builder)
34
    {
35
        $castToBool = function ($value) {
36
            $filtered = filter_var(
37
                $value,
38
                FILTER_VALIDATE_BOOLEAN,
39
                FILTER_NULL_ON_FAILURE
40
            );
41
42
            return (null === $filtered) ? (bool) $value : $filtered;
43
        };
44
        $builder
45
            ->addDefaultsIfNotSet()
46
            ->children()
47
                ->scalarNode('bootstrap')
48
                    ->defaultValue('app/autoload.php')
49
                ->end()
50
                ->scalarNode('path')
51
                    ->defaultValue('app/AppKernel.php')
52
                ->end()
53
                ->scalarNode('class')
54
                    ->defaultValue('AppKernel')
55
                ->end()
56
                ->scalarNode('env')
57
                    ->defaultValue('test')
58
                ->end()
59
                ->booleanNode('debug')
60
                    ->beforeNormalization()
61
                    ->always()
62
                        ->then($castToBool)
63
                    ->end()
64
                    ->defaultTrue()
65
                ->end()
66
                ->booleanNode('reboot')
67
                    ->info('If true symfony kernel will be rebooted after each scenario/example')
68
                    ->beforeNormalization()
69
                        ->always()
70
                        ->then($castToBool)
71
                    ->end()
72
                    ->defaultTrue()
73
                ->end()
74
            ->end();
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80 2
    public function load(ContainerBuilder $container, array $config)
81
    {
82 2
        $kernelConfig = $config[$this->getConfigKey()];
83 2
        $container->setParameter(
84 2
            $this->buildContainerId('kernel.reboot'),
85 2
            $kernelConfig['reboot']
86 2
        );
87 2
        $container->setParameter(
88 2
            $this->buildContainerId('kernel.bootstrap'),
89 2
            $kernelConfig['bootstrap']
90 2
        );
91 2
        $this->createService(
92 2
            $container,
93 2
            'kernel',
94 2
            $kernelConfig['class'],
95
            [
96 2
                $kernelConfig['env'],
97 2
                $kernelConfig['debug'],
98
            ]
99 2
        );
100 2
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105 3
    public function process(ContainerBuilder $container)
106
    {
107 3
        $bootstrapPath = $container->getParameter($this->buildContainerId('kernel.bootstrap'));
108 3
        if ($bootstrapPath) {
109 2
            $bootstrap = sprintf(
110 2
                '%s/%s',
111 2
                $container->getParameter('paths.base'),
112
                $bootstrapPath
113 2
            );
114 2
            if (file_exists($bootstrap)) {
115 1
                require_once($bootstrap);
116 1
            } else {
117 1
                throw new ProcessingException('Could not find bootstrap file !');
118
            }
119 1
        }
120 2
    }
121
}
122