Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7d45767

Browse filesBrowse files
committed
bug #48509 [HttpKernel] Fix using entities with the #[Cache()] attribute (HypeMC)
This PR was merged into the 6.2 branch. Discussion ---------- [HttpKernel] Fix using entities with the `#[Cache()]` attribute | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #48506 | License | MIT | Doc PR | - The `#[Cache()]` attribute is suppose to be a replacement for the SensioFrameworkExtraBundle ``@Cache`` annotation, but unlike the annotation, it doesn't work when entities are used in expressions. The reason for it is that the `CacheAttributeListener` is triggered by a `kernel.controller` event, while the `EntityValueResolver` is called afterwards: https://github.com/symfony/symfony/blob/97f0ce875d87ef566bf533e34fc8419e36f84e6f/src/Symfony/Component/HttpKernel/HttpKernel.php#L150-L159 This PR attempts to solve this problem by changing the event of the `CacheAttributeListener` to `kernel.controller_arguments`. Even though this has a BC break the listener was introduced in 6.2 so it might still be early enough to make this change? In any case, I don't have a better idea how to fix this, so I'm open to suggestions. Commits ------- c69057b [HttpKernel] Fix using entities with the #[Cache()] attribute
2 parents 4cb2a86 + c69057b commit 7d45767
Copy full SHA for 7d45767

File tree

2 files changed

+64
-38
lines changed
Filter options

2 files changed

+64
-38
lines changed

‎src/Symfony/Component/HttpKernel/EventListener/CacheAttributeListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/EventListener/CacheAttributeListener.php
+5-5Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use Symfony\Component\HttpFoundation\Request;
1717
use Symfony\Component\HttpFoundation\Response;
1818
use Symfony\Component\HttpKernel\Attribute\Cache;
19-
use Symfony\Component\HttpKernel\Event\ControllerEvent;
19+
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
2020
use Symfony\Component\HttpKernel\Event\ResponseEvent;
2121
use Symfony\Component\HttpKernel\KernelEvents;
2222

@@ -47,7 +47,7 @@ public function __construct(
4747
/**
4848
* Handles HTTP validation headers.
4949
*/
50-
public function onKernelController(ControllerEvent $event)
50+
public function onKernelControllerArguments(ControllerArgumentsEvent $event)
5151
{
5252
$request = $event->getRequest();
5353

@@ -63,12 +63,12 @@ public function onKernelController(ControllerEvent $event)
6363
/** @var Cache[] $attributes */
6464
foreach ($attributes as $cache) {
6565
if (null !== $cache->lastModified) {
66-
$lastModified = $this->getExpressionLanguage()->evaluate($cache->lastModified, $request->attributes->all());
66+
$lastModified = $this->getExpressionLanguage()->evaluate($cache->lastModified, array_merge($request->attributes->all(), $event->getNamedArguments()));
6767
($response ??= new Response())->setLastModified($lastModified);
6868
}
6969

7070
if (null !== $cache->etag) {
71-
$etag = hash('sha256', $this->getExpressionLanguage()->evaluate($cache->etag, $request->attributes->all()));
71+
$etag = hash('sha256', $this->getExpressionLanguage()->evaluate($cache->etag, array_merge($request->attributes->all(), $event->getNamedArguments())));
7272
($response ??= new Response())->setEtag($etag);
7373
}
7474
}
@@ -169,7 +169,7 @@ public function onKernelResponse(ResponseEvent $event)
169169
public static function getSubscribedEvents(): array
170170
{
171171
return [
172-
KernelEvents::CONTROLLER => ['onKernelController', 10],
172+
KernelEvents::CONTROLLER_ARGUMENTS => ['onKernelControllerArguments', 10],
173173
KernelEvents::RESPONSE => ['onKernelResponse', -10],
174174
];
175175
}

‎src/Symfony/Component/HttpKernel/Tests/EventListener/CacheAttributeListenerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/Tests/EventListener/CacheAttributeListenerTest.php
+59-33Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use Symfony\Component\HttpFoundation\Request;
1717
use Symfony\Component\HttpFoundation\Response;
1818
use Symfony\Component\HttpKernel\Attribute\Cache;
19-
use Symfony\Component\HttpKernel\Event\ControllerEvent;
19+
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
2020
use Symfony\Component\HttpKernel\Event\ResponseEvent;
2121
use Symfony\Component\HttpKernel\EventListener\CacheAttributeListener;
2222
use Symfony\Component\HttpKernel\HttpKernelInterface;
@@ -170,35 +170,48 @@ public function testCacheMaxAgeSupportsStrtotimeFormat()
170170
$this->assertSame('86400', $this->response->headers->getCacheControlDirective('stale-if-error'));
171171
}
172172

173-
public function testLastModifiedNotModifiedResponse()
173+
/**
174+
* @testWith ["test.getDate()"]
175+
* ["date"]
176+
*/
177+
public function testLastModifiedNotModifiedResponse(string $expression)
174178
{
175-
$request = $this->createRequest(new Cache(lastModified: 'test.getDate()'));
176-
$request->attributes->set('test', new TestEntity());
179+
$entity = new TestEntity();
180+
181+
$request = $this->createRequest(new Cache(lastModified: $expression));
182+
$request->attributes->set('date', new \DateTimeImmutable('Fri, 23 Aug 2013 00:00:00 GMT'));
177183
$request->headers->add(['If-Modified-Since' => 'Fri, 23 Aug 2013 00:00:00 GMT']);
178184

179185
$listener = new CacheAttributeListener();
180-
$controllerEvent = new ControllerEvent($this->getKernel(), function () {
186+
$controllerArgumentsEvent = new ControllerArgumentsEvent($this->getKernel(), function (TestEntity $test) {
181187
return new Response();
182-
}, $request, null);
188+
}, [$entity], $request, null);
183189

184-
$listener->onKernelController($controllerEvent);
185-
$response = \call_user_func($controllerEvent->getController());
190+
$listener->onKernelControllerArguments($controllerArgumentsEvent);
191+
$response = $controllerArgumentsEvent->getController()($entity);
186192

187193
$this->assertSame(304, $response->getStatusCode());
188194
}
189195

190-
public function testLastModifiedHeader()
196+
/**
197+
* @testWith ["test.getDate()"]
198+
* ["date"]
199+
*/
200+
public function testLastModifiedHeader(string $expression)
191201
{
192-
$request = $this->createRequest(new Cache(lastModified: 'test.getDate()'));
193-
$request->attributes->set('test', new TestEntity());
202+
$entity = new TestEntity();
203+
204+
$request = $this->createRequest(new Cache(lastModified: $expression));
205+
$request->attributes->set('date', new \DateTimeImmutable('Fri, 23 Aug 2013 00:00:00 GMT'));
194206

195207
$listener = new CacheAttributeListener();
196-
$controllerEvent = new ControllerEvent($this->getKernel(), function () {
208+
$controllerArgumentsEvent = new ControllerArgumentsEvent($this->getKernel(), function (TestEntity $test) {
197209
return new Response();
198-
}, $request, null);
199-
$listener->onKernelController($controllerEvent);
210+
}, [$entity], $request, null);
211+
$listener->onKernelControllerArguments($controllerArgumentsEvent);
200212

201-
$responseEvent = new ResponseEvent($this->getKernel(), $request, HttpKernelInterface::MAIN_REQUEST, \call_user_func($controllerEvent->getController()));
213+
$controllerResponse = $controllerArgumentsEvent->getController()($entity);
214+
$responseEvent = new ResponseEvent($this->getKernel(), $request, HttpKernelInterface::MAIN_REQUEST, $controllerResponse);
202215
$listener->onKernelResponse($responseEvent);
203216

204217
$response = $responseEvent->getResponse();
@@ -208,35 +221,48 @@ public function testLastModifiedHeader()
208221
$this->assertSame('Fri, 23 Aug 2013 00:00:00 GMT', $response->headers->get('Last-Modified'));
209222
}
210223

211-
public function testEtagNotModifiedResponse()
224+
/**
225+
* @testWith ["test.getId()"]
226+
* ["id"]
227+
*/
228+
public function testEtagNotModifiedResponse(string $expression)
212229
{
213-
$request = $this->createRequest(new Cache(etag: 'test.getId()'));
214-
$request->attributes->set('test', $entity = new TestEntity());
230+
$entity = new TestEntity();
231+
232+
$request = $this->createRequest(new Cache(etag: $expression));
233+
$request->attributes->set('id', '12345');
215234
$request->headers->add(['If-None-Match' => sprintf('"%s"', hash('sha256', $entity->getId()))]);
216235

217236
$listener = new CacheAttributeListener();
218-
$controllerEvent = new ControllerEvent($this->getKernel(), function () {
237+
$controllerArgumentsEvent = new ControllerArgumentsEvent($this->getKernel(), function (TestEntity $test) {
219238
return new Response();
220-
}, $request, null);
239+
}, [$entity], $request, null);
221240

222-
$listener->onKernelController($controllerEvent);
223-
$response = \call_user_func($controllerEvent->getController());
241+
$listener->onKernelControllerArguments($controllerArgumentsEvent);
242+
$response = $controllerArgumentsEvent->getController()($entity);
224243

225244
$this->assertSame(304, $response->getStatusCode());
226245
}
227246

228-
public function testEtagHeader()
247+
/**
248+
* @testWith ["test.getId()"]
249+
* ["id"]
250+
*/
251+
public function testEtagHeader(string $expression)
229252
{
230-
$request = $this->createRequest(new Cache(etag: 'test.getId()'));
231-
$request->attributes->set('test', $entity = new TestEntity());
253+
$entity = new TestEntity();
254+
255+
$request = $this->createRequest(new Cache(etag: $expression));
256+
$request->attributes->set('id', '12345');
232257

233258
$listener = new CacheAttributeListener();
234-
$controllerEvent = new ControllerEvent($this->getKernel(), function () {
259+
$controllerArgumentsEvent = new ControllerArgumentsEvent($this->getKernel(), function (TestEntity $test) {
235260
return new Response();
236-
}, $request, null);
237-
$listener->onKernelController($controllerEvent);
261+
}, [$entity], $request, null);
262+
$listener->onKernelControllerArguments($controllerArgumentsEvent);
238263

239-
$responseEvent = new ResponseEvent($this->getKernel(), $request, HttpKernelInterface::MAIN_REQUEST, \call_user_func($controllerEvent->getController()));
264+
$controllerResponse = $controllerArgumentsEvent->getController()($entity);
265+
$responseEvent = new ResponseEvent($this->getKernel(), $request, HttpKernelInterface::MAIN_REQUEST, $controllerResponse);
240266
$listener->onKernelResponse($responseEvent);
241267

242268
$response = $responseEvent->getResponse();
@@ -280,8 +306,8 @@ public function testConfigurationDoesNotOverrideAlreadySetResponseHeaders()
280306
public function testAttribute()
281307
{
282308
$request = new Request();
283-
$event = new ControllerEvent($this->getKernel(), [new CacheAttributeController(), 'foo'], $request, null);
284-
$this->listener->onKernelController($event);
309+
$event = new ControllerArgumentsEvent($this->getKernel(), [new CacheAttributeController(), 'foo'], [], $request, null);
310+
$this->listener->onKernelControllerArguments($event);
285311

286312
$response = new Response();
287313
$event = new ResponseEvent($this->getKernel(), $request, HttpKernelInterface::MAIN_REQUEST, $response);
@@ -290,8 +316,8 @@ public function testAttribute()
290316
$this->assertSame(CacheAttributeController::METHOD_SMAXAGE, $response->getMaxAge());
291317

292318
$request = new Request();
293-
$event = new ControllerEvent($this->getKernel(), [new CacheAttributeController(), 'bar'], $request, null);
294-
$this->listener->onKernelController($event);
319+
$event = new ControllerArgumentsEvent($this->getKernel(), [new CacheAttributeController(), 'bar'], [], $request, null);
320+
$this->listener->onKernelControllerArguments($event);
295321

296322
$response = new Response();
297323
$event = new ResponseEvent($this->getKernel(), $request, HttpKernelInterface::MAIN_REQUEST, $response);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.