Repository: symfony/symfony
File: src/Symfony/Component/HttpKernel/EventListener/CacheAttributeListener.php (PHP)

Code before:
            $event->setController(static fn () => $response);
            $event->stopPropagation();

            return;
        }

        if (null !== $etag) {
            $this->etags[$request] = $etag;
        }
        if (null !== $lastModified) {
            $this->lastModified[$request] = $lastModified;
        }
    }

    /**
     * Modifies the response to apply HTTP cache headers when needed.
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        $request = $event->getRequest();

        /** @var Cache[] $attributes */
        if (!\is_array($attributes = $request->attributes->get('_cache'))) {
            return;
        }
        $attributes = array_reverse($attributes);
        $response = $event->getResponse();

        // http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-12#section-3.1
        if (!\in_array($response->getStatusCode(), [200, 203, 300, 301, 302, 304, 404, 410], true)) {
            unset($this->lastModified[$request]);
            unset($this->etags[$request]);

            return;
        }

        if (isset($this->lastModified[$request]) && !$response->headers->has('Last-Modified')) {
            $response->setLastModified($this->lastModified[$request]);
        }

        if (isset($this->etags[$request]) && !$response->headers->has('Etag')) {
            $response->setEtag($this->etags[$request]);
        }

        unset($this->lastModified[$request]);
        unset($this->etags[$request]);
        // Check if the response has a Vary header that should be considered, ignoring cases where
        // it's only 'Accept-Language' and the request has the '_vary_by_language' attribute
        $hasVary = ['Accept-Language'] === $response->getVary() ? !$request->attributes->get('_vary_by_language') : $response->hasVary();
        // Check if cache-control directive was set manually in cacheControl (not auto computed)
        $hasCacheControlDirective = new class($response->headers) extends HeaderBag {

Review comment (performance):
Could we move this to where `$hasPublicOrPrivateCacheControlDirective` is defined, so we only do the `array_reverse()` when the status code is relevant?

Code after:

            return;
        }

        if (null !== $etag) {
            $this->etags[$request] = $etag;
        }
        if (null !== $lastModified) {
            $this->lastModified[$request] = $lastModified;
        }
    }

    /**
     * Modifies the response to apply HTTP cache headers when needed.
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        $request = $event->getRequest();

        /** @var Cache[] $attributes */
        if (!\is_array($attributes = $request->attributes->get('_cache'))) {
            return;
        }
        $response = $event->getResponse();

        // http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-12#section-3.1
        if (!\in_array($response->getStatusCode(), [200, 203, 300, 301, 302, 304, 404, 410], true)) {
            unset($this->lastModified[$request]);
            unset($this->etags[$request]);

            return;
        }

        if (isset($this->lastModified[$request]) && !$response->headers->has('Last-Modified')) {
            $response->setLastModified($this->lastModified[$request]);
        }

        if (isset($this->etags[$request]) && !$response->headers->has('Etag')) {
            $response->setEtag($this->etags[$request]);
        }

        unset($this->lastModified[$request]);
        unset($this->etags[$request]);
        // Check if the response has a Vary header that should be considered, ignoring cases where
        // it's only 'Accept-Language' and the request has the '_vary_by_language' attribute
        $hasVary = ['Accept-Language'] === $response->getVary() ? !$request->attributes->get('_vary_by_language') : $response->hasVary();
        // Check if cache-control directive was set manually in cacheControl (not auto computed)
        $hasCacheControlDirective = new class($response->headers) extends HeaderBag {
            public function __construct(private parent $headerBag)
            {
            }