annotate vendor/symfony/http-foundation/HeaderBag.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\HttpFoundation;
Chris@0 13
Chris@0 14 /**
Chris@0 15 * HeaderBag is a container for HTTP headers.
Chris@0 16 *
Chris@0 17 * @author Fabien Potencier <fabien@symfony.com>
Chris@0 18 */
Chris@0 19 class HeaderBag implements \IteratorAggregate, \Countable
Chris@0 20 {
Chris@17 21 protected $headers = [];
Chris@17 22 protected $cacheControl = [];
Chris@0 23
Chris@0 24 /**
Chris@0 25 * @param array $headers An array of HTTP headers
Chris@0 26 */
Chris@17 27 public function __construct(array $headers = [])
Chris@0 28 {
Chris@0 29 foreach ($headers as $key => $values) {
Chris@0 30 $this->set($key, $values);
Chris@0 31 }
Chris@0 32 }
Chris@0 33
Chris@0 34 /**
Chris@0 35 * Returns the headers as a string.
Chris@0 36 *
Chris@0 37 * @return string The headers
Chris@0 38 */
Chris@0 39 public function __toString()
Chris@0 40 {
Chris@14 41 if (!$headers = $this->all()) {
Chris@0 42 return '';
Chris@0 43 }
Chris@0 44
Chris@14 45 ksort($headers);
Chris@14 46 $max = max(array_map('strlen', array_keys($headers))) + 1;
Chris@0 47 $content = '';
Chris@14 48 foreach ($headers as $name => $values) {
Chris@0 49 $name = implode('-', array_map('ucfirst', explode('-', $name)));
Chris@0 50 foreach ($values as $value) {
Chris@0 51 $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value);
Chris@0 52 }
Chris@0 53 }
Chris@0 54
Chris@0 55 return $content;
Chris@0 56 }
Chris@0 57
Chris@0 58 /**
Chris@0 59 * Returns the headers.
Chris@0 60 *
Chris@0 61 * @return array An array of headers
Chris@0 62 */
Chris@0 63 public function all()
Chris@0 64 {
Chris@0 65 return $this->headers;
Chris@0 66 }
Chris@0 67
Chris@0 68 /**
Chris@0 69 * Returns the parameter keys.
Chris@0 70 *
Chris@0 71 * @return array An array of parameter keys
Chris@0 72 */
Chris@0 73 public function keys()
Chris@0 74 {
Chris@14 75 return array_keys($this->all());
Chris@0 76 }
Chris@0 77
Chris@0 78 /**
Chris@0 79 * Replaces the current HTTP headers by a new set.
Chris@0 80 *
Chris@0 81 * @param array $headers An array of HTTP headers
Chris@0 82 */
Chris@17 83 public function replace(array $headers = [])
Chris@0 84 {
Chris@17 85 $this->headers = [];
Chris@0 86 $this->add($headers);
Chris@0 87 }
Chris@0 88
Chris@0 89 /**
Chris@0 90 * Adds new headers the current HTTP headers set.
Chris@0 91 *
Chris@0 92 * @param array $headers An array of HTTP headers
Chris@0 93 */
Chris@0 94 public function add(array $headers)
Chris@0 95 {
Chris@0 96 foreach ($headers as $key => $values) {
Chris@0 97 $this->set($key, $values);
Chris@0 98 }
Chris@0 99 }
Chris@0 100
Chris@0 101 /**
Chris@0 102 * Returns a header value by name.
Chris@0 103 *
Chris@17 104 * @param string $key The header name
Chris@17 105 * @param string|null $default The default value
Chris@17 106 * @param bool $first Whether to return the first value or all header values
Chris@0 107 *
Chris@17 108 * @return string|string[]|null The first header value or default value if $first is true, an array of values otherwise
Chris@0 109 */
Chris@0 110 public function get($key, $default = null, $first = true)
Chris@0 111 {
Chris@0 112 $key = str_replace('_', '-', strtolower($key));
Chris@14 113 $headers = $this->all();
Chris@0 114
Chris@18 115 if (!\array_key_exists($key, $headers)) {
Chris@0 116 if (null === $default) {
Chris@17 117 return $first ? null : [];
Chris@0 118 }
Chris@0 119
Chris@17 120 return $first ? $default : [$default];
Chris@0 121 }
Chris@0 122
Chris@0 123 if ($first) {
Chris@14 124 return \count($headers[$key]) ? $headers[$key][0] : $default;
Chris@0 125 }
Chris@0 126
Chris@14 127 return $headers[$key];
Chris@0 128 }
Chris@0 129
Chris@0 130 /**
Chris@0 131 * Sets a header by name.
Chris@0 132 *
Chris@14 133 * @param string $key The key
Chris@14 134 * @param string|string[] $values The value or an array of values
Chris@14 135 * @param bool $replace Whether to replace the actual value or not (true by default)
Chris@0 136 */
Chris@0 137 public function set($key, $values, $replace = true)
Chris@0 138 {
Chris@0 139 $key = str_replace('_', '-', strtolower($key));
Chris@0 140
Chris@14 141 if (\is_array($values)) {
Chris@14 142 $values = array_values($values);
Chris@0 143
Chris@14 144 if (true === $replace || !isset($this->headers[$key])) {
Chris@14 145 $this->headers[$key] = $values;
Chris@14 146 } else {
Chris@14 147 $this->headers[$key] = array_merge($this->headers[$key], $values);
Chris@14 148 }
Chris@0 149 } else {
Chris@14 150 if (true === $replace || !isset($this->headers[$key])) {
Chris@17 151 $this->headers[$key] = [$values];
Chris@14 152 } else {
Chris@14 153 $this->headers[$key][] = $values;
Chris@14 154 }
Chris@0 155 }
Chris@0 156
Chris@0 157 if ('cache-control' === $key) {
Chris@14 158 $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key]));
Chris@0 159 }
Chris@0 160 }
Chris@0 161
Chris@0 162 /**
Chris@0 163 * Returns true if the HTTP header is defined.
Chris@0 164 *
Chris@0 165 * @param string $key The HTTP header
Chris@0 166 *
Chris@0 167 * @return bool true if the parameter exists, false otherwise
Chris@0 168 */
Chris@0 169 public function has($key)
Chris@0 170 {
Chris@18 171 return \array_key_exists(str_replace('_', '-', strtolower($key)), $this->all());
Chris@0 172 }
Chris@0 173
Chris@0 174 /**
Chris@0 175 * Returns true if the given HTTP header contains the given value.
Chris@0 176 *
Chris@0 177 * @param string $key The HTTP header name
Chris@0 178 * @param string $value The HTTP value
Chris@0 179 *
Chris@0 180 * @return bool true if the value is contained in the header, false otherwise
Chris@0 181 */
Chris@0 182 public function contains($key, $value)
Chris@0 183 {
Chris@17 184 return \in_array($value, $this->get($key, null, false));
Chris@0 185 }
Chris@0 186
Chris@0 187 /**
Chris@0 188 * Removes a header.
Chris@0 189 *
Chris@0 190 * @param string $key The HTTP header name
Chris@0 191 */
Chris@0 192 public function remove($key)
Chris@0 193 {
Chris@0 194 $key = str_replace('_', '-', strtolower($key));
Chris@0 195
Chris@0 196 unset($this->headers[$key]);
Chris@0 197
Chris@0 198 if ('cache-control' === $key) {
Chris@17 199 $this->cacheControl = [];
Chris@0 200 }
Chris@0 201 }
Chris@0 202
Chris@0 203 /**
Chris@0 204 * Returns the HTTP header value converted to a date.
Chris@0 205 *
Chris@0 206 * @param string $key The parameter key
Chris@0 207 * @param \DateTime $default The default value
Chris@0 208 *
Chris@17 209 * @return \DateTime|null The parsed DateTime or the default value if the header does not exist
Chris@0 210 *
Chris@0 211 * @throws \RuntimeException When the HTTP header is not parseable
Chris@0 212 */
Chris@0 213 public function getDate($key, \DateTime $default = null)
Chris@0 214 {
Chris@0 215 if (null === $value = $this->get($key)) {
Chris@0 216 return $default;
Chris@0 217 }
Chris@0 218
Chris@0 219 if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) {
Chris@0 220 throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value));
Chris@0 221 }
Chris@0 222
Chris@0 223 return $date;
Chris@0 224 }
Chris@0 225
Chris@0 226 /**
Chris@0 227 * Adds a custom Cache-Control directive.
Chris@0 228 *
Chris@0 229 * @param string $key The Cache-Control directive name
Chris@0 230 * @param mixed $value The Cache-Control directive value
Chris@0 231 */
Chris@0 232 public function addCacheControlDirective($key, $value = true)
Chris@0 233 {
Chris@0 234 $this->cacheControl[$key] = $value;
Chris@0 235
Chris@0 236 $this->set('Cache-Control', $this->getCacheControlHeader());
Chris@0 237 }
Chris@0 238
Chris@0 239 /**
Chris@0 240 * Returns true if the Cache-Control directive is defined.
Chris@0 241 *
Chris@0 242 * @param string $key The Cache-Control directive
Chris@0 243 *
Chris@0 244 * @return bool true if the directive exists, false otherwise
Chris@0 245 */
Chris@0 246 public function hasCacheControlDirective($key)
Chris@0 247 {
Chris@18 248 return \array_key_exists($key, $this->cacheControl);
Chris@0 249 }
Chris@0 250
Chris@0 251 /**
Chris@0 252 * Returns a Cache-Control directive value by name.
Chris@0 253 *
Chris@0 254 * @param string $key The directive name
Chris@0 255 *
Chris@0 256 * @return mixed|null The directive value if defined, null otherwise
Chris@0 257 */
Chris@0 258 public function getCacheControlDirective($key)
Chris@0 259 {
Chris@18 260 return \array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
Chris@0 261 }
Chris@0 262
Chris@0 263 /**
Chris@0 264 * Removes a Cache-Control directive.
Chris@0 265 *
Chris@0 266 * @param string $key The Cache-Control directive
Chris@0 267 */
Chris@0 268 public function removeCacheControlDirective($key)
Chris@0 269 {
Chris@0 270 unset($this->cacheControl[$key]);
Chris@0 271
Chris@0 272 $this->set('Cache-Control', $this->getCacheControlHeader());
Chris@0 273 }
Chris@0 274
Chris@0 275 /**
Chris@0 276 * Returns an iterator for headers.
Chris@0 277 *
Chris@0 278 * @return \ArrayIterator An \ArrayIterator instance
Chris@0 279 */
Chris@0 280 public function getIterator()
Chris@0 281 {
Chris@0 282 return new \ArrayIterator($this->headers);
Chris@0 283 }
Chris@0 284
Chris@0 285 /**
Chris@0 286 * Returns the number of headers.
Chris@0 287 *
Chris@0 288 * @return int The number of headers
Chris@0 289 */
Chris@0 290 public function count()
Chris@0 291 {
Chris@17 292 return \count($this->headers);
Chris@0 293 }
Chris@0 294
Chris@0 295 protected function getCacheControlHeader()
Chris@0 296 {
Chris@17 297 $parts = [];
Chris@0 298 ksort($this->cacheControl);
Chris@0 299 foreach ($this->cacheControl as $key => $value) {
Chris@0 300 if (true === $value) {
Chris@0 301 $parts[] = $key;
Chris@0 302 } else {
Chris@0 303 if (preg_match('#[^a-zA-Z0-9._-]#', $value)) {
Chris@0 304 $value = '"'.$value.'"';
Chris@0 305 }
Chris@0 306
Chris@0 307 $parts[] = "$key=$value";
Chris@0 308 }
Chris@0 309 }
Chris@0 310
Chris@0 311 return implode(', ', $parts);
Chris@0 312 }
Chris@0 313
Chris@0 314 /**
Chris@0 315 * Parses a Cache-Control HTTP header.
Chris@0 316 *
Chris@0 317 * @param string $header The value of the Cache-Control HTTP header
Chris@0 318 *
Chris@0 319 * @return array An array representing the attribute values
Chris@0 320 */
Chris@0 321 protected function parseCacheControl($header)
Chris@0 322 {
Chris@17 323 $cacheControl = [];
Chris@0 324 preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER);
Chris@0 325 foreach ($matches as $match) {
Chris@0 326 $cacheControl[strtolower($match[1])] = isset($match[3]) ? $match[3] : (isset($match[2]) ? $match[2] : true);
Chris@0 327 }
Chris@0 328
Chris@0 329 return $cacheControl;
Chris@0 330 }
Chris@0 331 }