Failed Conditions
Push — feature/extension ( 976595...4da90f )
by Yo
04:21 queued 02:04
created

Behat3SymfonyExtension::process()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 0
cts 17
cp 0
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 12
nc 3
nop 1
crap 12
1
<?php
2
namespace Yoanm\Behat3SymfonyExtension\ServiceContainer;
3
4
use Behat\Testwork\ServiceContainer\Exception\ProcessingException;
5
use Behat\Testwork\ServiceContainer\Extension;
6
use Behat\Testwork\ServiceContainer\ExtensionManager;
7
use Monolog\Logger;
8
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
9
use Symfony\Component\DependencyInjection\ContainerBuilder;
10
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
11
use Yoanm\Behat3SymfonyExtension\ServiceContainer\Driver\Behat3SymfonyDriverFactory;
12
13
class Behat3SymfonyExtension implements Extension
14
{
15
    const BASE_CONTAINER_PARAMETER = 'behat3_symfony_extension';
16
17
    /**
18
     * {@inheritdoc}
19
     */
20
    public function getConfigKey()
21
    {
22
        return 'behat3_symfony';
23
    }
24
25
    /**
26
     * {@inheritdoc}
27
     */
28
    public function initialize(ExtensionManager $extensionManager)
29
    {
30
        $extensionManager->getExtension('mink')
1 ignored issue
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...
31
            ->registerDriverFactory(new Behat3SymfonyDriverFactory());
32
    }
33
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function configure(ArrayNodeDefinition $builder)
38
    {
39
        $castToBool = function ($value) {
40
            $filtered = filter_var(
41
                $value,
42
                FILTER_VALIDATE_BOOLEAN,
43
                FILTER_NULL_ON_FAILURE
44
            );
45
46
            return (null === $filtered) ? (bool) $value : $filtered;
47
        };
48
49
        $builder
50
            ->addDefaultsIfNotSet()
51
                ->children()
52
                    ->arrayNode('logger')
53
                        ->addDefaultsIfNotSet()
54
                        ->children()
55
                            ->scalarNode('path')
56
                                ->defaultValue('var/log/behat.log')
57
                            ->end()
58
                            ->scalarNode('level')
59
                                ->beforeNormalization()
60
                                ->always()
61
                                ->then(function ($value) {
62
                                    return Logger::toMonologLevel($value);
63
                                })
64
                                ->end()
65
                                ->defaultValue(Logger::DEBUG)
66
                            ->end()
67
                        ->end()
68
                    ->end()
69
                    ->arrayNode('kernel')
70
                        ->addDefaultsIfNotSet()
71
                        ->children()
72
                            ->scalarNode('bootstrap')
73
                                ->defaultValue('app/autoload.php')
74
                            ->end()
75
                            ->scalarNode('path')
76
                                ->defaultValue('app/AppKernel.php')
77
                            ->end()
78
                            ->scalarNode('class')
79
                                ->defaultValue('AppKernel')
80
                            ->end()
81
                            ->scalarNode('env')
82
                                ->defaultValue('test')
83
                            ->end()
84
                            ->booleanNode('debug')
85
                                ->beforeNormalization()
86
                                ->always()
87
                                    ->then($castToBool)
88
                                ->end()
89
                                ->defaultTrue()
90
                            ->end()
91
                            ->booleanNode('reboot')
92
                                ->info('If true symfony kernel will be rebooted after each scenario/example')
93
                                ->beforeNormalization()
94
                                    ->always()
95
                                    ->then($castToBool)
96
                                ->end()
97
                                ->defaultTrue()
98
                            ->end()
99
                        ->end()
100
                    ->end()
101
                ->end()
102
            ->end();
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108
    public function load(ContainerBuilder $container, array $config)
109
    {
110
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
111
112
        // load config files
113
        $loader->load('kernel.xml');
114
        $loader->load('logger.xml');
115
        $loader->load('initializer.xml');
116
        $loader->load('handler.xml');
117
        $loader->load('subscriber.xml');
118
119
        if (true === $config['kernel']['reboot']) {
120
            $loader->load('auto_reboot_kernel.xml');
121
        }
122
123
        foreach ($config['kernel'] as $configKey => $configValue) {
124
            $container->setParameter(
125
                sprintf(
126
                    '%s.kernel.%s',
127
                    self::BASE_CONTAINER_PARAMETER,
128
                    $configKey
129
                ),
130
                $configValue
131
            );
132
        }
133
        foreach ($config['logger'] as $configKey => $configValue) {
134
            $container->setParameter(
135
                sprintf(
136
                    '%s.logger.%s',
137
                    self::BASE_CONTAINER_PARAMETER,
138
                    $configKey
139
                ),
140
                $configValue
141
            );
142
        }
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     */
148
    public function process(ContainerBuilder $container)
149
    {
150
        $bootstrapPath = $container->getParameter('behat3_symfony_extension.kernel.bootstrap');
151
        if ($bootstrapPath) {
152
            $bootstrap = sprintf(
153
                '%s%s%s',
154
                $container->getParameter('paths.base'),
155
                PATH_SEPARATOR,
156
                $bootstrapPath
157
            );
158
            if (file_exists($bootstrap)) {
159
                require_once($bootstrap);
160
            } else {
161
                throw new ProcessingException('Could not find bootstrap file !');
162
            }
163
        }
164
    }
165
}
166