Skip to content

Commit c238a86

Browse files
committed
Replace getting route collection with route generation
The Symfony Router's getRouteCollection is not cached, so calling it causes the routes to be loaded. The UrlGenerator is cached, but it means we have to manually strip the query string that Symfony fills with parameters missing from the invalidated route.
1 parent cabf5eb commit c238a86

File tree

4 files changed

+45
-45
lines changed

4 files changed

+45
-45
lines changed

EventListener/InvalidationListener.php

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,14 @@ public function __construct(
5858
* Apply invalidators and flush cache manager
5959
*
6060
* On kernel.terminate:
61-
* - see if any invalidators apply to the current request and, if so, add their routes to the cache manager
62-
* - flush the cache manager in order to send invalidation requests to the HTTP cache.
61+
* - see if any invalidators apply to the current request and, if so, add
62+
* their routes to the cache manager
63+
* - flush the cache manager in order to send invalidation requests to the
64+
* HTTP cache.
6365
*
6466
* @param PostResponseEvent $event
67+
*
68+
* @return array Paths that were flushed from the invalidation queue
6569
*/
6670
public function onKernelTerminate(PostResponseEvent $event)
6771
{
@@ -78,34 +82,26 @@ public function onKernelTerminate(PostResponseEvent $event)
7882
return $this->cacheManager->flush();
7983
}
8084

81-
$invalidateRoutes = $this->invalidators->getInvalidatedRoutes($requestRoute);
82-
foreach ($invalidateRoutes as $route => $config) {
83-
$params = $this->getInvalidateRouteParameters($route, $request->attributes->get('_route_params'));
84-
$this->cacheManager->invalidateRoute($route, $params);
85-
}
85+
$requestParams = $request->attributes->get('_route_params');
86+
$invalidators = $this->invalidators->getInvalidators($requestRoute);
87+
foreach ($invalidators as $invalidator) {
88+
foreach ($invalidator->getInvalidatedRoutes() as $route => $config) {
89+
$path = $this->router->generate($route, $requestParams);
8690

87-
$this->cacheManager->flush();
88-
}
89-
90-
/**
91-
* Get route parameters for the route to invalidated based on current request parameters
92-
*
93-
* @param string $route Route name
94-
* @param array $parameters Request parameters
95-
*
96-
* @return array Parameters in the invalidate route that match current request parameters
97-
*/
98-
protected function getInvalidateRouteParameters($route, array $parameters)
99-
{
100-
// Which of the request parameters are also supported by the URL to be
101-
// generated?
102-
$invalidateRoute = $this->router->getRouteCollection()
103-
->get($route)
104-
->compile();
91+
// If extra route parameters should be ignored, strip the query
92+
// string generated by the Symfony router from the path
93+
if (isset($config['ignore_extra_params'])
94+
&& $config['ignore_extra_params']
95+
&& $pos = strpos($path, '?')
96+
) {
97+
$path = substr($path, 0, $pos);
98+
}
10599

106-
$supportedParams = \array_flip($invalidateRoute->getVariables());
100+
$this->cacheManager->invalidatePath($path);
101+
}
102+
}
107103

108-
return \array_intersect_key($parameters, $supportedParams);
104+
return $this->cacheManager->flush();
109105
}
110106

111107
/**

Invalidator/Invalidator.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ public function getInvalidatedRoutes()
5050
/**
5151
* {@inheritdoc}
5252
*/
53-
public function addInvalidatedRoute($route, $config = null)
53+
public function addInvalidatedRoute($route, array $config = array())
5454
{
55+
$defaultConfig = array(
56+
'ignore_extra_params' => true
57+
);
58+
$config = \array_merge($defaultConfig, $config);
5559
$this->invalidatedRoutes[$route] = $config;
5660

5761
return $this;

Invalidator/InvalidatorInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function getInvalidatorRoutes();
3737
*
3838
* @return InvalidatorInterface
3939
*/
40-
public function addInvalidatedRoute($route, $config);
40+
public function addInvalidatedRoute($route, array $config);
4141

4242
/**
4343
* Get routes that will be invalidated

Tests/EventListener/InvalidationListenerTest.php

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,16 @@
55
use Driebit\HttpCacheBundle\EventListener\InvalidationListener;
66
use Driebit\HttpCacheBundle\Invalidator\Invalidator;
77
use Driebit\HttpCacheBundle\Invalidator\InvalidatorCollection;
8-
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
98
use Symfony\Component\HttpFoundation\Request;
109
use Symfony\Component\HttpFoundation\Response;
1110
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
1211
use \Mockery;
13-
use Driebit\HttpCacheBundle\HttpCache\Varnish;
1412
use Symfony\Component\Routing\Route;
1513
use Symfony\Component\Routing\RouteCollection;
1614

1715
class InvalidationListenerTest extends \PHPUnit_Framework_TestCase
1816
{
19-
public function testNoRoutesInvalidedWhenResponseIsUnsuccessful()
17+
public function testNoRoutesInvalidatedWhenResponseIsUnsuccessful()
2018
{
2119
$cacheManager = \Mockery::mock('\Driebit\HttpCacheBundle\CacheManager')
2220
->shouldDeferMissing()
@@ -46,25 +44,27 @@ public function testNoRoutesInvalidedWhenResponseIsUnsuccessful()
4644

4745
public function testOnKernelTerminate()
4846
{
49-
$cacheManager = \Mockery::mock('\Driebit\HttpCacheBundle\CacheManager')
50-
->shouldReceive('invalidateRoute')
51-
->with('route_invalidated', array('id' => '123'))
52-
->shouldReceive('invalidateRoute')->with('route_invalidated_special', array('id' => '123', 'special' => 'bla'))
47+
$cacheManager = \Mockery::mock('\Driebit\HttpCacheBundle\CacheManager');
48+
$cacheManager->shouldReceive('invalidatePath')->with('/retrieve/something/123')
49+
->shouldReceive('invalidatePath')->with('/retrieve/something/123/bla')
5350
->shouldReceive('flush')->once()
5451
->getMock();
5552

5653
$routes = new RouteCollection();
57-
$route = new Route('/edit/something/{id}/{special}');
58-
$route2 = new Route('/retrieve/something/{id}');
59-
$route3 = new Route('/retrieve/something/{id}/{special}');
60-
$routes->add('route_invalidator', $route);
61-
$routes->add('route_invalidated', $route2);
62-
$routes->add('route_invalidated_special', $route3);
54+
$routes->add('route_invalidator', new Route('/edit/something/{id}/{special}'));
55+
$routes->add('route_invalidated', new Route('/retrieve/something/{id}'));
56+
$routes->add('route_invalidated_special', new Route('/retrieve/something/{id}/{special}'));
6357

58+
$requestParams = array('id' => 123, 'special' => 'bla');
6459
$router = \Mockery::mock('\Symfony\Component\Routing\Router')
6560
->shouldDeferMissing()
66-
->shouldReceive('getRouteCollection')
67-
->andReturn($routes)
61+
->shouldReceive('generate')
62+
->with('route_invalidated', $requestParams)
63+
->andReturn('/retrieve/something/123?special=bla')
64+
65+
->shouldReceive('generate')
66+
->with('route_invalidated_special', $requestParams)
67+
->andReturn('/retrieve/something/123/bla')
6868
->getMock();
6969

7070
$invalidator = new Invalidator();
@@ -79,7 +79,7 @@ public function testOnKernelTerminate()
7979

8080
$request = new Request();
8181
$request->attributes->set('_route', 'route_invalidator');
82-
$request->attributes->set('_route_params', array('id' => '123', 'special' => 'bla'));
82+
$request->attributes->set('_route_params', $requestParams);
8383

8484
$event = $this->getEvent($request);
8585
$listener->onKernelTerminate($event);

0 commit comments

Comments
 (0)