vendor/symfony/http-foundation/ResponseHeaderBag.php line 242

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\HttpFoundation;
  11. /**
  12.  * ResponseHeaderBag is a container for Response HTTP headers.
  13.  *
  14.  * @author Fabien Potencier <fabien@symfony.com>
  15.  */
  16. class ResponseHeaderBag extends HeaderBag
  17. {
  18.     public const COOKIES_FLAT 'flat';
  19.     public const COOKIES_ARRAY 'array';
  20.     public const DISPOSITION_ATTACHMENT 'attachment';
  21.     public const DISPOSITION_INLINE 'inline';
  22.     protected $computedCacheControl = [];
  23.     protected $cookies = [];
  24.     protected $headerNames = [];
  25.     public function __construct(array $headers = [])
  26.     {
  27.         parent::__construct($headers);
  28.         if (!isset($this->headers['cache-control'])) {
  29.             $this->set('Cache-Control''');
  30.         }
  31.         /* RFC2616 - 14.18 says all Responses need to have a Date */
  32.         if (!isset($this->headers['date'])) {
  33.             $this->initDate();
  34.         }
  35.     }
  36.     /**
  37.      * Returns the headers, with original capitalizations.
  38.      *
  39.      * @return array
  40.      */
  41.     public function allPreserveCase()
  42.     {
  43.         $headers = [];
  44.         foreach ($this->all() as $name => $value) {
  45.             $headers[$this->headerNames[$name] ?? $name] = $value;
  46.         }
  47.         return $headers;
  48.     }
  49.     public function allPreserveCaseWithoutCookies()
  50.     {
  51.         $headers $this->allPreserveCase();
  52.         if (isset($this->headerNames['set-cookie'])) {
  53.             unset($headers[$this->headerNames['set-cookie']]);
  54.         }
  55.         return $headers;
  56.     }
  57.     /**
  58.      * {@inheritdoc}
  59.      */
  60.     public function replace(array $headers = [])
  61.     {
  62.         $this->headerNames = [];
  63.         parent::replace($headers);
  64.         if (!isset($this->headers['cache-control'])) {
  65.             $this->set('Cache-Control''');
  66.         }
  67.         if (!isset($this->headers['date'])) {
  68.             $this->initDate();
  69.         }
  70.     }
  71.     /**
  72.      * {@inheritdoc}
  73.      */
  74.     public function all(string $key null)
  75.     {
  76.         $headers parent::all();
  77.         if (null !== $key) {
  78.             $key strtr($keyself::UPPERself::LOWER);
  79.             return 'set-cookie' !== $key $headers[$key] ?? [] : array_map('strval'$this->getCookies());
  80.         }
  81.         foreach ($this->getCookies() as $cookie) {
  82.             $headers['set-cookie'][] = (string) $cookie;
  83.         }
  84.         return $headers;
  85.     }
  86.     /**
  87.      * {@inheritdoc}
  88.      */
  89.     public function set(string $key$valuesbool $replace true)
  90.     {
  91.         $uniqueKey strtr($keyself::UPPERself::LOWER);
  92.         if ('set-cookie' === $uniqueKey) {
  93.             if ($replace) {
  94.                 $this->cookies = [];
  95.             }
  96.             foreach ((array) $values as $cookie) {
  97.                 $this->setCookie(Cookie::fromString($cookie));
  98.             }
  99.             $this->headerNames[$uniqueKey] = $key;
  100.             return;
  101.         }
  102.         $this->headerNames[$uniqueKey] = $key;
  103.         parent::set($key$values$replace);
  104.         // ensure the cache-control header has sensible defaults
  105.         if (\in_array($uniqueKey, ['cache-control''etag''last-modified''expires'], true) && '' !== $computed $this->computeCacheControlValue()) {
  106.             $this->headers['cache-control'] = [$computed];
  107.             $this->headerNames['cache-control'] = 'Cache-Control';
  108.             $this->computedCacheControl $this->parseCacheControl($computed);
  109.         }
  110.     }
  111.     /**
  112.      * {@inheritdoc}
  113.      */
  114.     public function remove(string $key)
  115.     {
  116.         $uniqueKey strtr($keyself::UPPERself::LOWER);
  117.         unset($this->headerNames[$uniqueKey]);
  118.         if ('set-cookie' === $uniqueKey) {
  119.             $this->cookies = [];
  120.             return;
  121.         }
  122.         parent::remove($key);
  123.         if ('cache-control' === $uniqueKey) {
  124.             $this->computedCacheControl = [];
  125.         }
  126.         if ('date' === $uniqueKey) {
  127.             $this->initDate();
  128.         }
  129.     }
  130.     /**
  131.      * {@inheritdoc}
  132.      */
  133.     public function hasCacheControlDirective(string $key)
  134.     {
  135.         return \array_key_exists($key$this->computedCacheControl);
  136.     }
  137.     /**
  138.      * {@inheritdoc}
  139.      */
  140.     public function getCacheControlDirective(string $key)
  141.     {
  142.         return $this->computedCacheControl[$key] ?? null;
  143.     }
  144.     public function setCookie(Cookie $cookie)
  145.     {
  146.         $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie;
  147.         $this->headerNames['set-cookie'] = 'Set-Cookie';
  148.     }
  149.     /**
  150.      * Removes a cookie from the array, but does not unset it in the browser.
  151.      */
  152.     public function removeCookie(string $name, ?string $path '/'string $domain null)
  153.     {
  154.         if (null === $path) {
  155.             $path '/';
  156.         }
  157.         unset($this->cookies[$domain][$path][$name]);
  158.         if (empty($this->cookies[$domain][$path])) {
  159.             unset($this->cookies[$domain][$path]);
  160.             if (empty($this->cookies[$domain])) {
  161.                 unset($this->cookies[$domain]);
  162.             }
  163.         }
  164.         if (empty($this->cookies)) {
  165.             unset($this->headerNames['set-cookie']);
  166.         }
  167.     }
  168.     /**
  169.      * Returns an array with all cookies.
  170.      *
  171.      * @return Cookie[]
  172.      *
  173.      * @throws \InvalidArgumentException When the $format is invalid
  174.      */
  175.     public function getCookies(string $format self::COOKIES_FLAT)
  176.     {
  177.         if (!\in_array($format, [self::COOKIES_FLATself::COOKIES_ARRAY])) {
  178.             throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).'$formatimplode(', ', [self::COOKIES_FLATself::COOKIES_ARRAY])));
  179.         }
  180.         if (self::COOKIES_ARRAY === $format) {
  181.             return $this->cookies;
  182.         }
  183.         $flattenedCookies = [];
  184.         foreach ($this->cookies as $path) {
  185.             foreach ($path as $cookies) {
  186.                 foreach ($cookies as $cookie) {
  187.                     $flattenedCookies[] = $cookie;
  188.                 }
  189.             }
  190.         }
  191.         return $flattenedCookies;
  192.     }
  193.     /**
  194.      * Clears a cookie in the browser.
  195.      */
  196.     public function clearCookie(string $name, ?string $path '/'string $domain nullbool $secure falsebool $httpOnly truestring $sameSite null)
  197.     {
  198.         $this->setCookie(new Cookie($namenull1$path$domain$secure$httpOnlyfalse$sameSite));
  199.     }
  200.     /**
  201.      * @see HeaderUtils::makeDisposition()
  202.      */
  203.     public function makeDisposition(string $dispositionstring $filenamestring $filenameFallback '')
  204.     {
  205.         return HeaderUtils::makeDisposition($disposition$filename$filenameFallback);
  206.     }
  207.     /**
  208.      * Returns the calculated value of the cache-control header.
  209.      *
  210.      * This considers several other headers and calculates or modifies the
  211.      * cache-control header to a sensible, conservative value.
  212.      *
  213.      * @return string
  214.      */
  215.     protected function computeCacheControlValue()
  216.     {
  217.         if (!$this->cacheControl) {
  218.             if ($this->has('Last-Modified') || $this->has('Expires')) {
  219.                 return 'private, must-revalidate'// allows for heuristic expiration (RFC 7234 Section 4.2.2) in the case of "Last-Modified"
  220.             }
  221.             // conservative by default
  222.             return 'no-cache, private';
  223.         }
  224.         $header $this->getCacheControlHeader();
  225.         if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) {
  226.             return $header;
  227.         }
  228.         // public if s-maxage is defined, private otherwise
  229.         if (!isset($this->cacheControl['s-maxage'])) {
  230.             return $header.', private';
  231.         }
  232.         return $header;
  233.     }
  234.     private function initDate(): void
  235.     {
  236.         $this->set('Date'gmdate('D, d M Y H:i:s').' GMT');
  237.     }
  238. }