FOSHttpCacheExtension   F
last analyzed

Complexity

Total Complexity 95

Size/Duplication

Total Lines 596
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 90.26%

Importance

Changes 0
Metric Value
wmc 95
lcom 1
cbo 9
dl 0
loc 596
ccs 278
cts 308
cp 0.9026
rs 2
c 0
b 0
f 0

24 Methods

Rating   Name   Duplication   Size   Complexity  
A getConfiguration() 0 4 1
F load() 0 97 22
A loadCacheable() 0 15 2
A loadCacheControl() 0 14 3
A parseRuleMatcher() 0 20 2
A parseRequestMatcher() 0 27 4
A parseResponseMatcher() 0 24 5
B loadUserContext() 0 59 7
A loadProxyClient() 0 24 5
A createHttpDispatcherDefinition() 0 24 4
A loadVarnish() 0 18 3
A loadNginx() 0 8 1
A loadSymfony() 0 25 3
B loadCacheTagging() 0 39 8
A loadTest() 0 8 2
A loadProxyServer() 0 15 3
A loadVarnishProxyServer() 0 10 2
A loadNginxProxyServer() 0 10 2
A loadTagRules() 0 15 2
A loadInvalidatorRules() 0 9 2
A validateUrl() 0 8 2
A prefixSchema() 0 8 2
B getDefaultProxyClient() 0 24 6
A createChildDefinition() 0 8 2

How to fix   Complexity   

Complex Class

Complex classes like FOSHttpCacheExtension 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 FOSHttpCacheExtension, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the FOSHttpCacheBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace FOS\HttpCacheBundle\DependencyInjection;
13
14
use FOS\HttpCache\ProxyClient\HttpDispatcher;
15
use FOS\HttpCache\ProxyClient\ProxyClient;
16
use FOS\HttpCache\ProxyClient\Varnish;
17
use FOS\HttpCache\SymfonyCache\KernelDispatcher;
18
use FOS\HttpCache\TagHeaderFormatter\MaxHeaderValueLengthFormatter;
19
use FOS\HttpCacheBundle\DependencyInjection\Compiler\HashGeneratorPass;
20
use FOS\HttpCacheBundle\Http\ResponseMatcher\ExpressionResponseMatcher;
21
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
22
use Symfony\Component\Config\FileLocator;
23
use Symfony\Component\Console\Application;
24
use Symfony\Component\DependencyInjection\ChildDefinition;
25
use Symfony\Component\DependencyInjection\ContainerBuilder;
26
use Symfony\Component\DependencyInjection\Definition;
27
use Symfony\Component\DependencyInjection\DefinitionDecorator;
28
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
29
use Symfony\Component\DependencyInjection\Reference;
30
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
31
use Symfony\Component\HttpKernel\Kernel;
32
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
33
34
/**
35
 * {@inheritdoc}
36
 */
37
class FOSHttpCacheExtension extends Extension
38
{
39
    /**
40
     * {@inheritdoc}
41
     */
42 37
    public function getConfiguration(array $config, ContainerBuilder $container)
43
    {
44 37
        return new Configuration($container->getParameter('kernel.debug'));
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 37
    public function load(array $configs, ContainerBuilder $container)
51
    {
52 37
        $configuration = $this->getConfiguration($configs, $container);
53 37
        $config = $this->processConfiguration($configuration, $configs);
0 ignored issues
show
Bug introduced by David de Boer
It seems like $configuration defined by $this->getConfiguration($configs, $container) on line 52 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...
54
55 37
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
56 37
        $loader->load('matcher.xml');
57
58 37
        if ($config['debug']['enabled'] || (!empty($config['cache_control']))) {
59 7
            $debugHeader = $config['debug']['enabled'] ? $config['debug']['header'] : false;
60 7
            $container->setParameter('fos_http_cache.debug_header', $debugHeader);
61 7
            $loader->load('cache_control_listener.xml');
62
        }
63
64 37
        $this->loadCacheable($container, $config['cacheable']);
65
66 37
        if (!empty($config['cache_control'])) {
67 7
            $this->loadCacheControl($container, $config['cache_control']);
68
        }
69
70 36
        if (isset($config['proxy_client'])) {
71 27
            $this->loadProxyClient($container, $loader, $config['proxy_client']);
72
        }
73
74 35
        if (isset($config['test'])) {
75 2
            $this->loadTest($container, $loader, $config['test']);
76
        }
77
78 35
        if ($config['cache_manager']['enabled']) {
79 27
            if (array_key_exists('custom_proxy_client', $config['cache_manager'])) {
80
                // overwrite the previously set alias, if a proxy client was also configured
81 1
                $container->setAlias(
82 1
                    'fos_http_cache.default_proxy_client',
83 1
                    $config['cache_manager']['custom_proxy_client']
84
                );
85
            }
86 27
            if ('auto' === $config['cache_manager']['generate_url_type']) {
87 27
                if (array_key_exists('custom_proxy_client', $config['cache_manager'])) {
88 1
                    $generateUrlType = UrlGeneratorInterface::ABSOLUTE_URL;
89
                } else {
90 26
                    $defaultClient = $this->getDefaultProxyClient($config['proxy_client']);
91 26
                    if ('noop' !== $defaultClient
92 26
                        && array_key_exists('base_url', $config['proxy_client'][$defaultClient])) {
93
                        $generateUrlType = UrlGeneratorInterface::ABSOLUTE_PATH;
94
                    } else {
95 27
                        $generateUrlType = UrlGeneratorInterface::ABSOLUTE_URL;
96
                    }
97
                }
98
            } else {
99
                $generateUrlType = $config['cache_manager']['generate_url_type'];
100
            }
101 27
            $container->setParameter('fos_http_cache.cache_manager.generate_url_type', $generateUrlType);
102 27
            $loader->load('cache_manager.xml');
103 27
            if (class_exists(Application::class)) {
104 27
                $loader->load('cache_manager_commands.xml');
105
            }
106
        }
107
108 35
        if ($config['tags']['enabled']) {
109 27
            $this->loadCacheTagging(
110 27
                $container,
111 27
                $loader,
112 27
                $config['tags'],
113 27
                array_key_exists('proxy_client', $config)
114 26
                    ? $this->getDefaultProxyClient($config['proxy_client'])
115 27
                    : 'custom'
116
            );
117
        } else {
118 8
            $container->setParameter('fos_http_cache.compiler_pass.tag_annotations', false);
119
        }
120
121 34
        if ($config['invalidation']['enabled']) {
122 26
            $loader->load('invalidation_listener.xml');
123
124 26
            if (!empty($config['invalidation']['expression_language'])) {
125
                $container->setAlias(
126
                    'fos_http_cache.invalidation.expression_language',
127
                    $config['invalidation']['expression_language']
128
                );
129
            }
130
131 26
            if (!empty($config['invalidation']['rules'])) {
132 3
                $this->loadInvalidatorRules($container, $config['invalidation']['rules']);
133
            }
134
        }
135
136 34
        if ($config['user_context']['enabled']) {
137 6
            $this->loadUserContext($container, $loader, $config['user_context']);
138
        }
139
140 34
        if (!empty($config['flash_message']) && $config['flash_message']['enabled']) {
141 3
            unset($config['flash_message']['enabled']);
142 3
            $container->setParameter('fos_http_cache.event_listener.flash_message.options', $config['flash_message']);
143
144 3
            $loader->load('flash_message.xml');
145
        }
146 34
    }
147
148 37
    private function loadCacheable(ContainerBuilder $container, array $config)
149
    {
150 37
        $definition = $container->getDefinition('fos_http_cache.response_matcher.cacheable');
151
152
        // Change CacheableResponseMatcher to ExpressionResponseMatcher
153 37
        if ($config['response']['expression']) {
154
            $definition->setClass(ExpressionResponseMatcher::class)
155
                ->setArguments([$config['response']['expression']]);
156
        } else {
157 37
            $container->setParameter(
158 37
                'fos_http_cache.cacheable.response.additional_status',
159 37
                $config['response']['additional_status']
160
            );
161
        }
162 37
    }
163
164
    /**
165
     * @param ContainerBuilder $container
166
     * @param array            $config
167
     *
168
     * @throws InvalidConfigurationException
169
     */
170 7
    private function loadCacheControl(ContainerBuilder $container, array $config)
171
    {
172 7
        $controlDefinition = $container->getDefinition('fos_http_cache.event_listener.cache_control');
173
174 7
        foreach ($config['rules'] as $rule) {
175 7
            $ruleMatcher = $this->parseRuleMatcher($container, $rule['match']);
176
177 7
            if ('default' === $rule['headers']['overwrite']) {
178 7
                $rule['headers']['overwrite'] = $config['defaults']['overwrite'];
179
            }
180
181 7
            $controlDefinition->addMethodCall('addRule', [$ruleMatcher, $rule['headers']]);
182
        }
183 6
    }
184
185
    /**
186
     * Parse one cache control rule match configuration.
187
     *
188
     * @param ContainerBuilder $container
189
     * @param array            $match     Request and response match criteria
190
     *
191
     * @return Reference pointing to a rule matcher service
192
     */
193 7
    private function parseRuleMatcher(ContainerBuilder $container, array $match)
194
    {
195 7
        $requestMatcher = $this->parseRequestMatcher($container, $match);
196 7
        $responseMatcher = $this->parseResponseMatcher($container, $match);
197
198 7
        $signature = serialize([(string) $requestMatcher, (string) $responseMatcher]);
199 7
        $id = 'fos_http_cache.cache_control.rule_matcher.'.md5($signature);
200
201 7
        if ($container->hasDefinition($id)) {
202 1
            throw new InvalidConfigurationException('Duplicate match criteria. Would be hidden by a previous rule. match: '.json_encode($match));
203
        }
204
205
        $container
206 7
            ->setDefinition($id, $this->createChildDefinition('fos_http_cache.rule_matcher'))
207 7
            ->replaceArgument(0, $requestMatcher)
208 7
            ->replaceArgument(1, $responseMatcher)
209
        ;
210
211 7
        return new Reference($id);
212
    }
213
214
    /**
215
     * Used for cache control, tag and invalidation rules.
216
     *
217
     * @param ContainerBuilder $container
218
     * @param array            $match
219
     *
220
     * @return Reference to the request matcher
221
     */
222 9
    private function parseRequestMatcher(ContainerBuilder $container, array $match)
223
    {
224 9
        $match['ips'] = (empty($match['ips'])) ? null : $match['ips'];
225
226
        $arguments = [
227 9
            $match['path'],
228 9
            $match['host'],
229 9
            $match['methods'],
230 9
            $match['ips'],
231 9
            $match['attributes'],
232
        ];
233 9
        $serialized = serialize($arguments);
234 9
        $id = 'fos_http_cache.request_matcher.'.md5($serialized).sha1($serialized);
235
236 9
        if (!$container->hasDefinition($id)) {
237
            $container
238 9
                ->setDefinition($id, $this->createChildDefinition('fos_http_cache.request_matcher'))
239 9
                ->setArguments($arguments)
240
            ;
241
242 9
            if (!empty($match['query_string'])) {
243
                $container->getDefinition($id)->addMethodCall('setQueryString', [$match['query_string']]);
244
            }
245
        }
246
247 9
        return new Reference($id);
248
    }
249
250
    /**
251
     * Used only for cache control rules.
252
     *
253
     * @param ContainerBuilder $container
254
     * @param array            $config
255
     *
256
     * @return Reference to the correct response matcher service
257
     */
258 7
    private function parseResponseMatcher(ContainerBuilder $container, array $config)
259
    {
260 7
        if (!empty($config['additional_response_status'])) {
261 1
            $id = 'fos_http_cache.cache_control.expression.'.md5(serialize($config['additional_response_status']));
262 1
            if (!$container->hasDefinition($id)) {
263
                $container
264 1
                    ->setDefinition($id, $this->createChildDefinition('fos_http_cache.response_matcher.cache_control.cacheable_response'))
265 1
                    ->setArguments([$config['additional_response_status']])
266
                ;
267
            }
268 6
        } elseif (!empty($config['match_response'])) {
269 2
            $id = 'fos_http_cache.cache_control.match_response.'.md5($config['match_response']);
270 2
            if (!$container->hasDefinition($id)) {
271
                $container
272 2
                    ->setDefinition($id, $this->createChildDefinition('fos_http_cache.response_matcher.cache_control.expression'))
273 2
                    ->replaceArgument(0, $config['match_response'])
274
                ;
275
            }
276
        } else {
277 4
            $id = 'fos_http_cache.response_matcher.cacheable';
278
        }
279
280 7
        return new Reference($id);
281
    }
282
283 6
    private function loadUserContext(ContainerBuilder $container, XmlFileLoader $loader, array $config)
284
    {
285 6
        $configuredUserIdentifierHeaders = array_map('strtolower', $config['user_identifier_headers']);
286 6
        $completeUserIdentifierHeaders = $configuredUserIdentifierHeaders;
287 6
        if (false !== $config['session_name_prefix'] && !in_array('cookie', $completeUserIdentifierHeaders)) {
288
            $completeUserIdentifierHeaders[] = 'cookie';
289
        }
290
291 6
        $loader->load('user_context.xml');
292
293 6
        $container->getDefinition('fos_http_cache.user_context.request_matcher')
294 6
            ->replaceArgument(0, $config['match']['accept'])
295 6
            ->replaceArgument(1, $config['match']['method']);
296
297 6
        $container->setParameter('fos_http_cache.event_listener.user_context.options', [
298 6
            'user_identifier_headers' => $completeUserIdentifierHeaders,
299 6
            'user_hash_header' => $config['user_hash_header'],
300 6
            'ttl' => $config['hash_cache_ttl'],
301 6
            'add_vary_on_hash' => $config['always_vary_on_context_hash'],
302
        ]);
303
304 6
        $container->getDefinition('fos_http_cache.event_listener.user_context')
305 6
            ->replaceArgument(0, new Reference($config['match']['matcher_service']))
306
        ;
307
308
        $options = [
309 6
            'user_identifier_headers' => $configuredUserIdentifierHeaders,
310 6
            'session_name_prefix' => $config['session_name_prefix'],
311
        ];
312 6
        $container->getDefinition('fos_http_cache.user_context.anonymous_request_matcher')
313 6
            ->replaceArgument(0, $options);
314
315 6
        if ($config['logout_handler']['enabled']) {
316 5
            $container->setAlias('security.logout.handler.session', 'fos_http_cache.user_context.session_logout_handler');
317
        } else {
318 1
            $container->removeDefinition('fos_http_cache.user_context.logout_handler');
319 1
            $container->removeDefinition('fos_http_cache.user_context.session_logout_handler');
320 1
            $container->removeDefinition('fos_http_cache.user_context_invalidator');
321
        }
322
323 6
        if ($config['role_provider']) {
324 4
            $container->getDefinition('fos_http_cache.user_context.role_provider')
325 4
                ->addTag(HashGeneratorPass::TAG_NAME)
326 4
                ->setAbstract(false);
327
        }
328
329
        // Only decorate default SessionListener for Symfony 3.4 - 4.0
330
        // For Symfony 4.1+, the UserContextListener sets the header that tells
331
        // the SessionListener to leave the cache-control header unchanged.
332 6
        if (version_compare(Kernel::VERSION, '3.4', '>=')
333 6
            && version_compare(Kernel::VERSION, '4.1', '<')
334
        ) {
335
            $container->getDefinition('fos_http_cache.user_context.session_listener')
336
                ->setArgument(1, strtolower($config['user_hash_header']))
337
                ->setArgument(2, $completeUserIdentifierHeaders);
338
        } else {
339 6
            $container->removeDefinition('fos_http_cache.user_context.session_listener');
340
        }
341 6
    }
342
343 27
    private function loadProxyClient(ContainerBuilder $container, XmlFileLoader $loader, array $config)
344
    {
345 27
        if (isset($config['varnish'])) {
346 22
            $this->loadVarnish($container, $loader, $config['varnish']);
347
        }
348 26
        if (isset($config['nginx'])) {
349 2
            $this->loadNginx($container, $loader, $config['nginx']);
350
        }
351 26
        if (isset($config['symfony'])) {
352 2
            $this->loadSymfony($container, $loader, $config['symfony']);
353
        }
354 26
        if (isset($config['noop'])) {
355 1
            $loader->load('noop.xml');
356
        }
357
358 26
        $container->setAlias(
359 26
            'fos_http_cache.default_proxy_client',
360 26
            'fos_http_cache.proxy_client.'.$this->getDefaultProxyClient($config)
361
        );
362 26
        $container->setAlias(
363 26
            ProxyClient::class,
364 26
            'fos_http_cache.default_proxy_client'
365
        );
366 26
    }
367
368
    /**
369
     * Define the http dispatcher service for the proxy client $name.
370
     *
371
     * @param ContainerBuilder $container
372
     * @param array            $config
373
     * @param string           $serviceName
374
     */
375 25
    private function createHttpDispatcherDefinition(ContainerBuilder $container, array $config, $serviceName)
376
    {
377 25
        foreach ($config['servers'] as $url) {
378 25
            $this->validateUrl($url, 'Not a valid Varnish server address: "%s"');
379
        }
380 25
        if (!empty($config['base_url'])) {
381 25
            $baseUrl = $this->prefixSchema($config['base_url']);
382 25
            $this->validateUrl($baseUrl, 'Not a valid base path: "%s"');
383
        } else {
384
            $baseUrl = null;
385
        }
386 24
        $httpClient = null;
387 24
        if ($config['http_client']) {
388 1
            $httpClient = new Reference($config['http_client']);
389
        }
390
391 24
        $definition = new Definition(HttpDispatcher::class, [
392 24
            $config['servers'],
393 24
            $baseUrl,
394 24
            $httpClient,
395
        ]);
396
397 24
        $container->setDefinition($serviceName, $definition);
398 24
    }
399
400 22
    private function loadVarnish(ContainerBuilder $container, XmlFileLoader $loader, array $config)
401
    {
402 22
        $this->createHttpDispatcherDefinition($container, $config['http'], 'fos_http_cache.proxy_client.varnish.http_dispatcher');
403
        $options = [
404 21
            'tag_mode' => $config['tag_mode'],
405 21
            'tags_header' => $config['tags_header'],
406
        ];
407
408 21
        if (!empty($config['header_length'])) {
409
            $options['header_length'] = $config['header_length'];
410
        }
411 21
        if (!empty($config['default_ban_headers'])) {
412
            $options['default_ban_headers'] = $config['default_ban_headers'];
413
        }
414 21
        $container->setParameter('fos_http_cache.proxy_client.varnish.options', $options);
415
416 21
        $loader->load('varnish.xml');
417 21
    }
418
419 2
    private function loadNginx(ContainerBuilder $container, XmlFileLoader $loader, array $config)
420
    {
421 2
        $this->createHttpDispatcherDefinition($container, $config['http'], 'fos_http_cache.proxy_client.nginx.http_dispatcher');
422 2
        $container->setParameter('fos_http_cache.proxy_client.nginx.options', [
423 2
            'purge_location' => $config['purge_location'],
424
        ]);
425 2
        $loader->load('nginx.xml');
426 2
    }
427
428 2
    private function loadSymfony(ContainerBuilder $container, XmlFileLoader $loader, array $config)
429
    {
430 2
        $serviceName = 'fos_http_cache.proxy_client.symfony.http_dispatcher';
431
432 2
        if ($config['use_kernel_dispatcher']) {
433 1
            $definition = new Definition(KernelDispatcher::class, [
434 1
                new Reference('kernel'),
435
            ]);
436 1
            $container->setDefinition($serviceName, $definition);
437
        } else {
438 1
            $this->createHttpDispatcherDefinition($container, $config['http'], $serviceName);
439
        }
440
441
        $options = [
442 2
            'tags_header' => $config['tags_header'],
443 2
            'tags_method' => $config['tags_method'],
444 2
            'purge_method' => $config['purge_method'],
445
        ];
446 2
        if (!empty($config['header_length'])) {
447
            $options['header_length'] = $config['header_length'];
448
        }
449 2
        $container->setParameter('fos_http_cache.proxy_client.symfony.options', $options);
450
451 2
        $loader->load('symfony.xml');
452 2
    }
453
454
    /**
455
     * @param ContainerBuilder $container
456
     * @param XmlFileLoader    $loader
457
     * @param array            $config    Configuration section for the tags node
458
     * @param string           $client    Name of the client used with the cache manager,
459
     *                                    "custom" when a custom client is used
460
     */
461 27
    private function loadCacheTagging(ContainerBuilder $container, XmlFileLoader $loader, array $config, $client)
462
    {
463 27
        if ('auto' === $config['enabled'] && !in_array($client, ['varnish', 'symfony'])) {
464 3
            $container->setParameter('fos_http_cache.compiler_pass.tag_annotations', false);
465
466 3
            return;
467
        }
468 24
        if (!in_array($client, ['varnish', 'symfony', 'custom', 'noop'])) {
469 1
            throw new InvalidConfigurationException(sprintf('You can not enable cache tagging with the %s client', $client));
470
        }
471
472 23
        $container->setParameter('fos_http_cache.compiler_pass.tag_annotations', $config['annotations']['enabled']);
473 23
        $container->setParameter('fos_http_cache.tag_handler.response_header', $config['response_header']);
474 23
        $container->setParameter('fos_http_cache.tag_handler.separator', $config['separator']);
475 23
        $container->setParameter('fos_http_cache.tag_handler.strict', $config['strict']);
476
477 23
        $loader->load('cache_tagging.xml');
478 23
        if (class_exists(Application::class)) {
479 23
            $loader->load('cache_tagging_commands.xml');
480
        }
481
482 23
        if (!empty($config['expression_language'])) {
483
            $container->setAlias(
484
                'fos_http_cache.tag_handler.expression_language',
485
                $config['expression_language']
486
            );
487
        }
488
489 23
        if (!empty($config['rules'])) {
490 3
            $this->loadTagRules($container, $config['rules']);
491
        }
492
493 23
        if (null !== $config['max_header_value_length']) {
494 1
            $container->register('fos_http_cache.tag_handler.max_header_value_length_header_formatter', MaxHeaderValueLengthFormatter::class)
495 1
                ->setDecoratedService('fos_http_cache.tag_handler.header_formatter')
496 1
                ->addArgument(new Reference('fos_http_cache.tag_handler.max_header_value_length_header_formatter.inner'))
497 1
                ->addArgument((int) $config['max_header_value_length']);
498
        }
499 23
    }
500
501 2
    private function loadTest(ContainerBuilder $container, XmlFileLoader $loader, array $config)
502
    {
503 2
        $container->setParameter('fos_http_cache.test.cache_header', $config['cache_header']);
504
505 2
        if ($config['proxy_server']) {
506 2
            $this->loadProxyServer($container, $loader, $config['proxy_server']);
507
        }
508 2
    }
509
510 2
    private function loadProxyServer(ContainerBuilder $container, XmlFileLoader $loader, array $config)
511
    {
512 2
        if (isset($config['varnish'])) {
513 2
            $this->loadVarnishProxyServer($container, $loader, $config['varnish']);
514
        }
515
516 2
        if (isset($config['nginx'])) {
517
            $this->loadNginxProxyServer($container, $loader, $config['nginx']);
518
        }
519
520 2
        $container->setAlias(
521 2
            'fos_http_cache.test.default_proxy_server',
522 2
            'fos_http_cache.test.proxy_server.'.$this->getDefaultProxyClient($config)
523
        );
524 2
    }
525
526 2
    private function loadVarnishProxyServer(ContainerBuilder $container, XmlFileLoader $loader, $config)
527
    {
528 2
        $loader->load('varnish_proxy.xml');
529 2
        foreach ($config as $key => $value) {
530 2
            $container->setParameter(
531 2
                'fos_http_cache.test.proxy_server.varnish.'.$key,
532 2
                $value
533
            );
534
        }
535 2
    }
536
537
    private function loadNginxProxyServer(ContainerBuilder $container, XmlFileLoader $loader, $config)
538
    {
539
        $loader->load('nginx_proxy.xml');
540
        foreach ($config as $key => $value) {
541
            $container->setParameter(
542
                'fos_http_cache.test.proxy_server.nginx.'.$key,
543
                $value
544
            );
545
        }
546
    }
547
548 3
    private function loadTagRules(ContainerBuilder $container, array $config)
549
    {
550 3
        $tagDefinition = $container->getDefinition('fos_http_cache.event_listener.tag');
551
552 3
        foreach ($config as $rule) {
553 3
            $ruleMatcher = $this->parseRequestMatcher($container, $rule['match']);
554
555
            $tags = [
556 3
                'tags' => $rule['tags'],
557 3
                'expressions' => $rule['tag_expressions'],
558
            ];
559
560 3
            $tagDefinition->addMethodCall('addRule', [$ruleMatcher, $tags]);
561
        }
562 3
    }
563
564 3
    private function loadInvalidatorRules(ContainerBuilder $container, array $config)
565
    {
566 3
        $tagDefinition = $container->getDefinition('fos_http_cache.event_listener.invalidation');
567
568 3
        foreach ($config as $rule) {
569 3
            $ruleMatcher = $this->parseRequestMatcher($container, $rule['match']);
570 3
            $tagDefinition->addMethodCall('addRule', [$ruleMatcher, $rule['routes']]);
571
        }
572 3
    }
573
574 25
    private function validateUrl($url, $msg)
575
    {
576 25
        $prefixed = $this->prefixSchema($url);
577
578 25
        if (!$parts = parse_url($prefixed)) {
579 1
            throw new InvalidConfigurationException(sprintf($msg, $url));
580
        }
581 25
    }
582
583 25
    private function prefixSchema($url)
584
    {
585 25
        if (false === strpos($url, '://')) {
586 25
            $url = sprintf('%s://%s', 'http', $url);
587
        }
588
589 25
        return $url;
590
    }
591
592 26
    private function getDefaultProxyClient(array $config)
593
    {
594 26
        if (isset($config['default'])) {
595
            return $config['default'];
596
        }
597
598 26
        if (isset($config['varnish'])) {
599 21
            return 'varnish';
600
        }
601
602 5
        if (isset($config['nginx'])) {
603 2
            return 'nginx';
604
        }
605
606 3
        if (isset($config['symfony'])) {
607 2
            return 'symfony';
608
        }
609
610 1
        if (isset($config['noop'])) {
611 1
            return 'noop';
612
        }
613
614
        throw new InvalidConfigurationException('No proxy client configured');
615
    }
616
617
    /**
618
     * Build the child definition with fallback for Symfony versions < 3.3.
619
     *
620
     * @param string $id Id of the service to extend
621
     *
622
     * @return ChildDefinition|DefinitionDecorator
623
     */
624 9
    private function createChildDefinition($id)
625
    {
626 9
        if (class_exists(ChildDefinition::class)) {
627 9
            return new ChildDefinition($id);
628
        }
629
630
        return new DefinitionDecorator($id);
631
    }
632
}
633