Completed
Pull Request — master (#162)
by Tobias
05:23
created

HttplugExtension   C

Complexity

Total Complexity 65

Size/Duplication

Total Lines 532
Duplicated Lines 10.15 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 87.8%

Importance

Changes 0
Metric Value
wmc 65
lcom 1
cbo 8
dl 54
loc 532
ccs 108
cts 123
cp 0.878
rs 5.7894
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
B load() 0 45 6
B configureClients() 0 30 6
A configureSharedPlugins() 0 18 4
C configurePluginByName() 0 62 15
B configureAuthentication() 0 37 6
C configureClient() 20 74 9
A createUri() 0 9 1
B configureAutoDiscoveryClients() 34 54 7
B registerAutoDiscoverableClient() 0 32 3
A getConfiguration() 0 4 1
A configurePlugin() 0 13 2
A decoratePluginWithProfilePlugin() 0 12 1
A configureStackPlugin() 0 13 2
A configureAutoDiscoveryFactory() 0 18 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like HttplugExtension often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use HttplugExtension, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Http\HttplugBundle\DependencyInjection;
4
5
use Http\Client\Common\BatchClient;
6
use Http\Client\Common\FlexibleHttpClient;
7
use Http\Client\Common\HttpMethodsClient;
8
use Http\Client\Common\Plugin\AuthenticationPlugin;
9
use Http\Discovery\HttpAsyncClientDiscovery;
10
use Http\Discovery\HttpClientDiscovery;
11
use Http\HttplugBundle\ClientFactory\DummyClient;
12
use Http\HttplugBundle\ClientFactory\PluginClientFactory;
13
use Http\HttplugBundle\Collector\ProfileClientFactory;
14
use Http\HttplugBundle\Collector\ProfilePlugin;
15
use Http\Message\Authentication\BasicAuth;
16
use Http\Message\Authentication\Bearer;
17
use Http\Message\Authentication\Wsse;
18
use Psr\Http\Message\UriInterface;
19
use Symfony\Component\Config\FileLocator;
20
use Symfony\Component\DependencyInjection\ChildDefinition;
21
use Symfony\Component\DependencyInjection\ContainerBuilder;
22
use Symfony\Component\DependencyInjection\ContainerInterface;
23
use Symfony\Component\DependencyInjection\Definition;
24
use Symfony\Component\DependencyInjection\DefinitionDecorator;
25
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
26
use Symfony\Component\DependencyInjection\Reference;
27
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
28
29
/**
30
 * @author David Buchmann <[email protected]>
31
 * @author Tobias Nyholm <[email protected]>
32
 */
33
class HttplugExtension extends Extension
34
{
35
    /**
36
     * {@inheritdoc}
37
     */
38 10
    public function load(array $configs, ContainerBuilder $container)
39
    {
40 10
        $configuration = $this->getConfiguration($configs, $container);
41 10
        $config = $this->processConfiguration($configuration, $configs);
1 ignored issue
show
Bug introduced by
It seems like $configuration defined by $this->getConfiguration($configs, $container) on line 40 can be null; however, Symfony\Component\Depend...:processConfiguration() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
42
43 10
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
44
45 10
        $loader->load('services.xml');
46 10
        $loader->load('plugins.xml');
47
48
        // Register default services
49 10
        foreach ($config['classes'] as $service => $class) {
50 10
            if (!empty($class)) {
51 1
                $container->register(sprintf('httplug.%s.default', $service), $class);
52 1
            }
53 10
        }
54
55
        // Set main aliases
56 10
        foreach ($config['main_alias'] as $type => $id) {
57 10
            $container->setAlias(sprintf('httplug.%s', $type), $id);
58 10
        }
59
60
        // Configure toolbar
61 10
        $profilingEnabled = $this->isConfigEnabled($container, $config['profiling']);
62 10
        if ($profilingEnabled) {
63 7
            $loader->load('data-collector.xml');
64
65 7
            if (!empty($config['profiling']['formatter'])) {
66
                // Add custom formatter
67
                $container
68 1
                    ->getDefinition('httplug.collector.formatter')
69 1
                    ->replaceArgument(0, new Reference($config['profiling']['formatter']))
70
                ;
71 1
            }
72
73
            $container
74 7
                ->getDefinition('httplug.formatter.full_http_message')
75 7
                ->addArgument($config['profiling']['captured_body_length'])
76
            ;
77 7
        }
78
79 10
        $this->configureClients($container, $config, $profilingEnabled);
80 10
        $this->configureSharedPlugins($container, $config['plugins']); // must be after clients, as clients.X.plugins might use plugins as templates that will be removed
81 10
        $this->configureAutoDiscoveryClients($container, $config);
82 10
    }
83
84
    /**
85
     * Configure client services.
86
     *
87
     * @param ContainerBuilder $container
88
     * @param array            $config
89
     * @param bool             $profiling
90
     */
91 10
    private function configureClients(ContainerBuilder $container, array $config, $profiling)
92
    {
93 10
        $first = null;
94 10
        $clients = [];
95
96 10
        foreach ($config['clients'] as $name => $arguments) {
97 6
            if ($first === null) {
98
                // Save the name of the first configured client.
99 6
                $first = $name;
100 6
            }
101
102 6
            $this->configureClient($container, $name, $arguments, $this->isConfigEnabled($container, $config['profiling']));
103 6
            $clients[] = $name;
104 10
        }
105
106
        // If we have clients configured
107 10
        if ($first !== null) {
108
            // If we do not have a client named 'default'
109 6
            if (!isset($config['clients']['default'])) {
110
                // Alias the first client to httplug.client.default
111 6
                $container->setAlias('httplug.client.default', 'httplug.client.'.$first);
112 6
            }
113 6
        }
114
115 10
        if ($profiling) {
116 7
            $container->getDefinition('httplug.collector.collector')
117 7
                ->setArguments([$clients])
118
            ;
119 7
        }
120 10
    }
121
122
    /**
123
     * @param ContainerBuilder $container
124
     * @param array            $config
125
     */
126 10
    private function configureSharedPlugins(ContainerBuilder $container, array $config)
127
    {
128 10
        if (!empty($config['authentication'])) {
129
            $this->configureAuthentication($container, $config['authentication']);
130
        }
131 10
        unset($config['authentication']);
132
133 10
        foreach ($config as $name => $pluginConfig) {
134 10
            $pluginId = 'httplug.plugin.'.$name;
135
136 10
            if ($this->isConfigEnabled($container, $pluginConfig)) {
137 10
                $def = $container->getDefinition($pluginId);
138 10
                $this->configurePluginByName($name, $def, $pluginConfig, $container, $pluginId);
139 10
            } else {
140 10
                $container->removeDefinition($pluginId);
141
            }
142 10
        }
143 10
    }
144
145
    /**
146
     * @param string           $name
147
     * @param Definition       $definition
148
     * @param array            $config
149
     * @param ContainerBuilder $container  In case we need to add additional services for this plugin
150
     * @param string           $serviceId  Service id of the plugin, in case we need to add additional services for this plugin.
151
     */
152 10
    private function configurePluginByName($name, Definition $definition, array $config, ContainerInterface $container, $serviceId)
153
    {
154
        switch ($name) {
155 10
            case 'cache':
156
                $definition
157
                    ->replaceArgument(0, new Reference($config['cache_pool']))
158
                    ->replaceArgument(1, new Reference($config['stream_factory']))
159
                    ->replaceArgument(2, $config['config']);
160
                break;
161 10
            case 'cookie':
162
                $definition->replaceArgument(0, new Reference($config['cookie_jar']));
163
                break;
164 10
            case 'decoder':
165 10
                $definition->addArgument([
166 10
                    'use_content_encoding' => $config['use_content_encoding'],
167 10
                ]);
168 10
                break;
169 10
            case 'history':
170
                $definition->replaceArgument(0, new Reference($config['journal']));
171
                break;
172 10
            case 'logger':
173 10
                $definition->replaceArgument(0, new Reference($config['logger']));
174 10
                if (!empty($config['formatter'])) {
175
                    $definition->replaceArgument(1, new Reference($config['formatter']));
176
                }
177 10
                break;
178 10
            case 'redirect':
179 10
                $definition->addArgument([
180 10
                    'preserve_header' => $config['preserve_header'],
181 10
                    'use_default_for_multiple' => $config['use_default_for_multiple'],
182 10
                ]);
183 10
                break;
184 10
            case 'retry':
185 10
                $definition->addArgument([
186 10
                    'retries' => $config['retry'],
187 10
                ]);
188 10
                break;
189 10
            case 'stopwatch':
190 10
                $definition->replaceArgument(0, new Reference($config['stopwatch']));
191 10
                break;
192
193
            /* client specific plugins */
194
195 3
            case 'add_host':
196 3
                $uriService = $serviceId.'.host_uri';
197 3
                $this->createUri($container, $uriService, $config['host']);
0 ignored issues
show
Compatibility introduced by
$container of type object<Symfony\Component...ion\ContainerInterface> is not a sub-type of object<Symfony\Component...ction\ContainerBuilder>. It seems like you assume a concrete implementation of the interface Symfony\Component\Depend...tion\ContainerInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
198 3
                $definition->replaceArgument(0, new Reference($uriService));
199 3
                $definition->replaceArgument(1, [
200 3
                    'replace' => $config['replace'],
201 3
                ]);
202 3
                break;
203 1
            case 'header_append':
204 1
            case 'header_defaults':
205 1
            case 'header_set':
206 1
            case 'header_remove':
207 1
                $definition->replaceArgument(0, $config['headers']);
208 1
                break;
209
210
            default:
211
                throw new \InvalidArgumentException(sprintf('Internal exception: Plugin %s is not handled', $name));
212
        }
213 10
    }
214
215
    /**
216
     * @param ContainerBuilder $container
217
     * @param array            $config
218
     *
219
     * @return array List of service ids for the authentication plugins.
220
     */
221 3
    private function configureAuthentication(ContainerBuilder $container, array $config, $servicePrefix = 'httplug.plugin.authentication')
222
    {
223 3
        $pluginServices = [];
224
225 3
        foreach ($config as $name => $values) {
226 3
            $authServiceKey = sprintf($servicePrefix.'.%s.auth', $name);
227 3
            switch ($values['type']) {
228 3
                case 'bearer':
229
                    $container->register($authServiceKey, Bearer::class)
230
                        ->addArgument($values['token']);
231
                    break;
232
                case 'basic':
233
                    $container->register($authServiceKey, BasicAuth::class)
234
                        ->addArgument($values['username'])
235
                        ->addArgument($values['password']);
236
                    break;
237
                case 'wsse':
238
                    $container->register($authServiceKey, Wsse::class)
239
                        ->addArgument($values['username'])
240
                        ->addArgument($values['password']);
241
                    break;
242
                case 'service':
243
                    $authServiceKey = $values['service'];
244
                    break;
245
                default:
246
                    throw new \LogicException(sprintf('Unknown authentication type: "%s"', $values['type']));
247
            }
248
249
            $pluginServiceKey = $servicePrefix.'.'.$name;
250
            $container->register($pluginServiceKey, AuthenticationPlugin::class)
251
                ->addArgument(new Reference($authServiceKey))
252
            ;
253
            $pluginServices[] = $pluginServiceKey;
254
        }
255
256
        return $pluginServices;
257
    }
258
259
    /**
260
     * @param ContainerBuilder $container
261
     * @param string           $clientName
262
     * @param array            $arguments
263
     * @param bool             $profiling
264
     */
265
    private function configureClient(ContainerBuilder $container, $clientName, array $arguments, $profiling)
266
    {
267
        $serviceId = 'httplug.client.'.$clientName;
268
269
        $plugins = [];
270
        foreach ($arguments['plugins'] as $plugin) {
271
            list($pluginName, $pluginConfig) = each($plugin);
272
            if ('reference' === $pluginName) {
273
                $plugins[] = $pluginConfig['id'];
274
            } elseif ('authentication' === $pluginName) {
275
                $plugins = array_merge($plugins, $this->configureAuthentication($container, $pluginConfig, $serviceId.'.authentication'));
276
            } else {
277
                $plugins[] = $this->configurePlugin($container, $serviceId, $pluginName, $pluginConfig);
278
            }
279
        }
280
281
        $pluginClientOptions = [];
282
        if ($profiling) {
283
            //Decorate each plugin with a ProfilePlugin instance.
284
            foreach ($plugins as $pluginServiceId) {
285
                $this->decoratePluginWithProfilePlugin($container, $pluginServiceId);
286
            }
287
288
            // To profile the requests, add a StackPlugin as first plugin in the chain.
289
            $stackPluginId = $this->configureStackPlugin($container, $clientName, $serviceId);
290
            array_unshift($plugins, $stackPluginId);
291
        }
292
293
        $container
294
            ->register($serviceId, DummyClient::class)
295
            ->setFactory([PluginClientFactory::class, 'createPluginClient'])
296
            ->addArgument(
297
                array_map(
298
                    function ($id) {
299
                        return new Reference($id);
300
                    },
301
                    $plugins
302
                )
303
            )
304
            ->addArgument(new Reference($arguments['factory']))
305
            ->addArgument($arguments['config'])
306
            ->addArgument($pluginClientOptions)
307
        ;
308
309
        /*
310
         * Decorate the client with clients from client-common
311
         */
312 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...
313
            $container
314
                ->register($serviceId.'.flexible', FlexibleHttpClient::class)
315
                ->addArgument(new Reference($serviceId.'.flexible.inner'))
316
                ->setPublic(false)
317
                ->setDecoratedService($serviceId)
318
            ;
319
        }
320
321 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...
322
            $container
323
                ->register($serviceId.'.http_methods', HttpMethodsClient::class)
324
                ->setArguments([new Reference($serviceId.'.http_methods.inner'), new Reference('httplug.message_factory')])
325
                ->setPublic(false)
326
                ->setDecoratedService($serviceId)
327
            ;
328
        }
329
330 View Code Duplication
        if ($arguments['batch_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...
331
            $container
332
                ->register($serviceId.'.batch_client', BatchClient::class)
333
                ->setArguments([new Reference($serviceId.'.batch_client.inner')])
334
                ->setPublic(false)
335
                ->setDecoratedService($serviceId)
336
            ;
337
        }
338
    }
339
340
    /**
341
     * Create a URI object with the default URI factory.
342
     *
343
     * @param ContainerBuilder $container
344
     * @param string           $serviceId Name of the private service to create
345
     * @param string           $uri       String representation of the URI
346
     */
347
    private function createUri(ContainerBuilder $container, $serviceId, $uri)
348
    {
349
        $container
350
            ->register($serviceId, UriInterface::class)
351
            ->setPublic(false)
352
            ->setFactory([new Reference('httplug.uri_factory'), 'createUri'])
353
            ->addArgument($uri)
354
        ;
355
    }
356
357
    /**
358
     * Make the user can select what client is used for auto discovery. If none is provided, a service will be created
359
     * by finding a client using auto discovery.
360
     *
361
     * @param ContainerBuilder $container
362
     * @param array            $config
363
     */
364
    private function configureAutoDiscoveryClients(ContainerBuilder $container, array $config)
365
    {
366
        $httpClient = $config['discovery']['client'];
367
368 View Code Duplication
        if (!empty($httpClient)) {
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...
369
            if ($httpClient === 'auto') {
370
                $httpClient = $this->registerAutoDiscoverableClient(
371
                    $container,
372
                    'auto_discovered_client',
373
                    $this->configureAutoDiscoveryFactory(
374
                        $container,
375
                        HttpClientDiscovery::class,
376
                        'auto_discovered_client',
377
                        $config
378
                    ),
379
                    $this->isConfigEnabled($container, $config['profiling'])
380
                );
381
            }
382
383
            $httpClient = new Reference($httpClient);
384
        }
385
386
        $asyncHttpClient = $config['discovery']['async_client'];
387
388 View Code Duplication
        if (!empty($asyncHttpClient)) {
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...
389
            if ($asyncHttpClient === 'auto') {
390
                $asyncHttpClient = $this->registerAutoDiscoverableClient(
391
                    $container,
392
                    'auto_discovered_async',
393
                    $this->configureAutoDiscoveryFactory(
394
                        $container,
395
                        HttpAsyncClientDiscovery::class,
396
                        'auto_discovered_async',
397
                        $config
398
                    ),
399
                    $this->isConfigEnabled($container, $config['profiling'])
400
                );
401
            }
402
403
            $asyncHttpClient = new Reference($asyncHttpClient);
404
        }
405
406
        if (null === $httpClient && null === $asyncHttpClient) {
407
            $container->removeDefinition('httplug.strategy');
408
409
            return;
410
        }
411
412
        $container
413
            ->getDefinition('httplug.strategy')
414
            ->addArgument($httpClient)
415
            ->addArgument($asyncHttpClient)
416
        ;
417
    }
418
419
    /**
420
     * Find a client with auto discovery and return a service Reference to it.
421
     *
422
     * @param ContainerBuilder   $container
423
     * @param string             $name
424
     * @param Reference|callable $factory
425
     * @param bool               $profiling
426
     *
427
     * @return string service id
428
     */
429
    private function registerAutoDiscoverableClient(ContainerBuilder $container, $name, $factory, $profiling)
430
    {
431
        $serviceId = 'httplug.auto_discovery.'.$name;
432
433
        $plugins = [];
434
        if ($profiling) {
435
            // To profile the requests, add a StackPlugin as first plugin in the chain.
436
            $plugins[] = $this->configureStackPlugin($container, $name, $serviceId);
437
        }
438
439
        $container
440
            ->register($serviceId, DummyClient::class)
441
            ->setFactory([PluginClientFactory::class, 'createPluginClient'])
442
            ->setArguments([
443
                array_map(
444
                    function ($id) {
445
                        return new Reference($id);
446
                    },
447
                    $plugins
448
                ),
449
                $factory,
450
                [],
451
            ])
452
        ;
453
454
        if ($profiling) {
455
            $collector = $container->getDefinition('httplug.collector.collector');
456
            $collector->replaceArgument(0, array_merge($collector->getArgument(0), [$name]));
457
        }
458
459
        return $serviceId;
460
    }
461
462
    /**
463
     * {@inheritdoc}
464
     */
465
    public function getConfiguration(array $config, ContainerBuilder $container)
466
    {
467
        return new Configuration($container->getParameter('kernel.debug'));
468
    }
469
470
    /**
471
     * Configure a plugin using the parent definition from plugins.xml.
472
     *
473
     * @param ContainerBuilder $container
474
     * @param string           $serviceId
475
     * @param string           $pluginName
476
     * @param array            $pluginConfig
477
     *
478
     * @return string configured service id
479
     */
480
    private function configurePlugin(ContainerBuilder $container, $serviceId, $pluginName, array $pluginConfig)
481
    {
482
        $pluginServiceId = $serviceId.'.plugin.'.$pluginName;
483
484
        $definition = class_exists(ChildDefinition::class)
485
            ? new ChildDefinition('httplug.plugin.'.$pluginName)
486
            : new DefinitionDecorator('httplug.plugin.'.$pluginName);
487
488
        $this->configurePluginByName($pluginName, $definition, $pluginConfig, $container, $pluginServiceId);
489
        $container->setDefinition($pluginServiceId, $definition);
490
491
        return $pluginServiceId;
492
    }
493
494
    /**
495
     * Decorate the plugin service with a ProfilePlugin service.
496
     *
497
     * @param ContainerBuilder $container
498
     * @param string           $pluginServiceId
499
     */
500
    private function decoratePluginWithProfilePlugin(ContainerBuilder $container, $pluginServiceId)
501
    {
502
        $container->register($pluginServiceId.'.debug', ProfilePlugin::class)
503
            ->setDecoratedService($pluginServiceId)
504
            ->setArguments([
505
                new Reference($pluginServiceId.'.debug.inner'),
506
                new Reference('httplug.collector.collector'),
507
                new Reference('httplug.collector.formatter'),
508
                $pluginServiceId,
509
            ])
510
            ->setPublic(false);
511
    }
512
513
    /**
514
     * Configure a StackPlugin for a client.
515
     *
516
     * @param ContainerBuilder $container
517
     * @param string           $clientName Client name to display in the profiler.
518
     * @param string           $serviceId  Client service id. Used as base for the StackPlugin service id.
519
     *
520
     * @return string configured StackPlugin service id
521
     */
522
    private function configureStackPlugin(ContainerBuilder $container, $clientName, $serviceId)
523
    {
524
        $pluginServiceId = $serviceId.'.plugin.stack';
525
526
        $definition = class_exists(ChildDefinition::class)
527
            ? new ChildDefinition('httplug.plugin.stack')
528
            : new DefinitionDecorator('httplug.plugin.stack');
529
530
        $definition->addArgument($clientName);
531
        $container->setDefinition($pluginServiceId, $definition);
532
533
        return $pluginServiceId;
534
    }
535
536
    /**
537
     * Configure the discovery factory when profiling is enabled to get client decorated with a ProfileClient.
538
     *
539
     * @param ContainerBuilder $container
540
     * @param string           $discovery
541
     * @param string           $name
542
     * @param array            $config
543
     *
544
     * @return callable|Reference
545
     */
546
    private function configureAutoDiscoveryFactory(ContainerBuilder $container, $discovery, $name, array $config)
547
    {
548
        $factory = [$discovery, 'find'];
549
        if ($this->isConfigEnabled($container, $config['profiling'])) {
550
            $factoryServiceId = 'httplug.auto_discovery.'.$name.'.factory';
551
            $container->register($factoryServiceId, ProfileClientFactory::class)
552
                ->setPublic(false)
553
                ->setArguments([
554
                    $factory,
555
                    new Reference('httplug.collector.collector'),
556
                    new Reference('httplug.collector.formatter'),
557
                    new Reference('debug.stopwatch'),
558
                ]);
559
            $factory = new Reference($factoryServiceId);
560
        }
561
562
        return $factory;
563
    }
564
}
565