Completed
Pull Request — master (#86)
by Márk
06:48
created

HttplugExtension::configureClients()   C

Complexity

Conditions 8
Paths 40

Size

Total Lines 31
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 23.625

Importance

Changes 8
Bugs 1 Features 6
Metric Value
c 8
b 1
f 6
dl 0
loc 31
ccs 6
cts 16
cp 0.375
rs 5.3846
cc 8
eloc 15
nc 40
nop 2
crap 23.625
1
<?php
2
3
namespace Http\HttplugBundle\DependencyInjection;
4
5
use Http\Client\Common\FlexibleHttpClient;
6
use Http\Client\Common\HttpMethodsClient;
7
use Http\Client\Common\Plugin\AuthenticationPlugin;
8
use Http\Client\Common\PluginClient;
9
use Http\HttplugBundle\ClientFactory\DummyClient;
10
use Http\Message\Authentication\BasicAuth;
11
use Http\Message\Authentication\Bearer;
12
use Http\Message\Authentication\Wsse;
13
use Symfony\Component\Config\FileLocator;
14
use Symfony\Component\DependencyInjection\ContainerBuilder;
15
use Symfony\Component\DependencyInjection\Definition;
16
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
17
use Symfony\Component\DependencyInjection\Reference;
18
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
19
20
/**
21
 * @author David Buchmann <[email protected]>
22
 * @author Tobias Nyholm <[email protected]>
23
 */
24
class HttplugExtension extends Extension
25
{
26
    /**
27
     * {@inheritdoc}
28
     */
29 3
    public function load(array $configs, ContainerBuilder $container)
30
    {
31 3
        $configuration = $this->getConfiguration($configs, $container);
32 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...
33
34 3
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
35
36 3
        $loader->load('services.xml');
37 3
        $loader->load('plugins.xml');
38
39 3
        $enabled = is_bool($config['toolbar']['enabled']) ? $config['toolbar']['enabled'] : $container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug');
40 3
        if ($enabled) {
41
            $loader->load('data-collector.xml');
42
            $config['_inject_collector_plugin'] = true;
43
44
            if (!empty($config['toolbar']['formatter'])) {
45
                $container->getDefinition('httplug.collector.message_journal')
46
                    ->replaceArgument(0, new Reference($config['toolbar']['formatter']));
47
            }
48
        }
49
50 3
        foreach ($config['classes'] as $service => $class) {
51 3
            if (!empty($class)) {
52 1
                $container->register(sprintf('httplug.%s.default', $service), $class);
53 1
            }
54 3
        }
55
56
        // Set main aliases
57 3
        foreach ($config['main_alias'] as $type => $id) {
58 3
            $container->setAlias(sprintf('httplug.%s', $type), $id);
59 3
        }
60
61 3
        $this->configurePlugins($container, $config['plugins']);
62 3
        $this->configureClients($container, $config);
63 3
    }
64
65
    /**
66
     * Configure client services.
67
     *
68
     * @param ContainerBuilder $container
69
     * @param array            $config
70
     */
71 3
    private function configureClients(ContainerBuilder $container, array $config)
72
    {
73
        // If we have a client named 'default'
74 3
        $first = isset($config['clients']['default']) ? 'default' : null;
75
76 3
        foreach ($config['clients'] as $name => $arguments) {
77
            if ($first === null) {
78
                // Save the name of the first configurated client.
79
                $first = $name;
80
            }
81
82
            if (isset($config['_inject_collector_plugin'])) {
83
                array_unshift($arguments['plugins'], 'httplug.collector.history_plugin');
84
            }
85
86
            $this->configureClient($container, $name, $arguments);
87 3
        }
88
89
        // If we have clients configured
90 3
        if ($first !== null) {
91
            if ($first !== 'default') {
92
                // Alias the first client to httplug.client.default
93
                $container->setAlias('httplug.client.default', 'httplug.client.'.$first);
94
            }
95 3
        } elseif (isset($config['_inject_collector_plugin'])) {
96
            // No client was configured. Make sure to inject history plugin to the auto discovery client.
97
            $container->register('httplug.client', PluginClient::class)
98
                ->addArgument(new Reference('httplug.client.default'))
99
                ->addArgument([new Reference('httplug.collector.history_plugin')]);
100
        }
101
    }
102
103
    /**
104
     * @param ContainerBuilder $container
105
     * @param array            $config
106
     */
107
    private function configurePlugins(ContainerBuilder $container, array $config)
108
    {
109
        if (!empty($config['authentication'])) {
110
            $this->configureAuthentication($container, $config['authentication']);
111
        }
112
        unset($config['authentication']);
113
114
        foreach ($config as $name => $pluginConfig) {
115
            $pluginId = 'httplug.plugin.'.$name;
116
117
            if ($pluginConfig['enabled']) {
118
                $def = $container->getDefinition($pluginId);
119
                $this->configurePluginByName($name, $def, $pluginConfig);
120
            } else {
121
                $container->removeDefinition($pluginId);
122
            }
123
        }
124
    }
125
126
    /**
127
     * @param string     $name
128
     * @param Definition $definition
129
     * @param array      $config
130
     */
131
    private function configurePluginByName($name, Definition $definition, array $config)
132
    {
133
        switch ($name) {
134
            case 'cache':
135
                $definition
136
                    ->replaceArgument(0, new Reference($config['cache_pool']))
137
                    ->replaceArgument(1, new Reference($config['stream_factory']))
138
                    ->replaceArgument(2, $config['config']);
139
                break;
140
            case 'cookie':
141
                $definition->replaceArgument(0, new Reference($config['cookie_jar']));
142
                break;
143
            case 'decoder':
144
                $definition->addArgument($config['use_content_encoding']);
145
                break;
146
            case 'history':
147
                $definition->replaceArgument(0, new Reference($config['journal']));
148
                break;
149
            case 'logger':
150
                $definition->replaceArgument(0, new Reference($config['logger']));
151
                if (!empty($config['formatter'])) {
152
                    $definition->replaceArgument(1, new Reference($config['formatter']));
153
                }
154
                break;
155
            case 'redirect':
156
                $definition
157
                    ->addArgument($config['preserve_header'])
158
                    ->addArgument($config['use_default_for_multiple']);
159
                break;
160
            case 'retry':
161
                $definition->addArgument($config['retry']);
162
                break;
163
            case 'stopwatch':
164
                $definition->replaceArgument(0, new Reference($config['stopwatch']));
165
                break;
166
        }
167
    }
168
169
    /**
170
     * @param ContainerBuilder $container
171
     * @param array            $config
172
     */
173
    private function configureAuthentication(ContainerBuilder $container, array $config)
174
    {
175
        foreach ($config as $name => $values) {
176
            $authServiceKey = sprintf('httplug.plugin.authentication.%s.auth', $name);
177
            switch ($values['type']) {
178
                case 'bearer':
179
                    $container->register($authServiceKey, Bearer::class)
180
                        ->addArgument($values['token']);
181
                    break;
182
                case 'basic':
183
                    $container->register($authServiceKey, BasicAuth::class)
184
                        ->addArgument($values['username'])
185
                        ->addArgument($values['password']);
186
                    break;
187
                case 'wsse':
188
                    $container->register($authServiceKey, Wsse::class)
189
                        ->addArgument($values['username'])
190
                        ->addArgument($values['password']);
191
                    break;
192
                case 'service':
193
                    $authServiceKey = $values['service'];
194
                    break;
195
                default:
196
                    throw new \LogicException(sprintf('Unknown authentication type: "%s"', $values['type']));
197
            }
198
199
            $container->register('httplug.plugin.authentication.'.$name, AuthenticationPlugin::class)
200
                ->addArgument(new Reference($authServiceKey));
201
        }
202
    }
203
204
    /**
205
     * @param ContainerBuilder $container
206
     * @param string           $name
207
     * @param array            $arguments
208
     */
209
    private function configureClient(ContainerBuilder $container, $name, array $arguments)
210
    {
211
        $serviceId = 'httplug.client.'.$name;
212
        $def = $container->register($serviceId, DummyClient::class);
213
214
        if (empty($arguments['plugins'])) {
215
            $def->setFactory([new Reference($arguments['factory']), 'createClient'])
216
                ->addArgument($arguments['config']);
217
        } else {
218
            $def->setFactory('Http\HttplugBundle\ClientFactory\PluginClientFactory::createPluginClient')
219
                ->addArgument(
220
                    array_map(
221
                        function ($id) {
222
                            return new Reference($id);
223
                        },
224
                        $arguments['plugins']
225
                    )
226
                )
227
                ->addArgument(new Reference($arguments['factory']))
228
                ->addArgument($arguments['config']);
229
        }
230
231
232
        /*
233
         * Decorate the client with clients from client-common
234
         */
235
236 View Code Duplication
        if ($arguments['flexible_client']) {
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...
237
            $container->register($serviceId.'.flexible', FlexibleHttpClient::class)
238
                ->addArgument(new Reference($serviceId.'.flexible.inner'))
239
                ->setPublic(false)
240
                ->setDecoratedService($serviceId);
241
        }
242
243 View Code Duplication
        if ($arguments['http_methods_client']) {
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...
244
            $container->register($serviceId.'.http_methods', HttpMethodsClient::class)
245
                ->setArguments([new Reference($serviceId.'.http_methods.inner'), new Reference('httplug.message_factory')])
246
                ->setPublic(false)
247
                ->setDecoratedService($serviceId);
248
        }
249
    }
250
}
251