Completed
Pull Request — master (#319)
by David
06:22
created

Configuration::addInvalidationSection()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 33
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 37
ccs 33
cts 33
cp 1
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 34
nc 1
nop 1
crap 1
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 Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
15
use Symfony\Component\Config\Definition\Builder\NodeBuilder;
16
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
17
use Symfony\Component\Config\Definition\ConfigurationInterface;
18
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
19
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
20
21
/**
22
 * This class contains the configuration information for the bundle.
23
 *
24
 * This information is solely responsible for how the different configuration
25
 * sections are normalized, and merged.
26
 *
27
 * @author David de Boer <[email protected]>
28
 * @author David Buchmann <[email protected]>
29
 */
30
class Configuration implements ConfigurationInterface
31
{
32
    /**
33
     * @var bool
34
     */
35
    private $debug;
36
37
    /**
38
     * @param bool $debug Whether to use the debug mode
39
     */
40 33
    public function __construct($debug)
41
    {
42 33
        $this->debug = $debug;
43 33
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48 33
    public function getConfigTreeBuilder()
49
    {
50 33
        $treeBuilder = new TreeBuilder();
51 33
        $rootNode = $treeBuilder->root('fos_http_cache');
52
53
        $rootNode
54 33
            ->validate()
55
                ->ifTrue(function ($v) {
56 31
                    return $v['cache_manager']['enabled']
57 31
                        && !isset($v['proxy_client'])
58 31
                        && !isset($v['cache_manager']['custom_proxy_client'])
59
                    ;
60 33
                })
61
                ->then(function ($v) {
62 7
                    if ('auto' === $v['cache_manager']['enabled']) {
63 6
                        $v['cache_manager']['enabled'] = false;
64
65 6
                        return $v;
66
                    }
67 1
                    throw new InvalidConfigurationException('You need to configure a proxy_client or specify a custom_proxy_client to use the cache_manager.');
68 33
                })
69 33
            ->end()
70 33
            ->validate()
71
                ->ifTrue(function ($v) {
72 30
                    return $v['tags']['enabled'] && !$v['cache_manager']['enabled'];
73 33
                })
74
                ->then(function ($v) {
75 8
                    if ('auto' === $v['tags']['enabled']) {
76 7
                        $v['tags']['enabled'] = false;
77
78 7
                        return $v;
79
                    }
80 1
                    throw new InvalidConfigurationException('You need to configure a proxy_client to get the cache_manager needed for tag handling.');
81 33
                })
82 33
            ->end()
83 33
            ->validate()
84
                ->ifTrue(function ($v) {
85 29
                    return $v['invalidation']['enabled'] && !$v['cache_manager']['enabled'];
86 33
                })
87
                ->then(function ($v) {
88 7
                    if ('auto' === $v['invalidation']['enabled']) {
89 6
                        $v['invalidation']['enabled'] = false;
90
91 6
                        return $v;
92
                    }
93 1
                    throw new InvalidConfigurationException('You need to configure a proxy_client to get the cache_manager needed for invalidation handling.');
94 33
                })
95 33
            ->end()
96 33
            ->validate()
97 View Code Duplication
                ->ifTrue(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...
98 28
                    return isset($v['test'])
99 28
                        && $v['test']['client']['varnish']['enabled']
100 28
                        && !isset($v['proxy_client']['varnish']);
101 33
                })
102 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...
103
                    if ('auto' === $v['test']['client']['varnish']['enabled']) {
104
                        $v['test']['client']['varnish']['enabled'] = false;
105
106
                        return $v;
107
                    }
108
                    throw new InvalidConfigurationException('You need to configure the Varnish proxy_client to use the Varnish test client');
109 33
                })
110 33
            ->end()
111 33
            ->validate()
112 View Code Duplication
                ->ifTrue(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...
113 28
                    if (isset($v['test'])) {
114 1
                        return $v['test']['client']['nginx']['enabled'] && !isset($v['proxy_client']['nginx']);
115
                    }
116 33
                })
117 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...
118 1
                    if ('auto' === $v['test']['client']['nginx']['enabled']) {
119 1
                        $v['test']['client']['nginx']['enabled'] = false;
120
121 1
                        return $v;
122
                    }
123
                    throw new InvalidConfigurationException('You need to configure the Nginx proxy_client to use the Nginx test client');
124 33
                })
125 33
            ->end()
126 33
            ->validate()
127 33
                ->ifTrue(
128
                    function ($v) {
129 28
                        return $v['user_context']['logout_handler']['enabled']
130 28
                            && !isset($v['proxy_client']);
131 33
                    }
132
                )
133
                ->then(function ($v) {
134 8
                    if ('auto' === $v['user_context']['logout_handler']['enabled']) {
135 8
                        $v['user_context']['logout_handler']['enabled'] = false;
136
137 8
                        return $v;
138
                    }
139
                    throw new InvalidConfigurationException('You need to configure a proxy_client for the logout_handler.');
140 33
                })
141
        ;
142
143 33
        $this->addCacheControlSection($rootNode);
144 33
        $this->addProxyClientSection($rootNode);
145 33
        $this->addCacheManagerSection($rootNode);
146 33
        $this->addTagSection($rootNode);
147 33
        $this->addInvalidationSection($rootNode);
148 33
        $this->addUserContextListenerSection($rootNode);
149 33
        $this->addFlashMessageSection($rootNode);
150 33
        $this->addTestSection($rootNode);
151 33
        $this->addDebugSection($rootNode);
152
153 33
        return $treeBuilder;
154
    }
155
156
    /**
157
     * Cache header control main section.
158
     *
159
     * @param ArrayNodeDefinition $rootNode
160
     */
161 33
    private function addCacheControlSection(ArrayNodeDefinition $rootNode)
162
    {
163
        $rules = $rootNode
164 33
            ->children()
165 33
                ->arrayNode('cache_control')
166 33
                    ->fixXmlConfig('rule')
167 33
                    ->children()
168 33
                        ->arrayNode('defaults')
169 33
                            ->addDefaultsIfNotSet()
170 33
                            ->children()
171 33
                                ->booleanNode('overwrite')
172 33
                                    ->info('Whether to overwrite existing cache headers')
173 33
                                    ->defaultFalse()
174 33
                                ->end()
175 33
                            ->end()
176 33
                        ->end()
177 33
                        ->arrayNode('rules')
178 33
                            ->prototype('array')
179 33
                                ->children();
180
181 33
        $this->addMatch($rules);
182
        $rules
183 33
            ->arrayNode('headers')
184 33
                ->isRequired()
185
                // todo validate there is some header defined
186 33
                ->children()
187 33
                    ->enumNode('overwrite')
188 33
                        ->info('Whether to overwrite cache headers for this rule, defaults to the cache_control.defaults.overwrite setting')
189 33
                        ->values(array('default', true, false))
190 33
                        ->defaultValue('default')
191 33
                    ->end()
192 33
                    ->arrayNode('cache_control')
193 33
                        ->info('Add the specified cache control directives.')
194 33
                        ->children()
195 33
                            ->scalarNode('max_age')->end()
196 33
                            ->scalarNode('s_maxage')->end()
197 33
                            ->booleanNode('private')->end()
198 33
                            ->booleanNode('public')->end()
199 33
                            ->booleanNode('must_revalidate')->end()
200 33
                            ->booleanNode('proxy_revalidate')->end()
201 33
                            ->booleanNode('no_transform')->end()
202 33
                            ->booleanNode('no_cache')->end()
203 33
                            ->scalarNode('stale_if_error')->end()
204 33
                            ->scalarNode('stale_while_revalidate')->end()
205 33
                        ->end()
206 33
                    ->end()
207 33
                    ->scalarNode('etag')
208 33
                        ->defaultValue(false)
209 33
                        ->info('Set a simple ETag which is just the md5 hash of the response body')
210 33
                    ->end()
211 33
                    ->scalarNode('last_modified')
212 33
                        ->validate()
213
                            ->ifTrue(function ($v) {
214 2
                                if (is_string($v)) {
215 2
                                    new \DateTime($v);
216
                                }
217
218 1
                                return false;
219 33
                            })
220 33
                            ->thenInvalid('') // this will never happen as new DateTime will throw an exception if $v is no date
221 33
                        ->end()
222 33
                        ->info('Set a default last modified timestamp if none is set yet. Value must be parseable by DateTime')
223 33
                    ->end()
224 33
                    ->scalarNode('reverse_proxy_ttl')
225 33
                        ->defaultNull()
226 33
                        ->info('Specify an X-Reverse-Proxy-TTL header with a time in seconds for a caching proxy under your control.')
227 33
                    ->end()
228 33
                    ->arrayNode('vary')
229
                        ->beforeNormalization()->ifString()->then(function ($v) {
230 2
                            return preg_split('/\s*,\s*/', $v);
231 33
                        })->end()
232 33
                        ->prototype('scalar')->end()
233 33
                        ->info('Define a list of additional headers on which the response varies.')
234 33
                    ->end()
235 33
                ->end()
236 33
            ->end()
237
        ;
238 33
    }
239
240
    /**
241
     * Shared configuration between cache control, tags and invalidation.
242
     *
243
     * @param NodeBuilder $rules
244
     */
245 33
    private function addMatch(NodeBuilder $rules)
246
    {
247
        $rules
248 33
            ->arrayNode('match')
249 33
                ->cannotBeOverwritten()
250 33
                ->isRequired()
251 33
                ->fixXmlConfig('method')
252 33
                ->fixXmlConfig('ip')
253 33
                ->fixXmlConfig('attribute')
254 33
                ->validate()
255
                    ->ifTrue(function ($v) {
256 9
                        return !empty($v['additional_cacheable_status']) && !empty($v['match_response']);
257 33
                    })
258 33
                    ->thenInvalid('You may not set both additional_cacheable_status and match_response.')
259 33
                ->end()
260 33
                ->validate()
261
                    ->ifTrue(function ($v) {
262 8
                        return !empty($v['match_response']) && !class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage');
263 33
                    })
264 33
                    ->thenInvalid('Configured a match_response but ExpressionLanguage is not available')
265 33
                ->end()
266 33
                ->children()
267 33
                    ->scalarNode('path')
268 33
                        ->defaultNull()
269 33
                        ->info('Request path.')
270 33
                    ->end()
271 33
                    ->scalarNode('host')
272 33
                        ->defaultNull()
273 33
                        ->info('Request host name.')
274 33
                    ->end()
275 33
                    ->arrayNode('methods')
276
                        ->beforeNormalization()->ifString()->then(function ($v) {
277 3
                            return preg_split('/\s*,\s*/', $v);
278 33
                        })->end()
279 33
                        ->useAttributeAsKey('name')
280 33
                        ->prototype('scalar')->end()
281 33
                        ->info('Request HTTP methods.')
282 33
                    ->end()
283 33
                    ->arrayNode('ips')
284
                        ->beforeNormalization()->ifString()->then(function ($v) {
285 3
                            return preg_split('/\s*,\s*/', $v);
286 33
                        })->end()
287 33
                        ->useAttributeAsKey('name')
288 33
                        ->prototype('scalar')->end()
289 33
                        ->info('List of client IPs.')
290 33
                    ->end()
291 33
                    ->arrayNode('attributes')
292 33
                        ->useAttributeAsKey('name')
293 33
                        ->prototype('scalar')->end()
294 33
                        ->info('Regular expressions on request attributes.')
295 33
                    ->end()
296 33
                    ->arrayNode('additional_cacheable_status')
297 33
                        ->prototype('scalar')->end()
298 33
                        ->info('Additional response HTTP status codes that will match.')
299 33
                    ->end()
300 33
                    ->scalarNode('match_response')
301 33
                        ->defaultNull()
302 33
                        ->info('Expression to decide whether response should be matched. Replaces HTTP code check and additional_cacheable_status.')
303 33
                    ->end()
304 33
                ->end()
305 33
            ->end()
306
        ;
307 33
    }
308
309 33
    private function addProxyClientSection(ArrayNodeDefinition $rootNode)
310
    {
311
        $rootNode
312 33
            ->children()
313 33
                ->arrayNode('proxy_client')
314 33
                    ->children()
315 33
                        ->enumNode('default')
316 33
                            ->values(array('varnish', 'nginx', 'symfony'))
317 33
                            ->info('If you configure more than one proxy client, specify which client is the default.')
318 33
                        ->end()
319 33
                        ->arrayNode('varnish')
320 33
                            ->fixXmlConfig('server')
321 33
                            ->children()
322 33
                                ->arrayNode('servers')
323
                                    ->beforeNormalization()->ifString()->then(function ($v) {
324 3
                                        return preg_split('/\s*,\s*/', $v);
325 33
                                    })->end()
326 33
                                    ->useAttributeAsKey('name')
327 33
                                    ->isRequired()
328 33
                                    ->requiresAtLeastOneElement()
329 33
                                    ->prototype('scalar')->end()
330 33
                                    ->info('Addresses of the hosts Varnish is running on. May be hostname or ip, and with :port if not the default port 80.')
331 33
                                ->end()
332 33
                                ->scalarNode('base_url')
333 33
                                    ->defaultNull()
334 33
                                    ->info('Default host name and optional path for path based invalidation.')
335 33
                                ->end()
336 33
                                ->scalarNode('guzzle_client')
337 33
                                    ->defaultNull()
338 33
                                    ->info('Guzzle service to use for customizing the requests.')
339 33
                                ->end()
340 33
                            ->end()
341 33
                        ->end()
342
343 33
                        ->arrayNode('nginx')
344 33
                            ->fixXmlConfig('server')
345 33
                            ->children()
346 33
                                ->arrayNode('servers')
347
                                    ->beforeNormalization()->ifString()->then(function ($v) {
348 2
                                        return preg_split('/\s*,\s*/', $v);
349 33
                                    })->end()
350 33
                                    ->useAttributeAsKey('name')
351 33
                                    ->isRequired()
352 33
                                    ->requiresAtLeastOneElement()
353 33
                                    ->prototype('scalar')->end()
354 33
                                    ->info('Addresses of the hosts Nginx is running on. May be hostname or ip, and with :port if not the default port 80.')
355 33
                                ->end()
356 33
                                ->scalarNode('base_url')
357 33
                                    ->defaultNull()
358 33
                                    ->info('Default host name and optional path for path based invalidation.')
359 33
                                ->end()
360 33
                                ->scalarNode('guzzle_client')
361 33
                                    ->defaultNull()
362 33
                                    ->info('Guzzle service to use for customizing the requests.')
363 33
                                ->end()
364 33
                                ->scalarNode('purge_location')
365 33
                                    ->defaultValue('')
366 33
                                    ->info('Path to trigger the purge on Nginx for different location purge.')
367 33
                                ->end()
368 33
                            ->end()
369 33
                        ->end()
370
371 33
                        ->arrayNode('symfony')
372 33
                            ->fixXmlConfig('server')
373 33
                            ->children()
374 33
                                ->arrayNode('servers')
375
                                    ->beforeNormalization()->ifString()->then(function ($v) {
376 1
                                        return preg_split('/\s*,\s*/', $v);
377 33
                                    })->end()
378 33
                                    ->useAttributeAsKey('name')
379 33
                                    ->isRequired()
380 33
                                    ->requiresAtLeastOneElement()
381 33
                                    ->prototype('scalar')->end()
382 33
                                    ->info('Addresses of the hosts Symfony HttpCache is running on. May be hostname or ip, and with :port if not the default port 80.')
383 33
                                ->end()
384 33
                                ->scalarNode('base_url')
385 33
                                    ->defaultNull()
386 33
                                    ->info('Default host name and optional path for path based invalidation.')
387 33
                                ->end()
388 33
                                ->scalarNode('guzzle_client')
389 33
                                    ->defaultNull()
390 33
                                    ->info('Guzzle service to use for customizing the requests.')
391 33
                                ->end()
392 33
                            ->end()
393 33
                        ->end()
394
395 33
                    ->end()
396 33
                ->end()
397 33
            ->end();
398 33
    }
399
400 33
    private function addTestSection(ArrayNodeDefinition $rootNode)
401
    {
402
        $rootNode
403 33
            ->children()
404 33
                ->arrayNode('test')
405 33
                    ->children()
406 33
                        ->scalarNode('cache_header')
407 33
                            ->defaultValue('X-Cache')
408 33
                            ->info('HTTP cache hit/miss header')
409 33
                        ->end()
410 33
                        ->arrayNode('proxy_server')
411 33
                            ->info('Configure how caching proxy will be run in your tests')
412 33
                            ->children()
413 33
                                ->enumNode('default')
414 33
                                    ->values(array('varnish', 'nginx'))
415 33
                                    ->info('If you configure more than one proxy server, specify which client is the default.')
416 33
                                ->end()
417 33
                                ->arrayNode('varnish')
418 33
                                    ->children()
419 33
                                        ->scalarNode('config_file')->isRequired()->end()
420 33
                                        ->scalarNode('binary')->defaultValue('varnishd')->end()
421 33
                                        ->integerNode('port')->defaultValue(6181)->end()
422 33
                                        ->scalarNode('ip')->defaultValue('127.0.0.1')->end()
423 33
                                    ->end()
424 33
                                ->end()
425 33
                                ->arrayNode('nginx')
426 33
                                    ->children()
427 33
                                        ->scalarNode('config_file')->isRequired()->end()
428 33
                                        ->scalarNode('binary')->defaultValue('nginx')->end()
429 33
                                        ->integerNode('port')->defaultValue(8080)->end()
430 33
                                        ->scalarNode('ip')->defaultValue('127.0.0.1')->end()
431 33
                                    ->end()
432 33
                                ->end()
433 33
                            ->end()
434 33
                        ->end()
435 33
                        ->arrayNode('client')
436 33
                            ->addDefaultsIfNotSet()
437 33
                            ->children()
438 33
                                ->enumNode('default')
439 33
                                    ->values(array('varnish', 'nginx'))
440 33
                                    ->info('If you configure more than one proxy client, specify which client is the default.')
441 33
                                ->end()
442 33
                                ->arrayNode('varnish')
443 33
                                    ->addDefaultsIfNotSet()
444 33
                                    ->canBeEnabled()
445 33
                                    ->children()
446 33
                                        ->enumNode('enabled')
447 33
                                            ->values(array(true, false, 'auto'))
448 33
                                            ->defaultValue('auto')
449 33
                                            ->info('Whether to enable the Varnish test client.')
450 33
                                        ->end()
451 33
                                    ->end()
452 33
                                ->end()
453 33
                                ->arrayNode('nginx')
454 33
                                    ->addDefaultsIfNotSet()
455 33
                                    ->canBeEnabled()
456 33
                                    ->children()
457 33
                                        ->enumNode('enabled')
458 33
                                            ->values(array(true, false, 'auto'))
459 33
                                            ->defaultValue('auto')
460 33
                                            ->info('Whether to enable the Nginx test client.')
461 33
                                        ->end()
462 33
                                    ->end()
463 33
                                ->end()
464 33
                            ->end()
465 33
                        ->end()
466 33
                    ->end()
467 33
                ->end()
468 33
            ->end();
469 33
    }
470
471
    /**
472
     * Cache manager main section.
473
     *
474
     * @param ArrayNodeDefinition $rootNode
475
     */
476 33
    private function addCacheManagerSection(ArrayNodeDefinition $rootNode)
477
    {
478
        $rootNode
479 33
            ->children()
480 33
                ->arrayNode('cache_manager')
481 33
                    ->addDefaultsIfNotSet()
482 33
                    ->beforeNormalization()
483 33
                        ->ifArray()
484
                        ->then(function ($v) {
485 6
                            $v['enabled'] = isset($v['enabled']) ? $v['enabled'] : true;
486
487 6
                            return $v;
488 33
                        })
489 33
                    ->end()
490 33
                    ->info('Configure the cache manager. Needs a proxy_client to be configured.')
491 33
                    ->children()
492 33
                        ->enumNode('enabled')
493 33
                            ->values(array(true, false, 'auto'))
494 33
                            ->defaultValue('auto')
495 33
                            ->info('Allows to disable the invalidation manager. Enabled by default if you configure a proxy client.')
496 33
                        ->end()
497 33
                        ->scalarNode('custom_proxy_client')
498 33
                            ->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.')
499 33
                        ->end()
500 33
                        ->enumNode('generate_url_type')
501 33
                            ->values(array(
502 33
                                'auto',
503
                                UrlGeneratorInterface::ABSOLUTE_PATH,
504
                                UrlGeneratorInterface::ABSOLUTE_URL,
505
                                UrlGeneratorInterface::NETWORK_PATH,
506
                                UrlGeneratorInterface::RELATIVE_PATH,
507
                            ))
508 33
                            ->defaultValue('auto')
509 33
                            ->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.')
510 33
                        ->end()
511 33
                    ->end()
512
        ;
513 33
    }
514
515 33
    private function addTagSection(ArrayNodeDefinition $rootNode)
516
    {
517
        $rules = $rootNode
518 33
            ->children()
519 33
                ->arrayNode('tags')
520 33
                    ->addDefaultsIfNotSet()
521 33
                    ->fixXmlConfig('rule')
522 33
                    ->children()
523 33
                        ->enumNode('enabled')
524 33
                            ->values(array(true, false, 'auto'))
525 33
                            ->defaultValue('auto')
526 33
                            ->info('Allows to disable the event subscriber for tag configuration and annotations when your project does not use the annotations. Enabled by default if you configured the cache manager.')
527 33
                        ->end()
528 33
                        ->scalarNode('expression_language')
529 33
                            ->defaultNull()
530 33
                            ->info('Service name of a custom ExpressionLanugage to use.')
531 33
                        ->end()
532 33
                        ->scalarNode('header')
533 33
                            ->defaultValue('X-Cache-Tags')
534 33
                            ->info('HTTP header that contains cache tags')
535 33
                        ->end()
536 33
                        ->arrayNode('rules')
537 33
                            ->prototype('array')
538 33
                                ->fixXmlConfig('tag')
539 33
                                ->fixXmlConfig('tag_expression')
540 33
                                ->validate()
541 33
                                    ->ifTrue(function ($v) {
542 3
                                        return !empty($v['tag_expressions']) && !class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage');
543 33
                                    })
544 33
                                    ->thenInvalid('Configured a tag_expression but ExpressionLanugage is not available')
545 33
                                ->end()
546 33
                                ->children();
547
548 33
        $this->addMatch($rules);
549
550
        $rules
551 33
            ->arrayNode('tags')
552 33
                ->prototype('scalar')
553 33
                ->info('Tags to add to the response on safe requests, to invalidate on unsafe requests')
554 33
            ->end()->end()
555 33
            ->arrayNode('tag_expressions')
556 33
                ->prototype('scalar')
557 33
                ->info('Tags to add to the response on safe requests, to invalidate on unsafe requests')
558 33
            ->end()
559
        ;
560 33
    }
561
562 33
    private function addInvalidationSection(ArrayNodeDefinition $rootNode)
563
    {
564
        $rules = $rootNode
565 33
            ->children()
566 33
                ->arrayNode('invalidation')
567 33
                    ->fixXmlConfig('rule')
568 33
                    ->addDefaultsIfNotSet()
569 33
                    ->children()
570 33
                        ->enumNode('enabled')
571 33
                            ->values(array(true, false, 'auto'))
572 33
                            ->defaultValue('auto')
573 33
                            ->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.')
574 33
                        ->end()
575 33
                        ->scalarNode('expression_language')
576 33
                            ->defaultNull()
577 33
                            ->info('Service name of a custom ExpressionLanugage to use.')
578 33
                        ->end()
579 33
                        ->arrayNode('rules')
580 33
                            ->info('Set what requests should invalidate which target routes.')
581 33
                            ->prototype('array')
582 33
                                ->fixXmlConfig('route')
583 33
                                ->children();
584
585 33
        $this->addMatch($rules);
586
        $rules
587 33
            ->arrayNode('routes')
588 33
                ->isRequired()
589 33
                ->requiresAtLeastOneElement()
590 33
                ->useAttributeAsKey('name')
591 33
                ->info('Target routes to invalidate when request is matched')
592 33
                ->prototype('array')
593 33
                    ->children()
594 33
                        ->booleanNode('ignore_extra_params')->defaultTrue()->end()
595 33
                    ->end()
596 33
                ->end()
597 33
            ->end();
598 33
    }
599
600
    /**
601
     * User context main section.
602
     *
603
     * @param ArrayNodeDefinition $rootNode
604
     */
605 33
    private function addUserContextListenerSection(ArrayNodeDefinition $rootNode)
606
    {
607
        $rootNode
608 33
            ->children()
609 33
                ->arrayNode('user_context')
610 33
                    ->info('Listener that returns the request for the user context hash as early as possible.')
611 33
                    ->addDefaultsIfNotSet()
612 33
                    ->canBeEnabled()
613 33
                    ->fixXmlConfig('user_identifier_header')
614 33
                    ->children()
615 33
                        ->arrayNode('match')
616 33
                            ->addDefaultsIfNotSet()
617 33
                            ->children()
618 33
                                ->scalarNode('matcher_service')
619 33
                                    ->defaultValue('fos_http_cache.user_context.request_matcher')
620 33
                                    ->info('Service id of a request matcher that tells whether the request is a context hash request.')
621 33
                                ->end()
622 33
                                ->scalarNode('accept')
623 33
                                    ->defaultValue('application/vnd.fos.user-context-hash')
624 33
                                    ->info('Specify the accept HTTP header used for context hash requests.')
625 33
                                ->end()
626 33
                                ->scalarNode('method')
627 33
                                    ->defaultNull()
628 33
                                    ->info('Specify the HTTP method used for context hash requests.')
629 33
                                ->end()
630 33
                            ->end()
631 33
                        ->end()
632 33
                        ->scalarNode('hash_cache_ttl')
633 33
                            ->defaultValue(0)
634 33
                            ->info('Cache the response for the hash for the specified number of seconds. Setting this to 0 will not cache those responses at all.')
635 33
                        ->end()
636 33
                        ->booleanNode('always_vary_on_context_hash')
637 33
                            ->defaultTrue()
638 33
                            ->info('Whether to always add the user context hash header name in the response Vary header.')
639 33
                        ->end()
640 33
                        ->arrayNode('user_identifier_headers')
641 33
                            ->prototype('scalar')->end()
642 33
                            ->defaultValue(array('Cookie', 'Authorization'))
643 33
                            ->info('List of headers that contains the unique identifier for the user in the hash request.')
644 33
                        ->end()
645 33
                        ->scalarNode('user_hash_header')
646 33
                            ->defaultValue('X-User-Context-Hash')
647 33
                            ->info('Name of the header that contains the hash information for the context.')
648 33
                        ->end()
649 33
                        ->booleanNode('role_provider')
650 33
                            ->defaultFalse()
651 33
                            ->info('Whether to enable a provider that automatically adds all roles of the current user to the context.')
652 33
                        ->end()
653 33
                        ->arrayNode('logout_handler')
654 33
                            ->addDefaultsIfNotSet()
655 33
                            ->canBeEnabled()
656 33
                            ->children()
657 33
                                ->enumNode('enabled')
658 33
                                    ->values(array(true, false, 'auto'))
659 33
                                    ->defaultValue('auto')
660 33
                                    ->info('Whether to enable the user context logout handler.')
661 33
                                ->end()
662 33
                            ->end()
663 33
                        ->end()
664 33
                    ->end()
665 33
                ->end()
666 33
            ->end()
667
        ;
668 33
    }
669
670 33
    private function addFlashMessageSection(ArrayNodeDefinition $rootNode)
671
    {
672
        $rootNode
673 33
            ->children()
674 33
                ->arrayNode('flash_message')
675 33
                    ->canBeUnset()
676 33
                    ->canBeEnabled()
677 33
                    ->info('Activate the flash message listener that puts flash messages into a cookie.')
678 33
                    ->children()
679 33
                        ->scalarNode('name')
680 33
                            ->defaultValue('flashes')
681 33
                            ->info('Name of the cookie to set for flashes.')
682 33
                        ->end()
683 33
                        ->scalarNode('path')
684 33
                            ->defaultValue('/')
685 33
                            ->info('Cookie path validity.')
686 33
                        ->end()
687 33
                        ->scalarNode('host')
688 33
                            ->defaultNull()
689 33
                            ->info('Cookie host name validity.')
690 33
                        ->end()
691 33
                        ->scalarNode('secure')
692 33
                            ->defaultFalse()
693 33
                            ->info('Whether the cookie should only be transmitted over a secure HTTPS connection from the client.')
694 33
                        ->end()
695 33
                    ->end()
696 33
                ->end()
697 33
            ->end();
698 33
    }
699
700 33
    private function addDebugSection(ArrayNodeDefinition $rootNode)
701
    {
702
        $rootNode
703 33
            ->children()
704 33
                ->arrayNode('debug')
705 33
                ->addDefaultsIfNotSet()
706 33
                ->canBeEnabled()
707 33
                ->children()
708 33
                    ->booleanNode('enabled')
709 33
                        ->defaultValue($this->debug)
710 33
                        ->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.')
711 33
                    ->end()
712 33
                    ->scalarNode('header')
713 33
                        ->defaultValue('X-Cache-Debug')
714 33
                        ->info('The header to send if debug is true.')
715 33
                    ->end()
716 33
                ->end()
717 33
            ->end()
718 33
        ->end();
719 33
    }
720
}
721