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