vendor/symfony/http-foundation/HeaderBag.php line 265

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.  * HeaderBag is a container for HTTP headers.
  13.  *
  14.  * @author Fabien Potencier <fabien@symfony.com>
  15.  */
  16. class HeaderBag implements \IteratorAggregate\Countable
  17. {
  18.     protected const UPPER '_ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  19.     protected const LOWER '-abcdefghijklmnopqrstuvwxyz';
  20.     protected $headers = [];
  21.     protected $cacheControl = [];
  22.     public function __construct(array $headers = [])
  23.     {
  24.         foreach ($headers as $key => $values) {
  25.             $this->set($key$values);
  26.         }
  27.     }
  28.     /**
  29.      * Returns the headers as a string.
  30.      *
  31.      * @return string The headers
  32.      */
  33.     public function __toString()
  34.     {
  35.         if (!$headers $this->all()) {
  36.             return '';
  37.         }
  38.         ksort($headers);
  39.         $max max(array_map('strlen'array_keys($headers))) + 1;
  40.         $content '';
  41.         foreach ($headers as $name => $values) {
  42.             $name ucwords($name'-');
  43.             foreach ($values as $value) {
  44.                 $content .= sprintf("%-{$max}s %s\r\n"$name.':'$value);
  45.             }
  46.         }
  47.         return $content;
  48.     }
  49.     /**
  50.      * Returns the headers.
  51.      *
  52.      * @param string|null $key The name of the headers to return or null to get them all
  53.      *
  54.      * @return array An array of headers
  55.      */
  56.     public function all(string $key null)
  57.     {
  58.         if (null !== $key) {
  59.             return $this->headers[strtr($keyself::UPPERself::LOWER)] ?? [];
  60.         }
  61.         return $this->headers;
  62.     }
  63.     /**
  64.      * Returns the parameter keys.
  65.      *
  66.      * @return array An array of parameter keys
  67.      */
  68.     public function keys()
  69.     {
  70.         return array_keys($this->all());
  71.     }
  72.     /**
  73.      * Replaces the current HTTP headers by a new set.
  74.      */
  75.     public function replace(array $headers = [])
  76.     {
  77.         $this->headers = [];
  78.         $this->add($headers);
  79.     }
  80.     /**
  81.      * Adds new headers the current HTTP headers set.
  82.      */
  83.     public function add(array $headers)
  84.     {
  85.         foreach ($headers as $key => $values) {
  86.             $this->set($key$values);
  87.         }
  88.     }
  89.     /**
  90.      * Returns a header value by name.
  91.      *
  92.      * @return string|null The first header value or default value
  93.      */
  94.     public function get(string $keystring $default null)
  95.     {
  96.         $headers $this->all($key);
  97.         if (!$headers) {
  98.             return $default;
  99.         }
  100.         if (null === $headers[0]) {
  101.             return null;
  102.         }
  103.         return (string) $headers[0];
  104.     }
  105.     /**
  106.      * Sets a header by name.
  107.      *
  108.      * @param string|string[]|null $values  The value or an array of values
  109.      * @param bool                 $replace Whether to replace the actual value or not (true by default)
  110.      */
  111.     public function set(string $key$valuesbool $replace true)
  112.     {
  113.         $key strtr($keyself::UPPERself::LOWER);
  114.         if (\is_array($values)) {
  115.             $values array_values($values);
  116.             if (true === $replace || !isset($this->headers[$key])) {
  117.                 $this->headers[$key] = $values;
  118.             } else {
  119.                 $this->headers[$key] = array_merge($this->headers[$key], $values);
  120.             }
  121.         } else {
  122.             if (true === $replace || !isset($this->headers[$key])) {
  123.                 $this->headers[$key] = [$values];
  124.             } else {
  125.                 $this->headers[$key][] = $values;
  126.             }
  127.         }
  128.         if ('cache-control' === $key) {
  129.             $this->cacheControl $this->parseCacheControl(implode(', '$this->headers[$key]));
  130.         }
  131.     }
  132.     /**
  133.      * Returns true if the HTTP header is defined.
  134.      *
  135.      * @return bool true if the parameter exists, false otherwise
  136.      */
  137.     public function has(string $key)
  138.     {
  139.         return \array_key_exists(strtr($keyself::UPPERself::LOWER), $this->all());
  140.     }
  141.     /**
  142.      * Returns true if the given HTTP header contains the given value.
  143.      *
  144.      * @return bool true if the value is contained in the header, false otherwise
  145.      */
  146.     public function contains(string $keystring $value)
  147.     {
  148.         return \in_array($value$this->all($key));
  149.     }
  150.     /**
  151.      * Removes a header.
  152.      */
  153.     public function remove(string $key)
  154.     {
  155.         $key strtr($keyself::UPPERself::LOWER);
  156.         unset($this->headers[$key]);
  157.         if ('cache-control' === $key) {
  158.             $this->cacheControl = [];
  159.         }
  160.     }
  161.     /**
  162.      * Returns the HTTP header value converted to a date.
  163.      *
  164.      * @return \DateTimeInterface|null The parsed DateTime or the default value if the header does not exist
  165.      *
  166.      * @throws \RuntimeException When the HTTP header is not parseable
  167.      */
  168.     public function getDate(string $key\DateTime $default null)
  169.     {
  170.         if (null === $value $this->get($key)) {
  171.             return $default;
  172.         }
  173.         if (false === $date \DateTime::createFromFormat(\DATE_RFC2822$value)) {
  174.             throw new \RuntimeException(sprintf('The "%s" HTTP header is not parseable (%s).'$key$value));
  175.         }
  176.         return $date;
  177.     }
  178.     /**
  179.      * Adds a custom Cache-Control directive.
  180.      *
  181.      * @param bool|string $value The Cache-Control directive value
  182.      */
  183.     public function addCacheControlDirective(string $key$value true)
  184.     {
  185.         $this->cacheControl[$key] = $value;
  186.         $this->set('Cache-Control'$this->getCacheControlHeader());
  187.     }
  188.     /**
  189.      * Returns true if the Cache-Control directive is defined.
  190.      *
  191.      * @return bool true if the directive exists, false otherwise
  192.      */
  193.     public function hasCacheControlDirective(string $key)
  194.     {
  195.         return \array_key_exists($key$this->cacheControl);
  196.     }
  197.     /**
  198.      * Returns a Cache-Control directive value by name.
  199.      *
  200.      * @return bool|string|null The directive value if defined, null otherwise
  201.      */
  202.     public function getCacheControlDirective(string $key)
  203.     {
  204.         return $this->cacheControl[$key] ?? null;
  205.     }
  206.     /**
  207.      * Removes a Cache-Control directive.
  208.      */
  209.     public function removeCacheControlDirective(string $key)
  210.     {
  211.         unset($this->cacheControl[$key]);
  212.         $this->set('Cache-Control'$this->getCacheControlHeader());
  213.     }
  214.     /**
  215.      * Returns an iterator for headers.
  216.      *
  217.      * @return \ArrayIterator An \ArrayIterator instance
  218.      */
  219.     public function getIterator()
  220.     {
  221.         return new \ArrayIterator($this->headers);
  222.     }
  223.     /**
  224.      * Returns the number of headers.
  225.      *
  226.      * @return int The number of headers
  227.      */
  228.     public function count()
  229.     {
  230.         return \count($this->headers);
  231.     }
  232.     protected function getCacheControlHeader()
  233.     {
  234.         ksort($this->cacheControl);
  235.         return HeaderUtils::toString($this->cacheControl',');
  236.     }
  237.     /**
  238.      * Parses a Cache-Control HTTP header.
  239.      *
  240.      * @return array An array representing the attribute values
  241.      */
  242.     protected function parseCacheControl(string $header)
  243.     {
  244.         $parts HeaderUtils::split($header',=');
  245.         return HeaderUtils::combine($parts);
  246.     }
  247. }