annotate vendor/symfony/http-foundation/HeaderBag.php @ 0:4c8ae668cc8c

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