diff --git a/EventListener/TagSubscriber.php b/EventListener/TagSubscriber.php index b02d8f2d..9ac4b7c0 100644 --- a/EventListener/TagSubscriber.php +++ b/EventListener/TagSubscriber.php @@ -15,7 +15,6 @@ use FOS\HttpCacheBundle\Configuration\Tag; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; @@ -78,10 +77,7 @@ public function onKernelResponse(FilterResponseEvent $event) $tags[] = $tag; } foreach ($configuredTags['expressions'] as $expression) { - $tags[] = $this->expressionLanguage->evaluate($expression, array( - 'request' => $request, - 'response' => $response, - )); + $tags[] = $this->evaluateTag($expression, $request); } } @@ -98,6 +94,16 @@ public function onKernelResponse(FilterResponseEvent $event) } } + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + KernelEvents::RESPONSE => 'onKernelResponse' + ); + } + /** * Get the tags from the annotations on the controller that was used in the * request. @@ -118,9 +124,9 @@ private function getAnnotationTags(Request $request) $tags = array(); foreach ($tagConfigurations as $tagConfiguration) { if (null !== $tagConfiguration->getExpression()) { - $tags[] = $this->expressionLanguage->evaluate( + $tags[] = $this->evaluateTag( $tagConfiguration->getExpression(), - $request->attributes->all() + $request ); } else { $tags = array_merge($tags, $tagConfiguration->getTags()); @@ -131,12 +137,19 @@ private function getAnnotationTags(Request $request) } /** - * {@inheritdoc} + * Evaluate a tag that contains expressions + * + * @param string $expression + * @param Request $request + * + * @return string Evaluaated tag */ - public static function getSubscribedEvents() + private function evaluateTag($expression, Request $request) { - return array( - KernelEvents::RESPONSE => 'onKernelResponse' + return $this->expressionLanguage->evaluate( + $expression, + $request->attributes->all() ); } + } diff --git a/Resources/doc/reference/annotations.rst b/Resources/doc/reference/annotations.rst index 5e59f852..7854101f 100644 --- a/Resources/doc/reference/annotations.rst +++ b/Resources/doc/reference/annotations.rst @@ -114,7 +114,7 @@ response:: */ public function showAction($id) { - // Assume $id equals 123 + // Assume request parameter $id equals 123 } Or, using a `param converter`_:: diff --git a/Resources/doc/reference/configuration/tags.rst b/Resources/doc/reference/configuration/tags.rst index 5509239e..2b4a70e0 100644 --- a/Resources/doc/reference/configuration/tags.rst +++ b/Resources/doc/reference/configuration/tags.rst @@ -2,7 +2,8 @@ tags ==== Create tag rules in your application configuration to set tags on responses -and invalidate them. +and invalidate them. See the :doc:`tagging feature chapter ` +for an introduction. .. include:: /includes/enabled.rst @@ -40,6 +41,14 @@ invalidated instead. .. include:: /includes/match.rst +tags +^^^^ + +**type**: ``array`` + +Tags that should be set on responses to safe requests; or invalidated for +unsafe requests. + .. code-block:: yaml # app/config/config.yml @@ -51,14 +60,27 @@ invalidated instead. path: ^/news tags: [news-section] -.. note:: - - See further the :doc:`tagging feature description `. -tags -^^^^ +tag_expressions +~~~~~~~~~~~~~~~ **type**: ``array`` -Tags that should be set on responses to safe requests; or invalidated for -unsafe requests. +You can dynamically refer to request attributes using +:ref:`expressions `. Assume a route +``/articles/{id}``. A request to path ``/articles/123`` will set/invalidate +tag ``articles-123`` with the following configuration: + +.. code-block:: yaml + + # app/config/config.yml + fos_http_cache: + tags: + rules: + - + match: + path: ^/articles + tags: [articles] + tag_expressions: ["'article-'~id"] + +You can combine ``tags`` and ``tag_expression`` in one rule. diff --git a/Tests/Functional/EventListener/CacheControlSubscriberTest.php b/Tests/Functional/EventListener/CacheControlSubscriberTest.php index ea30cf6d..76e7b4da 100644 --- a/Tests/Functional/EventListener/CacheControlSubscriberTest.php +++ b/Tests/Functional/EventListener/CacheControlSubscriberTest.php @@ -19,7 +19,7 @@ public function testIsCached() { $client = static::createClient(); - $client->request('GET', '/cached'); + $client->request('GET', '/cached/42'); $response = $client->getResponse(); $this->assertEquals('public', $response->headers->get('Cache-Control')); } diff --git a/Tests/Functional/EventListener/TagSubscriberTest.php b/Tests/Functional/EventListener/TagSubscriberTest.php index 61fedb73..3b9b2f2b 100644 --- a/Tests/Functional/EventListener/TagSubscriberTest.php +++ b/Tests/Functional/EventListener/TagSubscriberTest.php @@ -63,9 +63,9 @@ public function testConfigurationTagsAreSet() { $client = static::createClient(); - $client->request('GET', '/cached'); + $client->request('GET', '/cached/51'); $response = $client->getResponse(); - $this->assertEquals('area', $response->headers->get('X-Cache-Tags')); + $this->assertEquals('area,area-51', $response->headers->get('X-Cache-Tags')); } public function testConfigurationTagsAreInvalidated() @@ -76,11 +76,11 @@ public function testConfigurationTagsAreInvalidated() 'fos_http_cache.cache_manager', '\FOS\HttpCacheBundle\CacheManager' ) - ->shouldReceive('invalidateTags')->once()->with(array('area')) + ->shouldReceive('invalidateTags')->once()->with(array('area', 'area-51')) ->shouldReceive('flush')->once() ; - $client->request('POST', '/cached'); + $client->request('PUT', '/cached/51'); } protected function tearDown() diff --git a/Tests/Functional/Fixtures/Controller/TestController.php b/Tests/Functional/Fixtures/Controller/TestController.php index d7e4e11f..c7961c79 100644 --- a/Tests/Functional/Fixtures/Controller/TestController.php +++ b/Tests/Functional/Fixtures/Controller/TestController.php @@ -47,8 +47,8 @@ public function errorAction() return new Response('Forbidden', 403); } - public function contentAction() + public function contentAction($id = null) { - return new Response('content'); + return new Response('content ' . $id); } } diff --git a/Tests/Functional/Fixtures/app/config/config.yml b/Tests/Functional/Fixtures/app/config/config.yml index 44f27141..b1db2386 100644 --- a/Tests/Functional/Fixtures/app/config/config.yml +++ b/Tests/Functional/Fixtures/app/config/config.yml @@ -23,6 +23,7 @@ fos_http_cache: match: path: ^/cached tags: [area] + tag_expressions: ["'area-'~id"] user_context: user_identifier_headers: - Cookie diff --git a/Tests/Functional/Fixtures/app/config/routing.yml b/Tests/Functional/Fixtures/app/config/routing.yml index ef12cdd3..d6afe783 100644 --- a/Tests/Functional/Fixtures/app/config/routing.yml +++ b/Tests/Functional/Fixtures/app/config/routing.yml @@ -1,24 +1,25 @@ test_list: - pattern: /test/list - defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::listAction } + pattern: /test/list + defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::listAction } methods: [GET] test_error: - pattern: /test/error - defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::errorAction } + pattern: /test/error + defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::errorAction } test_one: - pattern: /test/{id} - defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::itemAction } + pattern: /test/{id} + defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::itemAction } methods: [GET,POST] test_cached: - pattern: /cached - defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::contentAction } + pattern: /cached/{id} + defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::contentAction } + methods: [GET,PUT] test_noncached: pattern: /noncached - defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::contentAction } + defaults: { _controller: FOS\HttpCacheBundle\Tests\Functional\Fixtures\Controller\TestController::contentAction } test_logout: pattern: /secured_area/logout diff --git a/Tests/Unit/EventListener/TagSubscriberTest.php b/Tests/Unit/EventListener/TagSubscriberTest.php index e8188218..91683ac0 100644 --- a/Tests/Unit/EventListener/TagSubscriberTest.php +++ b/Tests/Unit/EventListener/TagSubscriberTest.php @@ -68,7 +68,7 @@ public function testOnKernelResponseGet() ; $this->listener->addRule($mockMatcher, array( 'tags' => array('configured-tag'), - 'expressions' => array('"item-" ~ request.attributes.get("id")'), + 'expressions' => array('"item-" ~ id'), )); $this->listener->onKernelResponse($event); @@ -123,7 +123,7 @@ public function testOnKernelResponsePost() ; $this->listener->addRule($mockMatcher, array( 'tags' => array('configured-tag'), - 'expressions' => array('"item-" ~ request.attributes.get("id")'), + 'expressions' => array('"item-" ~ id'), )); $this->listener->onKernelResponse($event); }