Exception
2 years ago
File
1 year ago
RateLimiter
2 years ago
Session
1 year ago
Test
1 year ago
AcceptHeader.php
1 year ago
AcceptHeaderItem.php
2 years ago
BinaryFileResponse.php
1 year ago
Cookie.php
1 year ago
ExpressionRequestMatcher.php
2 years ago
FileBag.php
1 year ago
HeaderBag.php
1 year ago
HeaderUtils.php
1 year ago
InputBag.php
2 years ago
IpUtils.php
1 year ago
JsonResponse.php
1 year ago
LICENSE
2 years ago
ParameterBag.php
1 year ago
README.md
2 years ago
RedirectResponse.php
2 years ago
Request.php
1 year ago
RequestMatcher.php
1 year ago
RequestMatcherInterface.php
2 years ago
RequestStack.php
2 years ago
Response.php
1 year ago
ResponseHeaderBag.php
1 year ago
ServerBag.php
1 year ago
StreamedResponse.php
1 year ago
UrlHelper.php
2 years ago
HeaderBag.php
257 lines
| 1 | <?php |
| 2 | |
| 3 | /* |
| 4 | * This file is part of the Symfony package. |
| 5 | * |
| 6 | * (c) Fabien Potencier <fabien@symfony.com> |
| 7 | * |
| 8 | * For the full copyright and license information, please view the LICENSE |
| 9 | * file that was distributed with this source code. |
| 10 | */ |
| 11 | namespace Matomo\Dependencies\Symfony\Component\HttpFoundation; |
| 12 | |
| 13 | /** |
| 14 | * HeaderBag is a container for HTTP headers. |
| 15 | * |
| 16 | * @author Fabien Potencier <fabien@symfony.com> |
| 17 | * |
| 18 | * @implements \IteratorAggregate<string, list<string|null>> |
| 19 | */ |
| 20 | class HeaderBag implements \IteratorAggregate, \Countable |
| 21 | { |
| 22 | protected const UPPER = '_ABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
| 23 | protected const LOWER = '-abcdefghijklmnopqrstuvwxyz'; |
| 24 | /** |
| 25 | * @var array<string, list<string|null>> |
| 26 | */ |
| 27 | protected $headers = []; |
| 28 | protected $cacheControl = []; |
| 29 | public function __construct(array $headers = []) |
| 30 | { |
| 31 | foreach ($headers as $key => $values) { |
| 32 | $this->set($key, $values); |
| 33 | } |
| 34 | } |
| 35 | /** |
| 36 | * Returns the headers as a string. |
| 37 | * |
| 38 | * @return string |
| 39 | */ |
| 40 | public function __toString() |
| 41 | { |
| 42 | if (!($headers = $this->all())) { |
| 43 | return ''; |
| 44 | } |
| 45 | ksort($headers); |
| 46 | $max = max(array_map('strlen', array_keys($headers))) + 1; |
| 47 | $content = ''; |
| 48 | foreach ($headers as $name => $values) { |
| 49 | $name = ucwords($name, '-'); |
| 50 | foreach ($values as $value) { |
| 51 | $content .= sprintf("%-{$max}s %s\r\n", $name . ':', $value); |
| 52 | } |
| 53 | } |
| 54 | return $content; |
| 55 | } |
| 56 | /** |
| 57 | * Returns the headers. |
| 58 | * |
| 59 | * @param string|null $key The name of the headers to return or null to get them all |
| 60 | * |
| 61 | * @return array<string, array<int, string|null>>|array<int, string|null> |
| 62 | */ |
| 63 | public function all(?string $key = null) |
| 64 | { |
| 65 | if (null !== $key) { |
| 66 | return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? []; |
| 67 | } |
| 68 | return $this->headers; |
| 69 | } |
| 70 | /** |
| 71 | * Returns the parameter keys. |
| 72 | * |
| 73 | * @return string[] |
| 74 | */ |
| 75 | public function keys() |
| 76 | { |
| 77 | return array_keys($this->all()); |
| 78 | } |
| 79 | /** |
| 80 | * Replaces the current HTTP headers by a new set. |
| 81 | */ |
| 82 | public function replace(array $headers = []) |
| 83 | { |
| 84 | $this->headers = []; |
| 85 | $this->add($headers); |
| 86 | } |
| 87 | /** |
| 88 | * Adds new headers the current HTTP headers set. |
| 89 | */ |
| 90 | public function add(array $headers) |
| 91 | { |
| 92 | foreach ($headers as $key => $values) { |
| 93 | $this->set($key, $values); |
| 94 | } |
| 95 | } |
| 96 | /** |
| 97 | * Returns the first header by name or the default one. |
| 98 | * |
| 99 | * @return string|null |
| 100 | */ |
| 101 | public function get(string $key, ?string $default = null) |
| 102 | { |
| 103 | $headers = $this->all($key); |
| 104 | if (!$headers) { |
| 105 | return $default; |
| 106 | } |
| 107 | if (null === $headers[0]) { |
| 108 | return null; |
| 109 | } |
| 110 | return (string) $headers[0]; |
| 111 | } |
| 112 | /** |
| 113 | * Sets a header by name. |
| 114 | * |
| 115 | * @param string|string[]|null $values The value or an array of values |
| 116 | * @param bool $replace Whether to replace the actual value or not (true by default) |
| 117 | */ |
| 118 | public function set(string $key, $values, bool $replace = \true) |
| 119 | { |
| 120 | $key = strtr($key, self::UPPER, self::LOWER); |
| 121 | if (\is_array($values)) { |
| 122 | $values = array_values($values); |
| 123 | if (\true === $replace || !isset($this->headers[$key])) { |
| 124 | $this->headers[$key] = $values; |
| 125 | } else { |
| 126 | $this->headers[$key] = array_merge($this->headers[$key], $values); |
| 127 | } |
| 128 | } else { |
| 129 | if (\true === $replace || !isset($this->headers[$key])) { |
| 130 | $this->headers[$key] = [$values]; |
| 131 | } else { |
| 132 | $this->headers[$key][] = $values; |
| 133 | } |
| 134 | } |
| 135 | if ('cache-control' === $key) { |
| 136 | $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key])); |
| 137 | } |
| 138 | } |
| 139 | /** |
| 140 | * Returns true if the HTTP header is defined. |
| 141 | * |
| 142 | * @return bool |
| 143 | */ |
| 144 | public function has(string $key) |
| 145 | { |
| 146 | return \array_key_exists(strtr($key, self::UPPER, self::LOWER), $this->all()); |
| 147 | } |
| 148 | /** |
| 149 | * Returns true if the given HTTP header contains the given value. |
| 150 | * |
| 151 | * @return bool |
| 152 | */ |
| 153 | public function contains(string $key, string $value) |
| 154 | { |
| 155 | return \in_array($value, $this->all($key)); |
| 156 | } |
| 157 | /** |
| 158 | * Removes a header. |
| 159 | */ |
| 160 | public function remove(string $key) |
| 161 | { |
| 162 | $key = strtr($key, self::UPPER, self::LOWER); |
| 163 | unset($this->headers[$key]); |
| 164 | if ('cache-control' === $key) { |
| 165 | $this->cacheControl = []; |
| 166 | } |
| 167 | } |
| 168 | /** |
| 169 | * Returns the HTTP header value converted to a date. |
| 170 | * |
| 171 | * @return \DateTimeInterface|null |
| 172 | * |
| 173 | * @throws \RuntimeException When the HTTP header is not parseable |
| 174 | */ |
| 175 | public function getDate(string $key, ?\DateTime $default = null) |
| 176 | { |
| 177 | if (null === ($value = $this->get($key))) { |
| 178 | return $default; |
| 179 | } |
| 180 | if (\false === ($date = \DateTime::createFromFormat(\DATE_RFC2822, $value))) { |
| 181 | throw new \RuntimeException(sprintf('The "%s" HTTP header is not parseable (%s).', $key, $value)); |
| 182 | } |
| 183 | return $date; |
| 184 | } |
| 185 | /** |
| 186 | * Adds a custom Cache-Control directive. |
| 187 | * |
| 188 | * @param bool|string $value The Cache-Control directive value |
| 189 | */ |
| 190 | public function addCacheControlDirective(string $key, $value = \true) |
| 191 | { |
| 192 | $this->cacheControl[$key] = $value; |
| 193 | $this->set('Cache-Control', $this->getCacheControlHeader()); |
| 194 | } |
| 195 | /** |
| 196 | * Returns true if the Cache-Control directive is defined. |
| 197 | * |
| 198 | * @return bool |
| 199 | */ |
| 200 | public function hasCacheControlDirective(string $key) |
| 201 | { |
| 202 | return \array_key_exists($key, $this->cacheControl); |
| 203 | } |
| 204 | /** |
| 205 | * Returns a Cache-Control directive value by name. |
| 206 | * |
| 207 | * @return bool|string|null |
| 208 | */ |
| 209 | public function getCacheControlDirective(string $key) |
| 210 | { |
| 211 | return $this->cacheControl[$key] ?? null; |
| 212 | } |
| 213 | /** |
| 214 | * Removes a Cache-Control directive. |
| 215 | */ |
| 216 | public function removeCacheControlDirective(string $key) |
| 217 | { |
| 218 | unset($this->cacheControl[$key]); |
| 219 | $this->set('Cache-Control', $this->getCacheControlHeader()); |
| 220 | } |
| 221 | /** |
| 222 | * Returns an iterator for headers. |
| 223 | * |
| 224 | * @return \ArrayIterator<string, list<string|null>> |
| 225 | */ |
| 226 | #[\ReturnTypeWillChange] |
| 227 | public function getIterator() |
| 228 | { |
| 229 | return new \ArrayIterator($this->headers); |
| 230 | } |
| 231 | /** |
| 232 | * Returns the number of headers. |
| 233 | * |
| 234 | * @return int |
| 235 | */ |
| 236 | #[\ReturnTypeWillChange] |
| 237 | public function count() |
| 238 | { |
| 239 | return \count($this->headers); |
| 240 | } |
| 241 | protected function getCacheControlHeader() |
| 242 | { |
| 243 | ksort($this->cacheControl); |
| 244 | return HeaderUtils::toString($this->cacheControl, ','); |
| 245 | } |
| 246 | /** |
| 247 | * Parses a Cache-Control HTTP header. |
| 248 | * |
| 249 | * @return array |
| 250 | */ |
| 251 | protected function parseCacheControl(string $header) |
| 252 | { |
| 253 | $parts = HeaderUtils::split($header, ',='); |
| 254 | return HeaderUtils::combine($parts); |
| 255 | } |
| 256 | } |
| 257 |