Completed
Push — master ( 86d539...f93488 )
by David
15s queued 12s
created

createHttpDispatcherDefinition()   B

Complexity

Conditions 6
Paths 18

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 6.0029

Importance

Changes 0
Metric Value
dl 0
loc 33
ccs 22
cts 23
cp 0.9565
rs 8.7697
c 0
b 0
f 0
cc 6
nc 18
nop 3
crap 6.0029
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
            $usedEnvs = [];
379 25
            $container->resolveEnvPlaceholders($url, null, $usedEnvs);
380 25
            if (0 === \count($usedEnvs)) {
381 25
                $this->validateUrl($url, 'Not a valid Varnish server address: "%s"');
382
            }
383
        }
384 25
        if (!empty($config['base_url'])) {
385 25
            $baseUrl = $config['base_url'];
386 25
            $usedEnvs = [];
387 25
            $container->resolveEnvPlaceholders($baseUrl, null, $usedEnvs);
388 25
            if (0 === \count($usedEnvs)) {
389 25
                $baseUrl = $this->prefixSchema($baseUrl);
390 25
                $this->validateUrl($baseUrl, 'Not a valid base path: "%s"');
391
            }
392
        } else {
393
            $baseUrl = null;
394
        }
395 24
        $httpClient = null;
396 24
        if ($config['http_client']) {
397 1
            $httpClient = new Reference($config['http_client']);
398
        }
399
400 24
        $definition = new Definition(HttpDispatcher::class, [
401 24
            $config['servers'],
402 24
            $baseUrl,
403 24
            $httpClient,
404
        ]);
405
406 24
        $container->setDefinition($serviceName, $definition);
407 24
    }
408
409 22
    private function loadVarnish(ContainerBuilder $container, XmlFileLoader $loader, array $config)
410
    {
411 22
        $this->createHttpDispatcherDefinition($container, $config['http'], 'fos_http_cache.proxy_client.varnish.http_dispatcher');
412
        $options = [
413 21
            'tag_mode' => $config['tag_mode'],
414 21
            'tags_header' => $config['tags_header'],
415
        ];
416
417 21
        if (!empty($config['header_length'])) {
418
            $options['header_length'] = $config['header_length'];
419
        }
420 21
        if (!empty($config['default_ban_headers'])) {
421
            $options['default_ban_headers'] = $config['default_ban_headers'];
422
        }
423 21
        $container->setParameter('fos_http_cache.proxy_client.varnish.options', $options);
424
425 21
        $loader->load('varnish.xml');
426 21
    }
427
428 2
    private function loadNginx(ContainerBuilder $container, XmlFileLoader $loader, array $config)
429
    {
430 2
        $this->createHttpDispatcherDefinition($container, $config['http'], 'fos_http_cache.proxy_client.nginx.http_dispatcher');
431 2
        $container->setParameter('fos_http_cache.proxy_client.nginx.options', [
432 2
            'purge_location' => $config['purge_location'],
433
        ]);
434 2
        $loader->load('nginx.xml');
435 2
    }
436
437 2
    private function loadSymfony(ContainerBuilder $container, XmlFileLoader $loader, array $config)
438
    {
439 2
        $serviceName = 'fos_http_cache.proxy_client.symfony.http_dispatcher';
440
441 2
        if ($config['use_kernel_dispatcher']) {
442 1
            $definition = new Definition(KernelDispatcher::class, [
443 1
                new Reference('kernel'),
444
            ]);
445 1
            $container->setDefinition($serviceName, $definition);
446
        } else {
447 1
            $this->createHttpDispatcherDefinition($container, $config['http'], $serviceName);
448
        }
449
450
        $options = [
451 2
            'tags_header' => $config['tags_header'],
452 2
            'tags_method' => $config['tags_method'],
453 2
            'purge_method' => $config['purge_method'],
454
        ];
455 2
        if (!empty($config['header_length'])) {
456
            $options['header_length'] = $config['header_length'];
457
        }
458 2
        $container->setParameter('fos_http_cache.proxy_client.symfony.options', $options);
459
460 2
        $loader->load('symfony.xml');
461 2
    }
462
463
    /**
464
     * @param ContainerBuilder $container
465
     * @param XmlFileLoader    $loader
466
     * @param array            $config    Configuration section for the tags node
467
     * @param string           $client    Name of the client used with the cache manager,
468
     *                                    "custom" when a custom client is used
469
     */
470 27
    private function loadCacheTagging(ContainerBuilder $container, XmlFileLoader $loader, array $config, $client)
471
    {
472 27
        if ('auto' === $config['enabled'] && !in_array($client, ['varnish', 'symfony'])) {
473 3
            $container->setParameter('fos_http_cache.compiler_pass.tag_annotations', false);
474
475 3
            return;
476
        }
477 24
        if (!in_array($client, ['varnish', 'symfony', 'custom', 'noop'])) {
478 1
            throw new InvalidConfigurationException(sprintf('You can not enable cache tagging with the %s client', $client));
479
        }
480
481 23
        $container->setParameter('fos_http_cache.compiler_pass.tag_annotations', $config['annotations']['enabled']);
482 23
        $container->setParameter('fos_http_cache.tag_handler.response_header', $config['response_header']);
483 23
        $container->setParameter('fos_http_cache.tag_handler.separator', $config['separator']);
484 23
        $container->setParameter('fos_http_cache.tag_handler.strict', $config['strict']);
485
486 23
        $loader->load('cache_tagging.xml');
487 23
        if (class_exists(Application::class)) {
488 23
            $loader->load('cache_tagging_commands.xml');
489
        }
490
491 23
        if (!empty($config['expression_language'])) {
492
            $container->setAlias(
493
                'fos_http_cache.tag_handler.expression_language',
494
                $config['expression_language']
495
            );
496
        }
497
498 23
        if (!empty($config['rules'])) {
499 3
            $this->loadTagRules($container, $config['rules']);
500
        }
501
502 23
        if (null !== $config['max_header_value_length']) {
503 1
            $container->register('fos_http_cache.tag_handler.max_header_value_length_header_formatter', MaxHeaderValueLengthFormatter::class)
504 1
                ->setDecoratedService('fos_http_cache.tag_handler.header_formatter')
505 1
                ->addArgument(new Reference('fos_http_cache.tag_handler.max_header_value_length_header_formatter.inner'))
506 1
                ->addArgument((int) $config['max_header_value_length']);
507
        }
508 23
    }
509
510 2
    private function loadTest(ContainerBuilder $container, XmlFileLoader $loader, array $config)
511
    {
512 2
        $container->setParameter('fos_http_cache.test.cache_header', $config['cache_header']);
513
514 2
        if ($config['proxy_server']) {
515 2
            $this->loadProxyServer($container, $loader, $config['proxy_server']);
516
        }
517 2
    }
518
519 2
    private function loadProxyServer(ContainerBuilder $container, XmlFileLoader $loader, array $config)
520
    {
521 2
        if (isset($config['varnish'])) {
522 2
            $this->loadVarnishProxyServer($container, $loader, $config['varnish']);
523
        }
524
525 2
        if (isset($config['nginx'])) {
526
            $this->loadNginxProxyServer($container, $loader, $config['nginx']);
527
        }
528
529 2
        $container->setAlias(
530 2
            'fos_http_cache.test.default_proxy_server',
531 2
            'fos_http_cache.test.proxy_server.'.$this->getDefaultProxyClient($config)
532
        );
533 2
    }
534
535 2
    private function loadVarnishProxyServer(ContainerBuilder $container, XmlFileLoader $loader, $config)
536
    {
537 2
        $loader->load('varnish_proxy.xml');
538 2
        foreach ($config as $key => $value) {
539 2
            $container->setParameter(
540 2
                'fos_http_cache.test.proxy_server.varnish.'.$key,
541 2
                $value
542
            );
543
        }
544 2
    }
545
546
    private function loadNginxProxyServer(ContainerBuilder $container, XmlFileLoader $loader, $config)
547
    {
548
        $loader->load('nginx_proxy.xml');
549
        foreach ($config as $key => $value) {
550
            $container->setParameter(
551
                'fos_http_cache.test.proxy_server.nginx.'.$key,
552
                $value
553
            );
554
        }
555
    }
556
557 3
    private function loadTagRules(ContainerBuilder $container, array $config)
558
    {
559 3
        $tagDefinition = $container->getDefinition('fos_http_cache.event_listener.tag');
560
561 3
        foreach ($config as $rule) {
562 3
            $ruleMatcher = $this->parseRequestMatcher($container, $rule['match']);
563
564
            $tags = [
565 3
                'tags' => $rule['tags'],
566 3
                'expressions' => $rule['tag_expressions'],
567
            ];
568
569 3
            $tagDefinition->addMethodCall('addRule', [$ruleMatcher, $tags]);
570
        }
571 3
    }
572
573 3
    private function loadInvalidatorRules(ContainerBuilder $container, array $config)
574
    {
575 3
        $tagDefinition = $container->getDefinition('fos_http_cache.event_listener.invalidation');
576
577 3
        foreach ($config as $rule) {
578 3
            $ruleMatcher = $this->parseRequestMatcher($container, $rule['match']);
579 3
            $tagDefinition->addMethodCall('addRule', [$ruleMatcher, $rule['routes']]);
580
        }
581 3
    }
582
583 25
    private function validateUrl($url, $msg)
584
    {
585 25
        $prefixed = $this->prefixSchema($url);
586
587 25
        if (!$parts = parse_url($prefixed)) {
588 1
            throw new InvalidConfigurationException(sprintf($msg, $url));
589
        }
590 25
    }
591
592 25
    private function prefixSchema($url)
593
    {
594 25
        if (false === strpos($url, '://')) {
595 25
            $url = sprintf('%s://%s', 'http', $url);
596
        }
597
598 25
        return $url;
599
    }
600
601 26
    private function getDefaultProxyClient(array $config)
602
    {
603 26
        if (isset($config['default'])) {
604
            return $config['default'];
605
        }
606
607 26
        if (isset($config['varnish'])) {
608 21
            return 'varnish';
609
        }
610
611 5
        if (isset($config['nginx'])) {
612 2
            return 'nginx';
613
        }
614
615 3
        if (isset($config['symfony'])) {
616 2
            return 'symfony';
617
        }
618
619 1
        if (isset($config['noop'])) {
620 1
            return 'noop';
621
        }
622
623
        throw new InvalidConfigurationException('No proxy client configured');
624
    }
625
626
    /**
627
     * Build the child definition with fallback for Symfony versions < 3.3.
628
     *
629
     * @param string $id Id of the service to extend
630
     *
631
     * @return ChildDefinition|DefinitionDecorator
632
     */
633 9
    private function createChildDefinition($id)
634
    {
635 9
        if (class_exists(ChildDefinition::class)) {
636 9
            return new ChildDefinition($id);
637
        }
638
639
        return new DefinitionDecorator($id);
640
    }
641
}
642