/src/Symfony/Component/HttpFoundation/HeaderBag.php

https://github.com/fernanDOTdo/symfony · PHP · 320 lines · 157 code · 42 blank · 121 comment · 16 complexity · ff952fa6803a74a624074b51900f7392 MD5 · raw file

  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
  17. {
  18. protected $headers;
  19. protected $cookies;
  20. protected $cacheControl;
  21. /**
  22. * Constructor.
  23. *
  24. * @param array $headers An array of HTTP headers
  25. */
  26. public function __construct(array $headers = array())
  27. {
  28. $this->cacheControl = array();
  29. $this->cookies = array();
  30. $this->headers = array();
  31. foreach ($headers as $key => $values) {
  32. $this->set($key, $values);
  33. }
  34. }
  35. /**
  36. * Returns the headers.
  37. *
  38. * @return array An array of headers
  39. */
  40. public function all()
  41. {
  42. return $this->headers;
  43. }
  44. /**
  45. * Returns the parameter keys.
  46. *
  47. * @return array An array of parameter keys
  48. */
  49. public function keys()
  50. {
  51. return array_keys($this->headers);
  52. }
  53. /**
  54. * Replaces the current HTTP headers by a new set.
  55. *
  56. * @param array $headers An array of HTTP headers
  57. */
  58. public function replace(array $headers = array())
  59. {
  60. $this->headers = array();
  61. $this->add($headers);
  62. }
  63. /**
  64. * Adds new headers the current HTTP headers set.
  65. *
  66. * @param array $headers An array of HTTP headers
  67. */
  68. public function add(array $headers)
  69. {
  70. foreach ($headers as $key => $values) {
  71. $this->set($key, $values);
  72. }
  73. }
  74. /**
  75. * Returns a header value by name.
  76. *
  77. * @param string $key The header name
  78. * @param mixed $default The default value
  79. * @param Boolean $first Whether to return the first value or all header values
  80. *
  81. * @return string|array The first header value if $first is true, an array of values otherwise
  82. */
  83. public function get($key, $default = null, $first = true)
  84. {
  85. $key = strtr(strtolower($key), '_', '-');
  86. if (!array_key_exists($key, $this->headers)) {
  87. if (null === $default) {
  88. return $first ? null : array();
  89. }
  90. return $first ? $default : array($default);
  91. }
  92. if ($first) {
  93. return count($this->headers[$key]) ? $this->headers[$key][0] : $default;
  94. }
  95. return $this->headers[$key];
  96. }
  97. /**
  98. * Sets a header by name.
  99. *
  100. * @param string $key The key
  101. * @param string|array $values The value or an array of values
  102. * @param Boolean $replace Whether to replace the actual value of not (true by default)
  103. */
  104. public function set($key, $values, $replace = true)
  105. {
  106. $key = strtr(strtolower($key), '_', '-');
  107. if (!is_array($values)) {
  108. $values = array($values);
  109. }
  110. if (true === $replace || !isset($this->headers[$key])) {
  111. $this->headers[$key] = $values;
  112. } else {
  113. $this->headers[$key] = array_merge($this->headers[$key], $values);
  114. }
  115. if ('cache-control' === $key) {
  116. $this->cacheControl = $this->parseCacheControl($values[0]);
  117. }
  118. }
  119. /**
  120. * Returns true if the HTTP header is defined.
  121. *
  122. * @param string $key The HTTP header
  123. *
  124. * @return Boolean true if the parameter exists, false otherwise
  125. */
  126. public function has($key)
  127. {
  128. return array_key_exists(strtr(strtolower($key), '_', '-'), $this->headers);
  129. }
  130. /**
  131. * Returns true if the given HTTP header contains the given value.
  132. *
  133. * @param string $key The HTTP header name
  134. * @param string $value The HTTP value
  135. *
  136. * @return Boolean true if the value is contained in the header, false otherwise
  137. */
  138. public function contains($key, $value)
  139. {
  140. return in_array($value, $this->get($key, null, false));
  141. }
  142. /**
  143. * Removes a header.
  144. *
  145. * @param string $key The HTTP header name
  146. */
  147. public function remove($key)
  148. {
  149. $key = strtr(strtolower($key), '_', '-');
  150. unset($this->headers[$key]);
  151. if ('cache-control' === $key) {
  152. $this->cacheControl = array();
  153. }
  154. }
  155. /**
  156. * Sets a cookie.
  157. *
  158. * @param Cookie $cookie
  159. * @return void
  160. */
  161. public function setCookie(Cookie $cookie)
  162. {
  163. $this->cookies[$cookie->getName()] = $cookie;
  164. }
  165. /**
  166. * Removes a cookie from the array, but does not unset it in the browser
  167. *
  168. * @param string $name
  169. * @return void
  170. */
  171. public function removeCookie($name)
  172. {
  173. unset($this->cookies[$name]);
  174. }
  175. /**
  176. * Whether the array contains any cookie with this name
  177. *
  178. * @param string $name
  179. * @return Boolean
  180. */
  181. public function hasCookie($name)
  182. {
  183. return isset($this->cookies[$name]);
  184. }
  185. /**
  186. * Returns a cookie
  187. *
  188. * @param string $name
  189. *
  190. * @throws \InvalidArgumentException When the cookie does not exist
  191. *
  192. * @return Cookie
  193. */
  194. public function getCookie($name)
  195. {
  196. if (!$this->hasCookie($name)) {
  197. throw new \InvalidArgumentException(sprintf('There is no cookie with name "%s".', $name));
  198. }
  199. return $this->cookies[$name];
  200. }
  201. /**
  202. * Returns an array with all cookies
  203. *
  204. * @return array
  205. */
  206. public function getCookies()
  207. {
  208. return $this->cookies;
  209. }
  210. /**
  211. * Returns the HTTP header value converted to a date.
  212. *
  213. * @param string $key The parameter key
  214. * @param \DateTime $default The default value
  215. *
  216. * @return \DateTime The filtered value
  217. */
  218. public function getDate($key, \DateTime $default = null)
  219. {
  220. if (null === $value = $this->get($key)) {
  221. return $default;
  222. }
  223. if (false === $date = \DateTime::createFromFormat(DATE_RFC2822, $value)) {
  224. throw new \RuntimeException(sprintf('The %s HTTP header is not parseable (%s).', $key, $value));
  225. }
  226. return $date;
  227. }
  228. public function addCacheControlDirective($key, $value = true)
  229. {
  230. $this->cacheControl[$key] = $value;
  231. $this->set('Cache-Control', $this->getCacheControlHeader());
  232. }
  233. public function hasCacheControlDirective($key)
  234. {
  235. return array_key_exists($key, $this->cacheControl);
  236. }
  237. public function getCacheControlDirective($key)
  238. {
  239. return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null;
  240. }
  241. public function removeCacheControlDirective($key)
  242. {
  243. unset($this->cacheControl[$key]);
  244. $this->set('Cache-Control', $this->getCacheControlHeader());
  245. }
  246. protected function getCacheControlHeader()
  247. {
  248. $parts = array();
  249. ksort($this->cacheControl);
  250. foreach ($this->cacheControl as $key => $value) {
  251. if (true === $value) {
  252. $parts[] = $key;
  253. } else {
  254. if (preg_match('#[^a-zA-Z0-9._-]#', $value)) {
  255. $value = '"'.$value.'"';
  256. }
  257. $parts[] = "$key=$value";
  258. }
  259. }
  260. return implode(', ', $parts);
  261. }
  262. /**
  263. * Parses a Cache-Control HTTP header.
  264. *
  265. * @param string $header The value of the Cache-Control HTTP header
  266. *
  267. * @return array An array representing the attribute values
  268. */
  269. protected function parseCacheControl($header)
  270. {
  271. $cacheControl = array();
  272. preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER);
  273. foreach ($matches as $match) {
  274. $cacheControl[strtolower($match[1])] = isset($match[2]) && $match[2] ? $match[2] : (isset($match[3]) ? $match[3] : true);
  275. }
  276. return $cacheControl;
  277. }
  278. }