Configuration::addTagSection()   B
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 51
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 59
ccs 51
cts 51
cp 1
rs 8.8945
c 0
b 0
f 0
cc 2
nc 1
nop 1
crap 2

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Varnish;
15
use FOS\HttpCache\SymfonyCache\PurgeListener;
16
use FOS\HttpCache\SymfonyCache\PurgeTagsListener;
17
use FOS\HttpCache\TagHeaderFormatter\TagHeaderFormatter;
18
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
19
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
20
use Symfony\Component\Config\Definition\Builder\NodeDefinition;
21
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
22
use Symfony\Component\Config\Definition\ConfigurationInterface;
23
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
24
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
25
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
26
27
/**
28
 * This class contains the configuration information for the bundle.
29
 *
30
 * This information is solely responsible for how the different configuration
31
 * sections are normalized, and merged.
32
 *
33
 * @author David de Boer <[email protected]>
34
 * @author David Buchmann <[email protected]>
35
 */
36
class Configuration implements ConfigurationInterface
37
{
38
    /**
39
     * @var bool
40
     */
41
    private $debug;
42
43
    /**
44
     * @param bool $debug Whether to use the debug mode
45
     */
46 60
    public function __construct($debug)
47
    {
48 60
        $this->debug = $debug;
49 60
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54 60
    public function getConfigTreeBuilder()
55
    {
56 60
        $treeBuilder = new TreeBuilder('fos_http_cache');
57
58
        // Keep compatibility with symfony/config < 4.2
59 60
        if (!method_exists($treeBuilder, 'getRootNode')) {
60
            $rootNode = $treeBuilder->root('fos_http_cache');
0 ignored issues
show
Bug introduced by
The method root() does not seem to exist on object<Symfony\Component...on\Builder\TreeBuilder>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
61
        } else {
62 60
            $rootNode = $treeBuilder->getRootNode();
63
        }
64
65
        $rootNode
66 60
            ->validate()
67
                ->ifTrue(function ($v) {
68 58
                    return $v['cache_manager']['enabled']
69 58
                        && !isset($v['proxy_client'])
70 58
                        && !isset($v['cache_manager']['custom_proxy_client'])
71
                    ;
72 60
                })
73 View Code Duplication
                ->then(function ($v) {
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...
74 17
                    if ('auto' === $v['cache_manager']['enabled']) {
75 16
                        $v['cache_manager']['enabled'] = false;
76
77 16
                        return $v;
78
                    }
79
80 1
                    throw new InvalidConfigurationException('You need to configure a proxy_client or specify a custom_proxy_client to use the cache_manager.');
81 60
                })
82 60
            ->end()
83 60
            ->validate()
84
                ->ifTrue(function ($v) {
85 57
                    return $v['tags']['enabled'] && !$v['cache_manager']['enabled'];
86 60
                })
87 View Code Duplication
                ->then(function ($v) {
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...
88 18
                    if ('auto' === $v['tags']['enabled']) {
89 17
                        $v['tags']['enabled'] = false;
90
91 17
                        return $v;
92
                    }
93
94 1
                    throw new InvalidConfigurationException('You need to configure a proxy_client to get the cache_manager needed for tag handling.');
95 60
                })
96 60
            ->end()
97 60
            ->validate()
98
                ->ifTrue(function ($v) {
99 56
                    return $v['invalidation']['enabled'] && !$v['cache_manager']['enabled'];
100 60
                })
101 View Code Duplication
                ->then(function ($v) {
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...
102 17
                    if ('auto' === $v['invalidation']['enabled']) {
103 16
                        $v['invalidation']['enabled'] = false;
104
105 16
                        return $v;
106
                    }
107
108 1
                    throw new InvalidConfigurationException('You need to configure a proxy_client to get the cache_manager needed for invalidation handling.');
109 60
                })
110 60
            ->end()
111 60
            ->validate()
112 60
                ->ifTrue(
113
                    function ($v) {
114 55
                        return false !== $v['user_context']['logout_handler']['enabled'];
115 60
                    }
116
                )
117
                ->then(function ($v) {
118 54
                    if (isset($v['cache_manager']['custom_proxy_client'])) {
119 5
                        $v['user_context']['logout_handler']['enabled'] = true;
120
121 5
                        return $v;
122
                    }
123
124 49
                    if (isset($v['proxy_client']['default'])
125 49
                        && in_array($v['proxy_client']['default'], ['varnish', 'symfony', 'noop'])
126
                    ) {
127
                        $v['user_context']['logout_handler']['enabled'] = true;
128
129
                        return $v;
130
                    }
131 49
                    if (isset($v['proxy_client']['varnish'])
132 26
                        || isset($v['proxy_client']['symfony'])
133 49
                        || isset($v['proxy_client']['noop'])
134
                    ) {
135 28
                        $v['user_context']['logout_handler']['enabled'] = true;
136
137 28
                        return $v;
138
                    }
139
140 21
                    if ('auto' === $v['user_context']['logout_handler']['enabled']) {
141 19
                        $v['user_context']['logout_handler']['enabled'] = false;
142
143 19
                        return $v;
144
                    }
145
146 2
                    throw new InvalidConfigurationException('To enable the user context logout handler, you need to configure a tag capable proxy_client (varnish, symfony, noop or custom_proxy_client).');
147 60
                })
148 60
            ->end()
149
            // Determine the default tags header for the varnish client, depending on whether we use BAN or xkey
150 60
            ->validate()
151 60
                ->ifTrue(
152 View Code Duplication
                    function ($v) {
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...
153
                        return
154 53
                            array_key_exists('proxy_client', $v)
155 53
                            && array_key_exists('varnish', $v['proxy_client'])
156 53
                            && empty($v['proxy_client']['varnish']['tags_header'])
157
                        ;
158 60
                    }
159
                )
160
                ->then(function ($v) {
161 20
                    $v['proxy_client']['varnish']['tags_header'] =
162 20
                        (Varnish::TAG_XKEY === $v['proxy_client']['varnish']['tag_mode'])
163 1
                        ? Varnish::DEFAULT_HTTP_HEADER_CACHE_XKEY
164 19
                        : Varnish::DEFAULT_HTTP_HEADER_CACHE_TAGS;
165
166 20
                    return $v;
167 60
                })
168 60
            ->end()
169
            // Determine the default tag response header, depending on whether we use BAN or xkey
170 60
            ->validate()
171 60
                ->ifTrue(
172
                    function ($v) {
173 53
                        return empty($v['tags']['response_header']);
174 60
                    }
175
                )
176
                ->then(function ($v) {
177 49
                    $v['tags']['response_header'] = $this->isVarnishXkey($v) ? 'xkey' : TagHeaderFormatter::DEFAULT_HEADER_NAME;
178
179 49
                    return $v;
180 60
                })
181 60
            ->end()
182
            // Determine the default separator for the tags header, depending on whether we use BAN or xkey
183 60
            ->validate()
184 60
                ->ifTrue(
185
                    function ($v) {
186 53
                        return empty($v['tags']['separator']);
187 60
                    }
188
                )
189
                ->then(function ($v) {
190 50
                    $v['tags']['separator'] = $this->isVarnishXkey($v) ? ' ' : ',';
191
192 50
                    return $v;
193 60
                })
194
        ;
195
196 60
        $this->addCacheableResponseSection($rootNode);
197 60
        $this->addCacheControlSection($rootNode);
198 60
        $this->addProxyClientSection($rootNode);
199 60
        $this->addCacheManagerSection($rootNode);
200 60
        $this->addTagSection($rootNode);
201 60
        $this->addInvalidationSection($rootNode);
202 60
        $this->addUserContextListenerSection($rootNode);
203 60
        $this->addFlashMessageSection($rootNode);
204 60
        $this->addTestSection($rootNode);
205 60
        $this->addDebugSection($rootNode);
206
207 60
        return $treeBuilder;
208
    }
209
210 50 View Code Duplication
    private function isVarnishXkey(array $v): bool
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
211
    {
212 50
        return array_key_exists('proxy_client', $v)
213 50
            && array_key_exists('varnish', $v['proxy_client'])
214 50
            && Varnish::TAG_XKEY === $v['proxy_client']['varnish']['tag_mode']
215
        ;
216
    }
217
218 60
    private function addCacheableResponseSection(ArrayNodeDefinition $rootNode)
219
    {
220
        $rootNode
221 60
            ->children()
222 60
                ->arrayNode('cacheable')
223 60
                    ->addDefaultsIfNotSet()
224 60
                    ->children()
225 60
                        ->arrayNode('response')
226 60
                            ->addDefaultsIfNotSet()
227 60
                            ->children()
228 60
                                ->arrayNode('additional_status')
229 60
                                    ->prototype('scalar')->end()
230 60
                                    ->info('Additional response HTTP status codes that will be considered cacheable.')
231 60
                                ->end()
232 60
                                ->scalarNode('expression')
233 60
                                    ->defaultNull()
234 60
                                    ->info('Expression to decide whether response is cacheable. Replaces the default status codes.')
235 60
                            ->end()
236 60
                        ->end()
237
238 60
                        ->validate()
239
                            ->ifTrue(function ($v) {
240 6
                                return !empty($v['additional_status']) && !empty($v['expression']);
241 60
                            })
242 60
                            ->thenInvalid('You may not set both additional_status and expression.')
243 60
                            ->ifTrue(function ($v) {
244 60
                                return !empty($v['expression']) && !class_exists(ExpressionLanguage::class);
245 60
                            })
246 60
                            ->thenInvalid('Configured a response.expression but ExpressionLanguage is not available')
247 60
                        ->end()
248
                    ->end()
249
                ->end()
250
            ->end();
251
    }
252
253
    /**
254 60
     * Cache header control main section.
255
     */
256
    private function addCacheControlSection(ArrayNodeDefinition $rootNode)
257 60
    {
258 60
        $rules = $rootNode
259 60
            ->children()
260 60
                ->arrayNode('cache_control')
261 60
                    ->fixXmlConfig('rule')
262 60
                    ->children()
263 60
                        ->arrayNode('defaults')
264 60
                            ->addDefaultsIfNotSet()
265 60
                            ->children()
266 60
                                ->booleanNode('overwrite')
267 60
                                    ->info('Whether to overwrite existing cache headers')
268 60
                                    ->defaultFalse()
269 60
                                ->end()
270 60
                            ->end()
271 60
                        ->end()
272 60
                        ->arrayNode('rules')
273
                            ->prototype('array')
274 60
                                ->children();
275
276 60
        $this->addMatch($rules, true);
277 60
        $rules
278
            ->arrayNode('headers')
279 60
                ->isRequired()
280 60
                // todo validate there is some header defined
281 60
                ->children()
282 60
                    ->enumNode('overwrite')
283 60
                        ->info('Whether to overwrite cache headers for this rule, defaults to the cache_control.defaults.overwrite setting')
284 60
                        ->values(['default', true, false])
285 60
                        ->defaultValue('default')
286 60
                    ->end()
287 60
                    ->arrayNode('cache_control')
288 60
                        ->info('Add the specified cache control directives.')
289 60
                        ->children()
290 60
                            ->scalarNode('max_age')->end()
291 60
                            ->scalarNode('s_maxage')->end()
292 60
                            ->booleanNode('private')->end()
293 60
                            ->booleanNode('public')->end()
294 60
                            ->booleanNode('must_revalidate')->end()
295 60
                            ->booleanNode('proxy_revalidate')->end()
296 60
                            ->booleanNode('no_transform')->end()
297 60
                            ->booleanNode('no_cache')->end()
298 60
                            ->booleanNode('no_store')->end()
299 60
                            ->scalarNode('stale_if_error')->end()
300 60
                            ->scalarNode('stale_while_revalidate')->end()
301 60
                        ->end()
302 60
                    ->end()
303 60
                    ->enumNode('etag')
304 60
                        ->defaultValue(false)
305 60
                        ->treatTrueLike('strong')
306 60
                        ->info('Set a simple ETag which is just the md5 hash of the response body. '.
307 60
                               'You can specify which type of ETag you want by passing "strong" or "weak".')
308 60
                        ->values(['weak', 'strong', false])
309 60
                    ->end()
310
                    ->scalarNode('last_modified')
311 2
                        ->validate()
312 2
                            ->ifTrue(function ($v) {
313
                                if (is_string($v)) {
314
                                    new \DateTime($v);
315 1
                                }
316 60
317 60
                                return false;
318 60
                            })
319 60
                            ->thenInvalid('') // this will never happen as new DateTime will throw an exception if $v is no date
320 60
                        ->end()
321 60
                        ->info('Set a default last modified timestamp if none is set yet. Value must be parseable by DateTime')
322 60
                    ->end()
323 60
                    ->scalarNode('reverse_proxy_ttl')
324 60
                        ->defaultNull()
325 60
                        ->info('Specify an X-Reverse-Proxy-TTL header with a time in seconds for a caching proxy under your control.')
326
                    ->end()
327 2
                    ->arrayNode('vary')
328 60
                        ->beforeNormalization()->ifString()->then(function ($v) {
329 60
                            return preg_split('/\s*,\s*/', $v);
330 60
                        })->end()
331 60
                        ->prototype('scalar')->end()
332 60
                        ->info('Define a list of additional headers on which the response varies.')
333 60
                    ->end()
334
                ->end()
335 60
            ->end()
336
        ;
337
    }
338
339
    /**
340
     * Shared configuration between cache control, tags and invalidation.
341
     *
342
     * @param bool $matchResponse whether to also add fields to match response
343 60
     */
344
    private function addMatch(NodeBuilder $rules, $matchResponse = false)
345
    {
346 60
        $match = $rules
347 60
            ->arrayNode('match')
348 60
                ->cannotBeOverwritten()
349 60
                ->isRequired()
350 60
                ->fixXmlConfig('method')
351 60
                ->fixXmlConfig('ip')
352 60
                ->fixXmlConfig('attribute')
353
                ->validate()
354 14
                    ->ifTrue(function ($v) {
355 60
                        return !empty($v['additional_response_status']) && !empty($v['match_response']);
356 60
                    })
357 60
                    ->thenInvalid('You may not set both additional_response_status and match_response.')
358 60
                ->end()
359 60
                ->children()
360 60
                    ->scalarNode('path')
361 60
                        ->defaultNull()
362 60
                        ->info('Request path.')
363 60
                    ->end()
364 60
                    ->scalarNode('query_string')
365 60
                        ->defaultNull()
366 60
                        ->info('Request query string.')
367 60
                    ->end()
368 60
                    ->scalarNode('host')
369 60
                        ->defaultNull()
370 60
                        ->info('Request host name.')
371 60
                    ->end()
372
                    ->arrayNode('methods')
373 3
                        ->beforeNormalization()->ifString()->then(function ($v) {
374 60
                            return preg_split('/\s*,\s*/', $v);
375 60
                        })->end()
376 60
                        ->useAttributeAsKey('name')
377 60
                        ->prototype('scalar')->end()
378 60
                        ->info('Request HTTP methods.')
379 60
                    ->end()
380
                    ->arrayNode('ips')
381 3
                        ->beforeNormalization()->ifString()->then(function ($v) {
382 60
                            return preg_split('/\s*,\s*/', $v);
383 60
                        })->end()
384 60
                        ->useAttributeAsKey('name')
385 60
                        ->prototype('scalar')->end()
386 60
                        ->info('List of client IPs.')
387 60
                    ->end()
388 60
                    ->arrayNode('attributes')
389 60
                        ->useAttributeAsKey('name')
390 60
                        ->prototype('scalar')->end()
391 60
                        ->info('Regular expressions on request attributes.')
392
                    ->end()
393 60
        ;
394
        if ($matchResponse) {
395 60
            $match
396 60
                ->arrayNode('additional_response_status')
397 60
                    ->prototype('scalar')->end()
398 60
                    ->info('Additional response HTTP status codes that will match. Replaces cacheable configuration.')
399 60
                ->end()
400 60
                ->scalarNode('match_response')
401 60
                    ->defaultNull()
402 60
                    ->info('Expression to decide whether response should be matched. Replaces cacheable configuration.')
403
                ->end()
404
            ;
405 60
        }
406
    }
407 60
408
    private function addProxyClientSection(ArrayNodeDefinition $rootNode)
409
    {
410 60
        $rootNode
411 60
            ->children()
412 60
                ->arrayNode('proxy_client')
413 60
                    ->children()
414 60
                        ->enumNode('default')
415 60
                            ->values(['varnish', 'nginx', 'symfony', 'noop'])
416 60
                            ->info('If you configure more than one proxy client, you need to specify which client is the default.')
417 60
                        ->end()
418 60
                        ->arrayNode('varnish')
419 60
                            ->fixXmlConfig('default_ban_header')
420
                            ->validate()
421 24
                                ->always(function ($v) {
422 23
                                    if (!count($v['default_ban_headers'])) {
423
                                        unset($v['default_ban_headers']);
424
                                    }
425 24
426 60
                                    return $v;
427 60
                                })
428 60
                            ->end()
429 60
                            ->children()
430 60
                                ->scalarNode('tags_header')
431 60
                                    ->info('HTTP header to use when sending tag invalidation requests to Varnish')
432 60
                                ->end()
433 60
                                ->scalarNode('header_length')
434 60
                                    ->info('Maximum header length when invalidating tags. If there are more tags to invalidate than fit into the header, the invalidation request is split into several requests.')
435 60
                                ->end()
436 60
                                ->arrayNode('default_ban_headers')
437 60
                                    ->useAttributeAsKey('name')
438 60
                                    ->info('Map of additional headers to include in each ban request.')
439 60
                                    ->prototype('scalar')->end()
440 60
                                ->end()
441 60
                                ->enumNode('tag_mode')
442 60
                                    ->info('If you can enable the xkey module in Varnish, use the purgekeys mode for more efficient tag handling')
443 60
                                    ->values(['ban', 'purgekeys'])
444 60
                                    ->defaultValue('ban')
445 60
                                ->end()
446 60
                                ->append($this->getHttpDispatcherNode())
447 60
                            ->end()
448
                        ->end()
449 60
450 60
                        ->arrayNode('nginx')
451 60
                            ->children()
452 60
                                ->scalarNode('purge_location')
453 60
                                    ->defaultValue(false)
454 60
                                    ->info('Path to trigger the purge on Nginx for different location purge.')
455 60
                                ->end()
456 60
                                ->append($this->getHttpDispatcherNode())
457 60
                            ->end()
458
                        ->end()
459 60
460 60
                        ->arrayNode('symfony')
461 60
                            ->children()
462 60
                                ->scalarNode('tags_header')
463 60
                                    ->defaultValue(PurgeTagsListener::DEFAULT_TAGS_HEADER)
464 60
                                    ->info('HTTP header to use when sending tag invalidation requests to Symfony HttpCache')
465 60
                                ->end()
466 60
                                ->scalarNode('tags_method')
467 60
                                    ->defaultValue(PurgeTagsListener::DEFAULT_TAGS_METHOD)
468 60
                                    ->info('HTTP method for sending tag invalidation requests to Symfony HttpCache')
469 60
                                ->end()
470 60
                                ->scalarNode('header_length')
471 60
                                    ->info('Maximum header length when invalidating tags. If there are more tags to invalidate than fit into the header, the invalidation request is split into several requests.')
472 60
                                ->end()
473 60
                                ->scalarNode('purge_method')
474 60
                                    ->defaultValue(PurgeListener::DEFAULT_PURGE_METHOD)
475 60
                                    ->info('HTTP method to use when sending purge requests to Symfony HttpCache')
476 60
                                ->end()
477 60
                                ->booleanNode('use_kernel_dispatcher')
478 60
                                    ->defaultFalse()
479 60
                                    ->info('Dispatches invalidation requests to the kernel directly instead of executing real HTTP requests. Requires special kernel setup! Refer to the documentation for more information.')
480 60
                                ->end()
481 60
                                ->append($this->getHttpDispatcherNode())
482 60
                            ->end()
483
                        ->end()
484 60
485 60
                        ->booleanNode('noop')->end()
486 60
                    ->end()
487 60
                    ->validate()
488
                        ->always()
489 36
                        ->then(function ($config) {
490 36
                            foreach ($config as $proxyName => $proxyConfig) {
491
                                $serversConfigured = isset($proxyConfig['http']) && isset($proxyConfig['http']['servers']) && \is_array($proxyConfig['http']['servers']);
492 36
493 29
                                if (!\in_array($proxyName, ['noop', 'default', 'symfony'])) {
494
                                    if (!$serversConfigured) {
495
                                        throw new \InvalidArgumentException(sprintf('The "http.servers" section must be defined for the proxy "%s"', $proxyName));
496
                                    }
497 29
498
                                    return $config;
499
                                }
500 7
501 4
                                if ('symfony' === $proxyName) {
502 1
                                    if (!$serversConfigured && false === $proxyConfig['use_kernel_dispatcher']) {
503
                                        throw new \InvalidArgumentException('Either configure the "http.servers" section or enable "proxy_client.symfony.use_kernel_dispatcher"');
504
                                    }
505
                                }
506
                            }
507 6
508 60
                            return $config;
509 60
                        })
510 60
                    ->end()
511 60
                ->end()
512 60
            ->end();
513
    }
514
515
    /**
516
     * Get the configuration node for a HTTP dispatcher in a proxy client.
517
     *
518
     * @return NodeDefinition
519 60
     */
520
    private function getHttpDispatcherNode()
521 60
    {
522
        $treeBuilder = new TreeBuilder('http');
523
524 60
        // Keep compatibility with symfony/config < 4.2
525
        if (!method_exists($treeBuilder, 'getRootNode')) {
526
            $node = $treeBuilder->root('http');
0 ignored issues
show
Bug introduced by
The method root() does not seem to exist on object<Symfony\Component...on\Builder\TreeBuilder>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
527 60
        } else {
528
            $node = $treeBuilder->getRootNode();
529
        }
530
531 60
        $node
532 60
            ->fixXmlConfig('server')
533 60
            ->children()
534 60
                ->arrayNode('servers')
535 60
                    ->info('Addresses of the hosts the caching proxy is running on. May be hostname or ip, and with :port if not the default port 80.')
536 60
                    ->useAttributeAsKey('name')
537 60
                    ->isRequired()
538 60
                    ->requiresAtLeastOneElement()
539 60
                    ->prototype('scalar')->end()
540 60
                ->end()
541 60
                ->scalarNode('base_url')
542 60
                    ->defaultNull()
543 60
                    ->info('Default host name and optional path for path based invalidation.')
544 60
                ->end()
545 60
                ->scalarNode('http_client')
546 60
                    ->defaultNull()
547 60
                    ->info('Httplug async client service name to use for sending the requests.')
548 60
                ->end()
549
            ->end()
550
        ;
551 60
552
        return $node;
553
    }
554 60
555
    private function addTestSection(ArrayNodeDefinition $rootNode)
556
    {
557 60
        $rootNode
558 60
            ->children()
559 60
                ->arrayNode('test')
560 60
                    ->children()
561 60
                        ->scalarNode('cache_header')
562 60
                            ->defaultValue('X-Cache')
563 60
                            ->info('HTTP cache hit/miss header')
564 60
                        ->end()
565 60
                        ->arrayNode('proxy_server')
566 60
                            ->info('Configure how caching proxy will be run in your tests')
567 60
                            ->children()
568 60
                                ->enumNode('default')
569 60
                                    ->values(['varnish', 'nginx'])
570 60
                                    ->info('If you configure more than one proxy server, specify which client is the default.')
571 60
                                ->end()
572 60
                                ->arrayNode('varnish')
573 60
                                    ->children()
574 60
                                        ->scalarNode('config_file')->isRequired()->end()
575 60
                                        ->scalarNode('binary')->defaultValue('varnishd')->end()
576 60
                                        ->integerNode('port')->defaultValue(6181)->end()
577 60
                                        ->scalarNode('ip')->defaultValue('127.0.0.1')->end()
578 60
                                    ->end()
579 60
                                ->end()
580 60
                                ->arrayNode('nginx')
581 60
                                    ->children()
582 60
                                        ->scalarNode('config_file')->isRequired()->end()
583 60
                                        ->scalarNode('binary')->defaultValue('nginx')->end()
584 60
                                        ->integerNode('port')->defaultValue(8080)->end()
585 60
                                        ->scalarNode('ip')->defaultValue('127.0.0.1')->end()
586 60
                                    ->end()
587 60
                                ->end()
588 60
                            ->end()
589 60
                        ->end()
590 60
                    ->end()
591 60
                ->end()
592 60
            ->end();
593
    }
594
595
    /**
596
     * Cache manager main section.
597
     */
598
    private function addCacheManagerSection(ArrayNodeDefinition $rootNode)
599 60
    {
600
        $rootNode
601
            ->children()
602 60
                ->arrayNode('cache_manager')
603 60
                    ->addDefaultsIfNotSet()
604 60
                    ->beforeNormalization()
605 60
                        ->ifArray()
606 60
                        ->then(function ($v) {
607
                            $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true;
608 10
609
                            return $v;
610 10
                        })
611 60
                    ->end()
612 60
                    ->info('Configure the cache manager. Needs a proxy_client to be configured.')
613 60
                    ->children()
614 60
                        ->enumNode('enabled')
615 60
                            ->values([true, false, 'auto'])
616 60
                            ->defaultValue('auto')
617 60
                            ->info('Allows to disable the invalidation manager. Enabled by default if you configure a proxy client.')
618 60
                        ->end()
619 60
                        ->scalarNode('custom_proxy_client')
620 60
                            ->info('Service name of a custom proxy client to use. With a custom client, generate_url_type defaults to ABSOLUTE_URL and tag support needs to be explicitly enabled. If no custom proxy client is specified, the first proxy client you configured is used.')
621 60
                            ->cannotBeEmpty()
622 60
                        ->end()
623 60
                        ->enumNode('generate_url_type')
624 60
                            ->values([
625 60
                                'auto',
626 60
                                UrlGeneratorInterface::ABSOLUTE_PATH,
627
                                UrlGeneratorInterface::ABSOLUTE_URL,
628
                                UrlGeneratorInterface::NETWORK_PATH,
629
                                UrlGeneratorInterface::RELATIVE_PATH,
630
                            ])
631
                            ->defaultValue('auto')
632 60
                            ->info('Set what URLs to generate on invalidate/refresh Route. Auto means path if base_url is set on the default proxy client, full URL otherwise.')
633 60
                        ->end()
634 60
                    ->end()
635 60
        ;
636
    }
637 60
638
    private function addTagSection(ArrayNodeDefinition $rootNode)
639 60
    {
640
        $rules = $rootNode
641
            ->children()
642 60
                ->arrayNode('tags')
643 60
                    ->addDefaultsIfNotSet()
644 60
                    ->fixXmlConfig('rule')
645 60
                    ->children()
646 60
                        ->enumNode('enabled')
647 60
                            ->values([true, false, 'auto'])
648 60
                            ->defaultValue('auto')
649 60
                            ->info('Allows to disable tag support. Enabled by default if you configured the cache manager and have a proxy client that supports tagging.')
650 60
                        ->end()
651 60
                        ->arrayNode('annotations')
652 60
                            ->info('Annotations require the FrameworkExtraBundle. Because we can not detect whether annotations are used when the FrameworkExtraBundle is not available, this option must be set to false explicitly if the application does not use annotations.')
653 60
                            ->canBeDisabled()
654 60
                        ->end()
655 60
                        ->booleanNode('strict')->defaultFalse()->end()
656 60
                        ->scalarNode('expression_language')
657 60
                            ->defaultNull()
658 60
                            ->info('Service name of a custom ExpressionLanugage to use.')
659 60
                        ->end()
660 60
                        ->scalarNode('response_header')
661 60
                            ->defaultNull()
662 60
                            ->info('HTTP header that contains cache tags. Defaults to xkey-softpurge for Varnish xkey or X-Cache-Tags otherwise')
663 60
                        ->end()
664 60
                        ->scalarNode('separator')
665 60
                            ->defaultNull()
666 60
                            ->info('Character(s) to use to separate multiple tags. Defaults to " " for Varnish xkey or "," otherwise')
667 60
                        ->end()
668 60
                        ->scalarNode('max_header_value_length')
669 60
                            ->defaultNull()
670 60
                            ->info('If configured the tag header value will be split into multiple response headers of the same name (see "response_header" configuration key) that all do not exceed the configured "max_header_value_length" (recommended is 4KB = 4096) - configure in bytes.')
671 60
                        ->end()
672 60
                        ->arrayNode('rules')
673 60
                            ->prototype('array')
674 60
                                ->fixXmlConfig('tag')
675 60
                                ->fixXmlConfig('tag_expression')
676 60
                                ->validate()
677 60
                                    ->ifTrue(function ($v) {
678
                                        return !empty($v['tag_expressions']) && !class_exists(ExpressionLanguage::class);
679 4
                                    })
680 60
                                    ->thenInvalid('Configured a tag_expression but ExpressionLanugage is not available')
681 60
                                ->end()
682 60
                                ->children()
683 60
                        ;
684
        $this->addMatch($rules);
685 60
686
        $rules
687
            ->arrayNode('tags')
688 60
                ->prototype('scalar')
689 60
                ->info('Tags to add to the response on safe requests, to invalidate on unsafe requests')
690 60
            ->end()->end()
691 60
            ->arrayNode('tag_expressions')
692 60
                ->prototype('scalar')
693 60
                ->info('Tags to add to the response on safe requests, to invalidate on unsafe requests')
694 60
            ->end()
695 60
        ;
696
    }
697 60
698
    private function addInvalidationSection(ArrayNodeDefinition $rootNode)
699 60
    {
700
        $rules = $rootNode
701
            ->children()
702 60
                ->arrayNode('invalidation')
703 60
                    ->fixXmlConfig('rule')
704 60
                    ->addDefaultsIfNotSet()
705 60
                    ->children()
706 60
                        ->enumNode('enabled')
707 60
                            ->values([true, false, 'auto'])
708 60
                            ->defaultValue('auto')
709 60
                            ->info('Allows to disable the listener for invalidation. Enabled by default if the cache manager is configured. When disabled, the cache manager is no longer flushed automatically.')
710 60
                        ->end()
711 60
                        ->scalarNode('expression_language')
712 60
                            ->defaultNull()
713 60
                            ->info('Service name of a custom ExpressionLanugage to use.')
714 60
                        ->end()
715 60
                        ->arrayNode('rules')
716 60
                            ->info('Set what requests should invalidate which target routes.')
717 60
                            ->prototype('array')
718 60
                                ->fixXmlConfig('route')
719 60
                                ->children();
720 60
721
        $this->addMatch($rules);
722 60
        $rules
723
            ->arrayNode('routes')
724 60
                ->isRequired()
725 60
                ->requiresAtLeastOneElement()
726 60
                ->useAttributeAsKey('name')
727 60
                ->info('Target routes to invalidate when request is matched')
728 60
                ->prototype('array')
729 60
                    ->children()
730 60
                        ->booleanNode('ignore_extra_params')->defaultTrue()->end()
731 60
                    ->end()
732 60
                ->end()
733 60
            ->end();
734 60
    }
735 60
736
    /**
737
     * User context main section.
738
     */
739
    private function addUserContextListenerSection(ArrayNodeDefinition $rootNode)
740
    {
741
        $rootNode
742 60
            ->children()
743
                ->arrayNode('user_context')
744
                    ->info('Listener that returns the request for the user context hash as early as possible.')
745 60
                    ->addDefaultsIfNotSet()
746 60
                    ->canBeEnabled()
747 60
                    ->fixXmlConfig('user_identifier_header')
748 60
                    ->children()
749 60
                        ->arrayNode('match')
750 60
                            ->addDefaultsIfNotSet()
751 60
                            ->children()
752 60
                                ->scalarNode('matcher_service')
753 60
                                    ->defaultValue('fos_http_cache.user_context.request_matcher')
754 60
                                    ->info('Service id of a request matcher that tells whether the request is a context hash request.')
755 60
                                ->end()
756 60
                                ->scalarNode('accept')
757 60
                                    ->defaultValue('application/vnd.fos.user-context-hash')
758 60
                                    ->info('Specify the accept HTTP header used for context hash requests.')
759 60
                                ->end()
760 60
                                ->scalarNode('method')
761 60
                                    ->defaultNull()
762 60
                                    ->info('Specify the HTTP method used for context hash requests.')
763 60
                                ->end()
764 60
                            ->end()
765 60
                        ->end()
766 60
                        ->scalarNode('hash_cache_ttl')
767 60
                            ->defaultValue(0)
768 60
                            ->info('Cache the response for the hash for the specified number of seconds. Setting this to 0 will not cache those responses at all.')
769 60
                        ->end()
770 60
                        ->booleanNode('always_vary_on_context_hash')
771 60
                            ->defaultTrue()
772 60
                            ->info('Whether to always add the user context hash header name in the response Vary header.')
773 60
                        ->end()
774 60
                        ->arrayNode('user_identifier_headers')
775 60
                            ->prototype('scalar')->end()
776 60
                            ->defaultValue(['Cookie', 'Authorization'])
777 60
                            ->info('List of headers that contain the unique identifier for the user in the hash request.')
778 60
                        ->end()
779 60
                        ->scalarNode('session_name_prefix')
780 60
                            ->defaultValue(false)
781 60
                            ->info('Prefix for session cookies. Must match your PHP session configuration. Set to false to ignore the session in user context.')
782 60
                        ->end()
783 60
                        ->scalarNode('user_hash_header')
784 60
                            ->defaultValue('X-User-Context-Hash')
785 60
                            ->info('Name of the header that contains the hash information for the context.')
786 60
                        ->end()
787 60
                        ->booleanNode('role_provider')
788 60
                            ->defaultFalse()
789 60
                            ->info('Whether to enable a provider that automatically adds all roles of the current user to the context.')
790 60
                        ->end()
791 60
                        ->arrayNode('logout_handler')
792 60
                            ->addDefaultsIfNotSet()
793 60
                            ->canBeEnabled()
794 60
                            ->children()
795 60
                                ->enumNode('enabled')
796 60
                                    ->values([true, false, 'auto'])
797 60
                                    ->defaultValue('auto')
798 60
                                    ->info('Whether to enable the user context logout handler.')
799 60
                                ->end()
800 60
                            ->end()
801 60
                        ->end()
802 60
                    ->end()
803 60
                ->end()
804 60
            ->end()
805 60
        ;
806 60
    }
807 60
808
    private function addFlashMessageSection(ArrayNodeDefinition $rootNode)
809 60
    {
810
        $rootNode
811 60
            ->children()
812
                ->arrayNode('flash_message')
813
                    ->canBeUnset()
814 60
                    ->canBeEnabled()
815 60
                    ->info('Activate the flash message listener that puts flash messages into a cookie.')
816 60
                    ->children()
817 60
                        ->scalarNode('name')
818 60
                            ->defaultValue('flashes')
819 60
                            ->info('Name of the cookie to set for flashes.')
820 60
                        ->end()
821 60
                        ->scalarNode('path')
822 60
                            ->defaultValue('/')
823 60
                            ->info('Cookie path validity.')
824 60
                        ->end()
825 60
                        ->scalarNode('host')
826 60
                            ->defaultNull()
827 60
                            ->info('Cookie host name validity.')
828 60
                        ->end()
829 60
                        ->scalarNode('secure')
830 60
                            ->defaultFalse()
831 60
                            ->info('Whether the cookie should only be transmitted over a secure HTTPS connection from the client.')
832 60
                        ->end()
833 60
                    ->end()
834 60
                ->end()
835 60
            ->end();
836 60
    }
837 60
838 60
    private function addDebugSection(ArrayNodeDefinition $rootNode)
839 60
    {
840
        $rootNode
841 60
            ->children()
842
                ->arrayNode('debug')
843
                ->addDefaultsIfNotSet()
844 60
                ->canBeEnabled()
845 60
                ->children()
846 60
                    ->booleanNode('enabled')
847 60
                        ->defaultValue($this->debug)
848 60
                        ->info('Whether to send a debug header with the response to trigger a caching proxy to send debug information. If not set, defaults to kernel.debug.')
849 60
                    ->end()
850 60
                    ->scalarNode('header')
851 60
                        ->defaultValue('X-Cache-Debug')
852 60
                        ->info('The header to send if debug is true.')
853 60
                    ->end()
854 60
                ->end()
855 60
            ->end()
856 60
        ->end();
857 60
    }
858
}
859