Completed
Pull Request — master (#72)
by Márk
10:43
created

HttplugExtension::resolvePluginStatus()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
ccs 0
cts 0
cp 0
rs 9.4285
cc 2
eloc 6
nc 2
nop 2
crap 6
1
<?php
2
3
namespace Http\HttplugBundle\DependencyInjection;
4
5
use Http\Client\Common\Plugin\AuthenticationPlugin;
6
use Http\Client\Common\PluginClient;
7
use Http\HttplugBundle\ClientFactory\DummyClient;
8
use Http\Message\Authentication\BasicAuth;
9
use Http\Message\Authentication\Bearer;
10
use Http\Message\Authentication\Wsse;
11
use Symfony\Component\Config\FileLocator;
12
use Symfony\Component\DependencyInjection\ContainerBuilder;
13
use Symfony\Component\DependencyInjection\Definition;
14
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
15
use Symfony\Component\DependencyInjection\Reference;
16
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
17
18
/**
19
 * @author David Buchmann <[email protected]>
20
 * @author Tobias Nyholm <[email protected]>
21
 */
22
class HttplugExtension extends Extension
23
{
24
    /**
25
     * {@inheritdoc}
26
     */
27 3
    public function load(array $configs, ContainerBuilder $container)
28
    {
29 3
        $configuration = $this->getConfiguration($configs, $container);
30 3
        $config = $this->processConfiguration($configuration, $configs);
0 ignored issues
show
Documentation introduced by
$configuration is of type object|null, but the function expects a object<Symfony\Component...ConfigurationInterface>.

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...
31
32 3
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
33
34 3
        $loader->load('services.xml');
35 3
        $loader->load('plugins.xml');
36
37 3
        $enabled = is_bool($config['toolbar']['enabled']) ? $config['toolbar']['enabled'] : $container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug');
38 3
        if ($enabled) {
39
            $loader->load('data-collector.xml');
40
            $config['_inject_collector_plugin'] = true;
41
42
            if (!empty($config['toolbar']['formatter'])) {
43
                $container->getDefinition('httplug.collector.message_journal')
44
                    ->replaceArgument(0, new Reference($config['toolbar']['formatter']));
45
            }
46
        }
47
48 3
        foreach ($config['classes'] as $service => $class) {
49 3
            if (!empty($class)) {
50 1
                $container->register(sprintf('httplug.%s.default', $service), $class);
51 1
            }
52 3
        }
53
54 3
        foreach ($config['main_alias'] as $type => $id) {
55 3
            $container->setAlias(sprintf('httplug.%s', $type), $id);
56 3
        }
57
58 3
        $this->configurePlugins($container, $config['plugins']);
59 3
        $this->configureClients($container, $config);
60 3
    }
61
62
    /**
63
     * Configure client services.
64
     *
65
     * @param ContainerBuilder $container
66
     * @param array            $config
67
     */
68 3
    private function configureClients(ContainerBuilder $container, array $config)
69
    {
70 3
        $first = isset($config['clients']['default']) ? 'default' : null;
71 3
        foreach ($config['clients'] as $name => $arguments) {
72
            if ($first === null) {
73
                $first = $name;
74
            }
75
76
            if (isset($config['_inject_collector_plugin'])) {
77
                array_unshift($arguments['plugins'], 'httplug.collector.history_plugin');
78
            }
79
80
            $def = $container->register('httplug.client.'.$name, DummyClient::class);
81
82
            if (empty($arguments['plugins'])) {
83
                $def->setFactory([new Reference($arguments['factory']), 'createClient'])
84
                    ->addArgument($arguments['config']);
85
            } else {
86
                $def->setFactory('Http\HttplugBundle\ClientFactory\PluginClientFactory::createPluginClient')
87
                    ->addArgument(array_map(function ($id) {
88
                        return new Reference($id);
89
                    }, $arguments['plugins']))
90
                    ->addArgument(new Reference($arguments['factory']))
91
                    ->addArgument($arguments['config']);
92
            }
93 3
        }
94
95
        // If we have clients configured
96 3
        if ($first !== null) {
97
            if ($first !== 'default') {
98
                // Alias the first client to httplug.client.default
99
                $container->setAlias('httplug.client.default', 'httplug.client.'.$first);
100
            }
101 3
        } elseif (isset($config['_inject_collector_plugin'])) {
102
            // No client was configured. Make sure to inject history plugin to the auto discovery client.
103
            $container->register('httplug.client', PluginClient::class)
104
                ->addArgument(new Reference('httplug.client.default'))
105
                ->addArgument([new Reference('httplug.collector.history_plugin')]);
106
        }
107
    }
108
109
    /**
110
     * @param ContainerBuilder $container
111
     * @param array            $config
112
     */
113
    private function configurePlugins(ContainerBuilder $container, array $config)
114
    {
115
        if (!empty($config['authentication'])) {
116
            $this->configureAuthentication($container, $config['authentication']);
117
        }
118
        unset($config['authentication']);
119
120
        foreach ($config as $name => $pluginConfig) {
121
            $pluginId = 'httplug.plugin.'.$name;
122
123
            if ('auto' === $pluginConfig['enabled']) {
124
                $pluginConfig['enabled'] = $this->resolvePluginStatus($name, $pluginConfig);
125
            }
126
127
            if ($pluginConfig['enabled']) {
128
                $def = $container->getDefinition($pluginId);
129
                $this->configurePluginByName($name, $def, $pluginConfig);
130
            } else {
131
                $container->removeDefinition($pluginId);
132
            }
133
        }
134
    }
135
136
    /**
137
     * @param string     $name
138
     * @param Definition $definition
139
     * @param array      $config
140
     */
141
    private function configurePluginByName($name, Definition $definition, array $config)
142
    {
143
        switch ($name) {
144 View Code Duplication
            case 'cache':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
145
                if (class_exists('Http\Client\Common\Plugin\CachePlugin')) {
146
                    $definition->setClass('Http\Client\Common\Plugin\CachePlugin');
147
                }
148
                $definition
149
                    ->replaceArgument(0, new Reference($config['cache_pool']))
150
                    ->replaceArgument(1, new Reference($config['stream_factory']))
151
                    ->replaceArgument(2, $config['config']);
152
                break;
153
            case 'cookie':
154
                $definition->replaceArgument(0, new Reference($config['cookie_jar']));
155
                break;
156
            case 'decoder':
157
                $definition->addArgument($config['use_content_encoding']);
158
                break;
159
            case 'history':
160
                $definition->replaceArgument(0, new Reference($config['journal']));
161
                break;
162 View Code Duplication
            case 'logger':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
163
                if (class_exists('Http\Client\Common\Plugin\LoggerPlugin')) {
164
                    $definition->setClass('Http\Client\Common\Plugin\LoggerPlugin');
165
                }
166
                $definition->replaceArgument(0, new Reference($config['logger']));
167
                if (!empty($config['formatter'])) {
168
                    $definition->replaceArgument(1, new Reference($config['formatter']));
169
                }
170
                break;
171
            case 'redirect':
172
                $definition
173
                    ->addArgument($config['preserve_header'])
174
                    ->addArgument($config['use_default_for_multiple']);
175
                break;
176
            case 'retry':
177
                $definition->addArgument($config['retry']);
178
                break;
179
            case 'stopwatch':
180
                if (class_exists('Http\Client\Common\Plugin\StopwatchPlugin')) {
181
                    $definition->setClass('Http\Client\Common\Plugin\StopwatchPlugin');
182
                }
183
                $definition->replaceArgument(0, new Reference($config['stopwatch']));
184
                break;
185
        }
186
    }
187
188
    /**
189
     * @param ContainerBuilder $container
190
     * @param array            $config
191
     */
192
    private function configureAuthentication(ContainerBuilder $container, array $config)
193
    {
194
        foreach ($config as $name => $values) {
195
            $authServiceKey = sprintf('httplug.plugin.authentication.%s.auth', $name);
196
            switch ($values['type']) {
197
                case 'bearer':
198
                    $container->register($authServiceKey, Bearer::class)
199
                        ->addArgument($values['token']);
200
                    break;
201
                case 'basic':
202
                    $container->register($authServiceKey, BasicAuth::class)
203
                        ->addArgument($values['username'])
204
                        ->addArgument($values['password']);
205
                    break;
206
                case 'wsse':
207
                    $container->register($authServiceKey, Wsse::class)
208
                        ->addArgument($values['username'])
209
                        ->addArgument($values['password']);
210
                    break;
211
                case 'service':
212
                    $authServiceKey = $values['service'];
213
                    break;
214
                default:
215
                    throw new \LogicException(sprintf('Unknown authentication type: "%s"', $values['type']));
216
            }
217
218
            $container->register('httplug.plugin.authentication.'.$name, AuthenticationPlugin::class)
219
                ->addArgument(new Reference($authServiceKey));
220
        }
221
    }
222
223
    /**
224
     * Resolve the plugin enabled status if it is 'auto'.
225
     *
226
     * Returns false if plugin has no auto status allowed.
227
     *
228
     * @param string $name
229
     * @param array  $pluginConfig
230
     *
231
     * @return bool
232
     */
233
    private function resolvePluginStatus($name, array $pluginConfig)
0 ignored issues
show
Unused Code introduced by
The parameter $pluginConfig is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
234
    {
235
        switch ($name) {
236
            case 'logger':
237
                return class_exists('Http\Client\Common\Plugin\LoggerPlugin');
238
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
239
        }
240
241
        return false;
242
    }
243
}
244