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

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 (<= \func_num_args() && null !== $key func_get_arg(0)) {
  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.      * @param string      $key     The header name
  93.      * @param string|null $default The default value
  94.      *
  95.      * @return string|null The first header value or default value
  96.      */
  97.     public function get($key$default null)
  98.     {
  99.         $headers $this->all((string) $key);
  100.         if (< \func_num_args()) {
  101.             @trigger_error(sprintf('Passing a third argument to "%s()" is deprecated since Symfony 4.4, use method "all()" instead'__METHOD__), E_USER_DEPRECATED);
  102.             if (!func_get_arg(2)) {
  103.                 return $headers;
  104.             }
  105.         }
  106.         if (!$headers) {
  107.             return $default;
  108.         }
  109.         if (null === $headers[0]) {
  110.             return null;
  111.         }
  112.         return (string) $headers[0];
  113.     }
  114.     /**
  115.      * Sets a header by name.
  116.      *
  117.      * @param string          $key     The key
  118.      * @param string|string[] $values  The value or an array of values
  119.      * @param bool            $replace Whether to replace the actual value or not (true by default)
  120.      */
  121.     public function set($key$values$replace true)
  122.     {
  123.         $key strtr($keyself::UPPERself::LOWER);
  124.         if (\is_array($values)) {
  125.             $values array_values($values);
  126.             if (true === $replace || !isset($this->headers[$key])) {
  127.                 $this->headers[$key] = $values;
  128.             } else {
  129.                 $this->headers[$key] = array_merge($this->headers[$key], $values);
  130.             }
  131.         } else {
  132.             if (true === $replace || !isset($this->headers[$key])) {
  133.                 $this->headers[$key] = [$values];
  134.             } else {
  135.                 $this->headers[$key][] = $values;
  136.             }
  137.         }
  138.         if ('cache-control' === $key) {
  139.             $this->cacheControl $this->parseCacheControl(implode(', '$this->headers[$key]));
  140.         }
  141.     }
  142.     /**
  143.      * Returns true if the HTTP header is defined.
  144.      *
  145.      * @param string $key The HTTP header
  146.      *
  147.      * @return bool true if the parameter exists, false otherwise
  148.      */
  149.     public function has($key)
  150.     {
  151.         return \array_key_exists(strtr($keyself::UPPERself::LOWER), $this->all());
  152.     }
  153.     /**
  154.      * Returns true if the given HTTP header contains the given value.
  155.      *
  156.      * @param string $key   The HTTP header name
  157.      * @param string $value The HTTP value
  158.      *
  159.      * @return bool true if the value is contained in the header, false otherwise
  160.      */
  161.     public function contains($key$value)
  162.     {
  163.         return \in_array($value$this->all((string) $key));
  164.     }
  165.     /**
  166.      * Removes a header.
  167.      *
  168.      * @param string $key The HTTP header name
  169.      */
  170.     public function remove($key)
  171.     {
  172.         $key strtr($keyself::UPPERself::LOWER);
  173.         unset($this->headers[$key]);
  174.         if ('cache-control' === $key) {
  175.             $this->cacheControl = [];
  176.         }
  177.     }
  178.     /**
  179.      * Returns the HTTP header value converted to a date.
  180.      *
  181.      * @param string $key The parameter key
  182.      *
  183.      * @return \DateTimeInterface|null The parsed DateTime or the default value if the header does not exist
  184.      *
  185.      * @throws \RuntimeException When the HTTP header is not parseable
  186.      */
  187.     public function getDate($key, \DateTime $default null)
  188.     {
  189.         if (null === $value $this->get($key)) {
  190.             return $default;
  191.         }
  192.         if (false === $date = \DateTime::createFromFormat(DATE_RFC2822$value)) {
  193.             throw new \RuntimeException(sprintf('The "%s" HTTP header is not parseable (%s).'$key$value));
  194.         }
  195.         return $date;
  196.     }
  197.     /**
  198.      * Adds a custom Cache-Control directive.
  199.      *
  200.      * @param string $key   The Cache-Control directive name
  201.      * @param mixed  $value The Cache-Control directive value
  202.      */
  203.     public function addCacheControlDirective($key$value true)
  204.     {
  205.         $this->cacheControl[$key] = $value;
  206.         $this->set('Cache-Control'$this->getCacheControlHeader());
  207.     }
  208.     /**
  209.      * Returns true if the Cache-Control directive is defined.
  210.      *
  211.      * @param string $key The Cache-Control directive
  212.      *
  213.      * @return bool true if the directive exists, false otherwise
  214.      */
  215.     public function hasCacheControlDirective($key)
  216.     {
  217.         return \array_key_exists($key$this->cacheControl);
  218.     }
  219.     /**
  220.      * Returns a Cache-Control directive value by name.
  221.      *
  222.      * @param string $key The directive name
  223.      *
  224.      * @return mixed|null The directive value if defined, null otherwise
  225.      */
  226.     public function getCacheControlDirective($key)
  227.     {
  228.         return \array_key_exists($key$this->cacheControl) ? $this->cacheControl[$key] : null;
  229.     }
  230.     /**
  231.      * Removes a Cache-Control directive.
  232.      *
  233.      * @param string $key The Cache-Control directive
  234.      */
  235.     public function removeCacheControlDirective($key)
  236.     {
  237.         unset($this->cacheControl[$key]);
  238.         $this->set('Cache-Control'$this->getCacheControlHeader());
  239.     }
  240.     /**
  241.      * Returns an iterator for headers.
  242.      *
  243.      * @return \ArrayIterator An \ArrayIterator instance
  244.      */
  245.     public function getIterator()
  246.     {
  247.         return new \ArrayIterator($this->headers);
  248.     }
  249.     /**
  250.      * Returns the number of headers.
  251.      *
  252.      * @return int The number of headers
  253.      */
  254.     public function count()
  255.     {
  256.         return \count($this->headers);
  257.     }
  258.     protected function getCacheControlHeader()
  259.     {
  260.         ksort($this->cacheControl);
  261.         return HeaderUtils::toString($this->cacheControl',');
  262.     }
  263.     /**
  264.      * Parses a Cache-Control HTTP header.
  265.      *
  266.      * @param string $header The value of the Cache-Control HTTP header
  267.      *
  268.      * @return array An array representing the attribute values
  269.      */
  270.     protected function parseCacheControl($header)
  271.     {
  272.         $parts HeaderUtils::split($header',=');
  273.         return HeaderUtils::combine($parts);
  274.     }
  275. }