Skip to content

Commit 91bf04a

Browse files
Merge branch '7.4' into 8.0
* 7.4: Fix merge [HttpKernel] Make `#[Cache]` respect all explicit cache directives set in controller Revert "bug #62541 [DependencyInjection] Reset resolved state when setting a parameter (yoeunes)"
2 parents ad40489 + 7027650 commit 91bf04a

File tree

2 files changed

+45
-7
lines changed

2 files changed

+45
-7
lines changed

EventListener/CacheAttributeListener.php

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
1515
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
16+
use Symfony\Component\HttpFoundation\HeaderBag;
1617
use Symfony\Component\HttpFoundation\Request;
1718
use Symfony\Component\HttpFoundation\Response;
1819
use Symfony\Component\HttpKernel\Attribute\Cache;
@@ -122,29 +123,40 @@ public function onKernelResponse(ResponseEvent $event): void
122123
// Check if the response has a Vary header that should be considered, ignoring cases where
123124
// it's only 'Accept-Language' and the request has the '_vary_by_language' attribute
124125
$hasVary = ['Accept-Language'] === $response->getVary() ? !$request->attributes->get('_vary_by_language') : $response->hasVary();
126+
//Check if cache-control directive was set manually in cacheControl (not auto computed)
127+
$hasCacheControlDirective = new class($response->headers) extends HeaderBag {
128+
public function __construct(private parent $headerBag)
129+
{
130+
}
131+
132+
public function __invoke(string $key): bool
133+
{
134+
return \array_key_exists($key, $this->headerBag->cacheControl);
135+
}
136+
};
125137

126138
foreach (array_reverse($attributes) as $cache) {
127-
if (null !== $cache->smaxage && !$response->headers->hasCacheControlDirective('s-maxage')) {
139+
if (null !== $cache->smaxage && !$hasCacheControlDirective('s-maxage')) {
128140
$response->setSharedMaxAge($this->toSeconds($cache->smaxage));
129141
}
130142

131143
if ($cache->mustRevalidate) {
132144
$response->headers->addCacheControlDirective('must-revalidate');
133145
}
134146

135-
if (null !== $cache->maxage && !$response->headers->hasCacheControlDirective('max-age')) {
147+
if (null !== $cache->maxage && !$hasCacheControlDirective('max-age')) {
136148
$response->setMaxAge($this->toSeconds($cache->maxage));
137149
}
138150

139-
if (null !== $cache->maxStale && !$response->headers->hasCacheControlDirective('max-stale')) {
151+
if (null !== $cache->maxStale && !$hasCacheControlDirective('max-stale')) {
140152
$response->headers->addCacheControlDirective('max-stale', $this->toSeconds($cache->maxStale));
141153
}
142154

143-
if (null !== $cache->staleWhileRevalidate && !$response->headers->hasCacheControlDirective('stale-while-revalidate')) {
155+
if (null !== $cache->staleWhileRevalidate && !$hasCacheControlDirective('stale-while-revalidate')) {
144156
$response->headers->addCacheControlDirective('stale-while-revalidate', $this->toSeconds($cache->staleWhileRevalidate));
145157
}
146158

147-
if (null !== $cache->staleIfError && !$response->headers->hasCacheControlDirective('stale-if-error')) {
159+
if (null !== $cache->staleIfError && !$hasCacheControlDirective('stale-if-error')) {
148160
$response->headers->addCacheControlDirective('stale-if-error', $this->toSeconds($cache->staleIfError));
149161
}
150162

@@ -157,12 +169,14 @@ public function onKernelResponse(ResponseEvent $event): void
157169
}
158170
}
159171

172+
$hasPublicOrPrivateCacheControlDirective = $hasCacheControlDirective('public') || $hasCacheControlDirective('private');
173+
160174
foreach ($attributes as $cache) {
161-
if (true === $cache->public) {
175+
if (true === $cache->public && !$hasPublicOrPrivateCacheControlDirective) {
162176
$response->setPublic();
163177
}
164178

165-
if (false === $cache->public) {
179+
if (false === $cache->public && !$hasPublicOrPrivateCacheControlDirective) {
166180
$response->setPrivate();
167181
}
168182

Tests/EventListener/CacheAttributeListenerTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,30 @@ public function testHasRelevantVaryHeaderBehavior(array $responseVary, array $ca
375375
$this->assertSame($expectedVary, $response->getVary());
376376
}
377377

378+
public function testAttributeRespectsExplicitPrivateFromController()
379+
{
380+
$request = $this->createRequest(new Cache(public: true));
381+
$response = new Response();
382+
$response->setPrivate();
383+
384+
$this->listener->onKernelResponse($this->createEventMock($request, $response));
385+
386+
$this->assertTrue($response->headers->hasCacheControlDirective('private'));
387+
$this->assertFalse($response->headers->hasCacheControlDirective('public'));
388+
}
389+
390+
public function testAttributeRespectsExplicitPublicFromController()
391+
{
392+
$request = $this->createRequest(new Cache(public: false));
393+
$response = new Response();
394+
$response->setPublic();
395+
396+
$this->listener->onKernelResponse($this->createEventMock($request, $response));
397+
398+
$this->assertTrue($response->headers->hasCacheControlDirective('public'));
399+
$this->assertFalse($response->headers->hasCacheControlDirective('private'));
400+
}
401+
378402
public static function provideVaryHeaderScenarios(): \Traversable
379403
{
380404
yield 'no vary headers at all' => [

0 commit comments

Comments
 (0)