Completed
Push — master ( 6219f7...d44e26 )
by David
13s
created

src/DependencyInjection/FOSHttpCacheExtension.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 36
    public function getConfiguration(array $config, ContainerBuilder $container)
43
    {
44 36
        return new Configuration($container->getParameter('kernel.debug'));
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50 36
    public function load(array $configs, ContainerBuilder $container)
51
    {
52 36
        $configuration = $this->getConfiguration($configs, $container);
53 36
        $config = $this->processConfiguration($configuration, $configs);
0 ignored issues
show
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 36
        $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
56 36
        $loader->load('matcher.xml');
57
58 36
        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 36
        $this->loadCacheable($container, $config['cacheable']);
65
66 36
        if (!empty($config['cache_control'])) {
67 7
            $this->loadCacheControl($container, $config['cache_control']);
68
        }
69
70 35
        if (isset($config['proxy_client'])) {
71 26
            $this->loadProxyClient($container, $loader, $config['proxy_client']);
72
        }
73
74 34
        if (isset($config['test'])) {
75 2
            $this->loadTest($container, $loader, $config['test']);
76
        }
77
78 34
        if ($config['cache_manager']['enabled']) {
79 26
            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 26
            if ('auto' === $config['cache_manager']['generate_url_type']) {
87 26
                if (array_key_exists('custom_proxy_client', $config['cache_manager'])) {
88 1
                    $generateUrlType = UrlGeneratorInterface::ABSOLUTE_URL;
89
                } else {
90 25
                    $defaultClient = $this->getDefaultProxyClient($config['proxy_client']);
91 25
                    if ('noop' !== $defaultClient
92 25
                        && array_key_exists('base_url', $config['proxy_client'][$defaultClient])) {
93
                        $generateUrlType = UrlGeneratorInterface::ABSOLUTE_PATH;
94
                    } else {
95 26
                        $generateUrlType = UrlGeneratorInterface::ABSOLUTE_URL;
96
                    }
97
                }
98
            } else {
99
                $generateUrlType = $config['cache_manager']['generate_url_type'];
100
            }
101 26
            $container->setParameter('fos_http_cache.cache_manager.generate_url_type', $generateUrlType);
102 26
            $loader->load('cache_manager.xml');
103 26
            if (class_exists(Application::class)) {
104 26
                $loader->load('cache_manager_commands.xml');
105
            }
106
        }
107
108 34
        if ($config['tags']['enabled']) {
109 26
            $this->loadCacheTagging(
110 26
                $container,
111 26
                $loader,
112 26
                $config['tags'],
113 26
                array_key_exists('proxy_client', $config)
114 25
                    ? $this->getDefaultProxyClient($config['proxy_client'])
115 26
                    : 'custom'
116
            );
117
        } else {
118 8
            $container->setParameter('fos_http_cache.compiler_pass.tag_annotations', false);
119
        }
120
121 33
        if ($config['invalidation']['enabled']) {
122 25
            $loader->load('invalidation_listener.xml');
123
124 25
            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 25
            if (!empty($config['invalidation']['rules'])) {
132 3
                $this->loadInvalidatorRules($container, $config['invalidation']['rules']);
133
            }
134
        }
135
136 33
        if ($config['user_context']['enabled']) {
137 6
            $this->loadUserContext($container, $loader, $config['user_context']);
138
        }
139
140 33
        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 33
    }
147
148 36
    private function loadCacheable(ContainerBuilder $container, array $config)
149
    {
150 36
        $definition = $container->getDefinition('fos_http_cache.response_matcher.cacheable');
151
152
        // Change CacheableResponseMatcher to ExpressionResponseMatcher
153 36
        if ($config['response']['expression']) {
154
            $definition->setClass(ExpressionResponseMatcher::class)
155
                ->setArguments([$config['response']['expression']]);
156
        } else {
157 36
            $container->setParameter(
158 36
                'fos_http_cache.cacheable.response.additional_status',
159 36
                $config['response']['additional_status']
160
            );
161
        }
162 36
    }
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 26
    private function loadProxyClient(ContainerBuilder $container, XmlFileLoader $loader, array $config)
344
    {
345 26
        if (isset($config['varnish'])) {
346 21
            $this->loadVarnish($container, $loader, $config['varnish']);
347
        }
348 25
        if (isset($config['nginx'])) {
349 2
            $this->loadNginx($container, $loader, $config['nginx']);
350
        }
351 25
        if (isset($config['symfony'])) {
352 2
            $this->loadSymfony($container, $loader, $config['symfony']);
353
        }
354 25
        if (isset($config['noop'])) {
355 1
            $loader->load('noop.xml');
356
        }
357
358 25
        $container->setAlias(
359 25
            'fos_http_cache.default_proxy_client',
360 25
            'fos_http_cache.proxy_client.'.$this->getDefaultProxyClient($config)
361
        );
362 25
        $container->setAlias(
363 25
            ProxyClient::class,
364 25
            'fos_http_cache.default_proxy_client'
365
        );
366 25
    }
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 24
    private function createHttpDispatcherDefinition(ContainerBuilder $container, array $config, $serviceName)
376
    {
377 24
        foreach ($config['servers'] as $url) {
378 24
            $this->validateUrl($url, 'Not a valid Varnish server address: "%s"');
379
        }
380 24
        if (!empty($config['base_url'])) {
381 24
            $baseUrl = $this->prefixSchema($config['base_url']);
382 24
            $this->validateUrl($baseUrl, 'Not a valid base path: "%s"');
383
        } else {
384
            $baseUrl = null;
385
        }
386 23
        $httpClient = null;
387 23
        if ($config['http_client']) {
388 1
            $httpClient = new Reference($config['http_client']);
389
        }
390
391 23
        $definition = new Definition(HttpDispatcher::class, [
392 23
            $config['servers'],
393 23
            $baseUrl,
394 23
            $httpClient,
395
        ]);
396
397 23
        $container->setDefinition($serviceName, $definition);
398 23
    }
399
400 21
    private function loadVarnish(ContainerBuilder $container, XmlFileLoader $loader, array $config)
401
    {
402 21
        $this->createHttpDispatcherDefinition($container, $config['http'], 'fos_http_cache.proxy_client.varnish.http_dispatcher');
403
        $options = [
404 20
            'tag_mode' => $config['tag_mode'],
405 20
            'tags_header' => $config['tags_header'],
406
        ];
407
408 20
        if (!empty($config['header_length'])) {
409
            $options['header_length'] = $config['header_length'];
410
        }
411 20
        if (!empty($config['default_ban_headers'])) {
412
            $options['default_ban_headers'] = $config['default_ban_headers'];
413
        }
414 20
        $container->setParameter('fos_http_cache.proxy_client.varnish.options', $options);
415
416 20
        $loader->load('varnish.xml');
417 20
    }
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 26
    private function loadCacheTagging(ContainerBuilder $container, XmlFileLoader $loader, array $config, $client)
462
    {
463 26
        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 23
        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 22
        $container->setParameter('fos_http_cache.compiler_pass.tag_annotations', true);
473 22
        $container->setParameter('fos_http_cache.tag_handler.response_header', $config['response_header']);
474 22
        $container->setParameter('fos_http_cache.tag_handler.separator', $config['separator']);
475 22
        $container->setParameter('fos_http_cache.tag_handler.strict', $config['strict']);
476
477 22
        $loader->load('cache_tagging.xml');
478 22
        if (class_exists(Application::class)) {
479 22
            $loader->load('cache_tagging_commands.xml');
480
        }
481
482 22
        if (!empty($config['expression_language'])) {
483
            $container->setAlias(
484
                'fos_http_cache.tag_handler.expression_language',
485
                $config['expression_language']
486
            );
487
        }
488
489 22
        if (!empty($config['rules'])) {
490 3
            $this->loadTagRules($container, $config['rules']);
491
        }
492
493 22
        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 22
    }
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 24
    private function validateUrl($url, $msg)
575
    {
576 24
        $prefixed = $this->prefixSchema($url);
577
578 24
        if (!$parts = parse_url($prefixed)) {
579 1
            throw new InvalidConfigurationException(sprintf($msg, $url));
580
        }
581 24
    }
582
583 24
    private function prefixSchema($url)
584
    {
585 24
        if (false === strpos($url, '://')) {
586 24
            $url = sprintf('%s://%s', 'http', $url);
587
        }
588
589 24
        return $url;
590
    }
591
592 25
    private function getDefaultProxyClient(array $config)
593
    {
594 25
        if (isset($config['default'])) {
595
            return $config['default'];
596
        }
597
598 25
        if (isset($config['varnish'])) {
599 20
            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