Completed
Pull Request — master (#54)
by Tobias
08:14
created

HttplugExtension::load()   D

Complexity

Conditions 9
Paths 144

Size

Total Lines 44
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 10.1394

Importance

Changes 7
Bugs 1 Features 3
Metric Value
c 7
b 1
f 3
dl 0
loc 44
ccs 22
cts 29
cp 0.7586
rs 4.6666
cc 9
eloc 27
nc 144
nop 2
crap 10.1394
1
<?php
2
3
namespace Http\HttplugBundle\DependencyInjection;
4
5
use Http\Client\Plugin\AuthenticationPlugin;
6
use Http\Client\Plugin\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 3
        $loader->load('discovery.xml');
37
38 3
        $enabled = is_bool($config['toolbar']['enabled']) ? $config['toolbar']['enabled'] : $container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug');
39 3
        if ($enabled) {
40
            $loader->load('data-collector.xml');
41
            $config['_inject_collector_plugin'] = true;
42
43
            if (!empty($config['toolbar']['formatter'])) {
44
                $container->getDefinition('httplug.collector.message_journal')
45
                    ->replaceArgument(0, new Reference($config['toolbar']['formatter']));
46
            }
47
        }
48
49 3
        $useDiscovery = false;
50 3
        foreach ($config['classes'] as $service => $class) {
51 1
            if (!empty($class)) {
52 1
                $container->removeDefinition(sprintf('httplug.%s.default', $service));
53 1
                $container->register(sprintf('httplug.%s.default', $service), $class);
54 3
            } else {
55
                // we have to use discovery to find this class
56 3
                $useDiscovery = true;
57 3
            }
58 3
        }
59 3
60 3
        if ($useDiscovery) {
61 3
            $this->verifyDiscoveryInstalled($container);
62
        }
63
64
65
        foreach ($config['main_alias'] as $type => $id) {
66
            $container->setAlias(sprintf('httplug.%s', $type), $id);
67
        }
68
        $this->configurePlugins($container, $config['plugins']);
69 3
        $this->configureClients($container, $config);
70
    }
71 3
72 3
    /**
73
     * Configure client services.
74
     *
75
     * @param ContainerBuilder $container
76
     * @param array            $config
77
     */
78
    private function configureClients(ContainerBuilder $container, array $config)
79
    {
80
        $first = isset($config['clients']['default']) ? 'default' : null;
81
        foreach ($config['clients'] as $name => $arguments) {
82
            if ($first === null) {
83
                $first = $name;
84
            }
85
86
            if (isset($config['_inject_collector_plugin'])) {
87
                array_unshift($arguments['plugins'], 'httplug.collector.history_plugin');
88
            }
89
90
            $def = $container->register('httplug.client.'.$name, DummyClient::class);
91
92
            if (empty($arguments['plugins'])) {
93
                $def->setFactory([new Reference($arguments['factory']), 'createClient'])
94 3
                    ->addArgument($arguments['config']);
95
            } else {
96
                $def->setFactory('Http\HttplugBundle\ClientFactory\PluginClientFactory::createPluginClient')
97 3
                    ->addArgument(array_map(function ($id) {
98
                        return new Reference($id);
99
                    }, $arguments['plugins']))
100
                    ->addArgument(new Reference($arguments['factory']))
101
                    ->addArgument($arguments['config']);
102 3
            }
103
        }
104
105
        // If we have clients configured
106
        if ($first !== null) {
107
            if ($first !== 'default') {
108
                // Alias the first client to httplug.client.default
109
                $container->setAlias('httplug.client.default', 'httplug.client.'.$first);
110
            }
111
        } elseif (isset($config['_inject_collector_plugin'])) {
112
            // No client was configured. Make sure to inject history plugin to the auto discovery client.
113
            $container->register('httplug.client', PluginClient::class)
114
                ->addArgument(new Reference('httplug.client.default'))
115
                ->addArgument([new Reference('httplug.collector.history_plugin')]);
116
        }
117
    }
118
119
    /**
120
     * @param ContainerBuilder $container
121
     * @param array            $config
122
     */
123
    private function configurePlugins(ContainerBuilder $container, array $config)
124
    {
125
        if (!empty($config['authentication'])) {
126
            $this->configureAuthentication($container, $config['authentication']);
127
        }
128
        unset($config['authentication']);
129
130
        foreach ($config as $name => $pluginConfig) {
131
            $pluginId = 'httplug.plugin.'.$name;
132
            if ($pluginConfig['enabled']) {
133
                $def = $container->getDefinition($pluginId);
134
                $this->configurePluginByName($name, $def, $pluginConfig);
135
            } else {
136
                $container->removeDefinition($pluginId);
137
            }
138
        }
139
    }
140
141
    /**
142
     * @param string     $name
143
     * @param Definition $definition
144
     * @param array      $config
145
     */
146
    private function configurePluginByName($name, Definition $definition, array $config)
147
    {
148
        switch ($name) {
149
            case 'cache':
150
                $definition
151
                    ->replaceArgument(0, new Reference($config['cache_pool']))
152
                    ->replaceArgument(1, new Reference($config['stream_factory']))
153
                    ->replaceArgument(2, $config['config']);
154
                break;
155
            case 'cookie':
156
                $definition->replaceArgument(0, new Reference($config['cookie_jar']));
157
                break;
158
            case 'decoder':
159
                $definition->addArgument($config['use_content_encoding']);
160
                break;
161
            case 'history':
162
                $definition->replaceArgument(0, new Reference($config['journal']));
163
                break;
164
            case 'logger':
165
                $definition->replaceArgument(0, new Reference($config['logger']));
166
                if (!empty($config['formatter'])) {
167
                    $definition->replaceArgument(1, new Reference($config['formatter']));
168
                }
169
                break;
170
            case 'redirect':
171
                $definition
172
                    ->addArgument($config['preserve_header'])
173
                    ->addArgument($config['use_default_for_multiple']);
174
                break;
175
            case 'retry':
176
                $definition->addArgument($config['retry']);
177
                break;
178
            case 'stopwatch':
179
                $definition->replaceArgument(0, new Reference($config['stopwatch']));
180
                break;
181
        }
182
    }
183
184
    /**
185
     * @param ContainerBuilder $container
186
     * @param Definition       $parent
0 ignored issues
show
Bug introduced by
There is no parameter named $parent. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
187
     * @param array            $config
188
     */
189
    private function configureAuthentication(ContainerBuilder $container, array $config)
190
    {
191
        foreach ($config as $name => $values) {
192
            $authServiceKey = sprintf('httplug.plugin.authentication.%s.auth', $name);
193
            switch ($values['type']) {
194
                case 'bearer':
195
                    $container->register($authServiceKey, Bearer::class)
196
                        ->addArgument($values['token']);
197
                    break;
198
                case 'basic':
199
                    $container->register($authServiceKey, BasicAuth::class)
200
                        ->addArgument($values['username'])
201
                        ->addArgument($values['password']);
202
                    break;
203
                case 'wsse':
204
                    $container->register($authServiceKey, Wsse::class)
205
                        ->addArgument($values['username'])
206
                        ->addArgument($values['password']);
207
                    break;
208
                case 'service':
209
                    $authServiceKey = $values['service'];
210
                    break;
211
                default:
212
                    throw new \LogicException(sprintf('Unknown authentication type: "%s"', $values['type']));
213
            }
214
215
            $container->register('httplug.plugin.authentication.'.$name, AuthenticationPlugin::class)
216
                ->addArgument(new Reference($authServiceKey));
217
        }
218
    }
219
220
    /**
221
     * Verify that Puli is installed
222
     *
223
     * @param ContainerBuilder $container
224
     * @throws \Exception
225
     */
226
    private function verifyDiscoveryInstalled(ContainerBuilder $container)
227
    {
228
        $enabledBundles = $container->getParameter('kernel.bundles');
229
        if (!isset($enabledBundles['PuliSymfonyBundle'])) {
230
            throw new \Exception(
231
                'You need to install puli/symfony-bundle or add configuration at httplug.classes in order to use this bundle. Refer to http://some.doc'
232
            );
233
        }
234
235
        // .... OR
236
        if (defined('PULI_FACTORY')) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
237
            // Throw exception
238
        }
239
    }
240
}
241