FriendsOfSymfony /
FOSHttpCacheBundle
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /* |
||
| 4 | * This file is part of the FOSHttpCacheBundle package. |
||
| 5 | * |
||
| 6 | * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> |
||
| 7 | * |
||
| 8 | * For the full copyright and license information, please view the LICENSE |
||
| 9 | * file that was distributed with this source code. |
||
| 10 | */ |
||
| 11 | |||
| 12 | namespace FOS\HttpCacheBundle\DependencyInjection; |
||
| 13 | |||
| 14 | use 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 |
||
|
0 ignored issues
–
show
|
|||
| 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: