-
Notifications
You must be signed in to change notification settings - Fork 84
Cleanup invalidation annotation #121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -181,6 +181,10 @@ private function addMatch(NodeBuilder $rules) | |
->ifTrue(function ($v) {return !empty($v['additional_cacheable_status']) && !empty($v['match_response']);}) | ||
->thenInvalid('You may not set both additional_cacheable_status and match_response.') | ||
->end() | ||
->validate() | ||
->ifTrue(function ($v) {return !empty($v['match_response']) && !class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage');}) | ||
->thenInvalid('Configured a match_response but ExpressionLanugage is not available') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks, fixed in 8597598 |
||
->end() | ||
->children() | ||
->scalarNode('path') | ||
->defaultNull() | ||
|
@@ -324,7 +328,7 @@ private function addTagSection(ArrayNodeDefinition $rootNode) | |
->enumNode('enabled') | ||
->values(array(true, false, 'auto')) | ||
->defaultValue('auto') | ||
->info('Allows to disable the listener for tag annotations when your project does not use the annotations. Enabled by default if you have expression language and the cache manager.') | ||
->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.') | ||
->end() | ||
->scalarNode('header') | ||
->defaultValue('X-Cache-Tags') | ||
|
@@ -334,6 +338,10 @@ private function addTagSection(ArrayNodeDefinition $rootNode) | |
->prototype('array') | ||
->fixXmlConfig('tag') | ||
->fixXmlConfig('tag_expression') | ||
->validate() | ||
->ifTrue(function ($v) {return !empty($v['tag_expressions']) && !class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage');}) | ||
->thenInvalid('Configured a tag_expression but ExpressionLanugage is not available') | ||
->end() | ||
->children(); | ||
|
||
$this->addMatch($rules); | ||
|
@@ -361,7 +369,7 @@ private function addInvalidationSection(ArrayNodeDefinition $rootNode) | |
->enumNode('enabled') | ||
->values(array(true, false, 'auto')) | ||
->defaultValue('auto') | ||
->info('Allows to disable the listener for invalidation annotations when your project does not use the annotations. Enabled by default if you have expression language and the cache manager.') | ||
->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.') | ||
->end() | ||
->arrayNode('rules') | ||
->info('Set what requests should invalidate which target routes.') | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,14 +64,9 @@ public function load(array $configs, ContainerBuilder $container) | |
|
||
if ($config['tags']['enabled']) { | ||
// true or auto | ||
if (class_exists('\Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { | ||
$loader->load('tag_listener.xml'); | ||
if (!empty($config['tags']['rules'])) { | ||
$this->loadTagRules($container, $config['tags']['rules']); | ||
} | ||
} elseif (true === $config['tags']['enabled']) { | ||
// silently skip if set to auto | ||
throw new InvalidConfigurationException('The TagSubscriber requires symfony/expression-language and needs the cache_manager to be configured'); | ||
$loader->load('tag_listener.xml'); | ||
if (!empty($config['tags']['rules'])) { | ||
$this->loadTagRules($container, $config['tags']['rules']); | ||
} | ||
|
||
$tagsHeader = $config['tags']['header']; | ||
|
@@ -81,15 +76,9 @@ public function load(array $configs, ContainerBuilder $container) | |
} | ||
|
||
if ($config['invalidation']['enabled']) { | ||
// true or auto | ||
if (class_exists('\Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { | ||
$loader->load('invalidation_listener.xml'); | ||
if (!empty($config['invalidation']['rules'])) { | ||
$this->loadInvalidatorRules($container, $config['invalidation']['rules']); | ||
} | ||
} elseif (true === $config['invalidation']['enabled']) { | ||
// silently skip if set to auto | ||
throw new InvalidConfigurationException('The InvalidationSubscriber requires symfony/expression-language and needs the cache_manager to be configured'); | ||
$loader->load('invalidation_listener.xml'); | ||
if (!empty($config['invalidation']['rules'])) { | ||
$this->loadInvalidatorRules($container, $config['invalidation']['rules']); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i noticed that the InvalidationSubscriber is the only one calling CacheManager::flush, so i guess we want that enabled whenver possible to reduce the WTF moments. now that we make expressions explicit, this should be fine - we only fail when people use expressions without having expression language. note that includes/enabled.rst is now not correct anymore. i suggest we also simplify the rules for the tag subscriber, it would also work without expressions now, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don’t think the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indeed. i copied the behaviour from InvalidationSubscriber now so it won't fail anymore. |
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,7 +47,7 @@ public function __construct( | |
ExpressionLanguage $expressionLanguage = null | ||
) { | ||
$this->cacheManager = $cacheManager; | ||
$this->expressionLanguage = $expressionLanguage ?: new ExpressionLanguage(); | ||
$this->expressionLanguage = $expressionLanguage; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moving into a getter that instantiates if needed. i validate the existence of expressionlanguage in the annoation class, so i think we never ever can have fatal errors anymore now, and can use everything without expressions properly. |
||
} | ||
|
||
/** | ||
|
@@ -146,10 +146,24 @@ private function getAnnotationTags(Request $request) | |
*/ | ||
private function evaluateTag($expression, Request $request) | ||
{ | ||
return $this->expressionLanguage->evaluate( | ||
return $this->getExpressionLanguage()->evaluate( | ||
$expression, | ||
$request->attributes->all() | ||
); | ||
} | ||
|
||
/** | ||
* Delay instantiating the expression language instance until we need it, | ||
* to support a setup with only symfony 2.3. | ||
* | ||
* @return ExpressionLanguage | ||
*/ | ||
private function getExpressionLanguage() | ||
{ | ||
if (!$this->expressionLanguage) { | ||
$this->expressionLanguage = new ExpressionLanguage(); | ||
} | ||
|
||
return $this->expressionLanguage; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,9 @@ actions are executed. | |
|
||
.. note:: | ||
|
||
Annotations need the SensioFrameworkExtraBundle. Some features also need | ||
the ExpressionLanguage. Make sure to | ||
Annotations need the SensioFrameworkExtraBundle including registering the | ||
Doctrine AnnotationsRegistry. Some features also need the | ||
ExpressionLanguage. Make sure to | ||
:ref:`installed the dependencies first <requirements>`. | ||
|
||
.. _invalidatepath: | ||
|
@@ -20,8 +21,8 @@ Invalidate a path:: | |
use FOS\HttpCacheBundle\Configuration\InvalidatePath; | ||
|
||
/** | ||
* @InvalidatePath("/posts") | ||
* @InvalidatePath("/posts/latest") | ||
* @InvalidatePath("/articles") | ||
* @InvalidatePath("/articles/latest") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. renamed all examples to use /articles rather than /posts to avoid any confusion with the http POST method (i was confused while jumping around in the doc for a sec, so thought for somebody new to all this, its better to use this name) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good one. |
||
*/ | ||
public function editAction() | ||
{ | ||
|
@@ -39,25 +40,25 @@ Invalidate a route with parameters:: | |
use FOS\HttpCacheBundle\Configuration\InvalidateRoute; | ||
|
||
/** | ||
* @InvalidateRoute("posts") | ||
* @InvalidateRoute("posts", params={"type" = "latest"}) | ||
* @InvalidateRoute("articles") | ||
* @InvalidateRoute("articles", params={"type" = "latest"}) | ||
*/ | ||
public function editAction() | ||
{ | ||
} | ||
|
||
You can also use expressions_ in the route parameter values:: | ||
You can also use expressions_ in the route parameter values. This obviously | ||
:ref:`requires the ExpressionLanguage component <requirements>`. To invalidate | ||
route ``articles`` with the ``number`` parameter set to ``123``, do:: | ||
|
||
/** | ||
* @InvalidateRoute("posts", params={"number" = "id"}) | ||
* @InvalidateRoute("articles", params={"number" = {"expression"="id"}}) | ||
*/ | ||
public function editAction(Request $request) | ||
public function editAction(Request $request, $id) | ||
{ | ||
// Assume $request->attributes->get('id') returns 123 | ||
} | ||
|
||
Route ``posts`` will now be invalidated with value ``123`` for param ``number``. | ||
|
||
See :doc:`/features/invalidation` for more information. | ||
|
||
.. _tag: | ||
|
@@ -106,8 +107,9 @@ If you prefer, you can combine tags in one annotation:: | |
* @Tag({"news", "news-list"}) | ||
*/ | ||
|
||
You can also use expressions_ in tags. This will set tag ``news-123`` on the | ||
response:: | ||
You can also use expressions_ in tags. This obviously | ||
:ref:`requires the ExpressionLanguage component <requirements>`. The following | ||
example sets the tag ``news-123`` on the Response:: | ||
|
||
/** | ||
* @Tag(expression="'news-'~id") | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the FOSHttpCacheBundle package. | ||
* | ||
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace FOS\HttpCacheBundle\Tests\Functional\EventListener; | ||
|
||
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; | ||
|
||
class InvalidationSubscriberTest extends WebTestCase | ||
{ | ||
public function testInvalidateRoute() | ||
{ | ||
$client = static::createClient(); | ||
|
||
$client->getContainer()->mock( | ||
'fos_http_cache.cache_manager', | ||
'\FOS\HttpCacheBundle\CacheManager' | ||
) | ||
->shouldReceive('invalidateRoute')->once()->with('test_noncached', array()) | ||
->shouldReceive('invalidateRoute')->once()->with('test_cached', array('id' => 'myhardcodedid')) | ||
->shouldReceive('invalidateRoute')->once()->with('tag_one', array('id' => '42')) | ||
->shouldReceive('flush')->once() | ||
; | ||
|
||
$client->request('POST', '/invalidate/route/42'); | ||
} | ||
|
||
public function testInvalidatePath() | ||
{ | ||
$client = static::createClient(); | ||
|
||
$client->getContainer()->mock( | ||
'fos_http_cache.cache_manager', | ||
'\FOS\HttpCacheBundle\CacheManager' | ||
) | ||
->shouldReceive('invalidatePath')->once()->with('/cached') | ||
->shouldReceive('flush')->once() | ||
; | ||
|
||
$client->request('POST', '/invalidate/path'); | ||
} | ||
|
||
public function testErrorIsNotInvalidated() | ||
{ | ||
$client = static::createClient(); | ||
|
||
$client->getContainer()->mock( | ||
'fos_http_cache.cache_manager', | ||
'\FOS\HttpCacheBundle\CacheManager' | ||
) | ||
->shouldReceive('invalidatePath')->never() | ||
->shouldReceive('flush')->once() | ||
; | ||
|
||
$client->request('POST', '/invalidate/error'); | ||
} | ||
|
||
protected function tearDown() | ||
{ | ||
static::createClient()->getContainer()->unmock('fos_http_cache.cache_manager'); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doing the validation early to notice problems as soon as possible