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