HeaderCollection.php 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. <?php
  2. /**
  3. * @link https://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license https://www.yiiframework.com/license/
  6. */
  7. namespace yii\web;
  8. use yii\base\BaseObject;
  9. /**
  10. * HeaderCollection is used by [[Response]] to maintain the currently registered HTTP headers.
  11. *
  12. * @property-read int $count The number of headers in the collection.
  13. * @property-read \ArrayIterator $iterator An iterator for traversing the headers in the collection.
  14. *
  15. * @author Qiang Xue <qiang.xue@gmail.com>
  16. * @since 2.0
  17. */
  18. class HeaderCollection extends BaseObject implements \IteratorAggregate, \ArrayAccess, \Countable
  19. {
  20. /**
  21. * @var array the headers in this collection (indexed by the normalized header names)
  22. */
  23. private $_headers = [];
  24. /**
  25. * @var array the original names of the headers (indexed by the normalized header names)
  26. */
  27. private $_originalHeaderNames = [];
  28. /**
  29. * Returns an iterator for traversing the headers in the collection.
  30. * This method is required by the SPL interface [[\IteratorAggregate]].
  31. * It will be implicitly called when you use `foreach` to traverse the collection.
  32. * @return \ArrayIterator an iterator for traversing the headers in the collection.
  33. */
  34. #[\ReturnTypeWillChange]
  35. public function getIterator()
  36. {
  37. return new \ArrayIterator($this->_headers);
  38. }
  39. /**
  40. * Returns the number of headers in the collection.
  41. * This method is required by the SPL `Countable` interface.
  42. * It will be implicitly called when you use `count($collection)`.
  43. * @return int the number of headers in the collection.
  44. */
  45. #[\ReturnTypeWillChange]
  46. public function count()
  47. {
  48. return $this->getCount();
  49. }
  50. /**
  51. * Returns the number of headers in the collection.
  52. * @return int the number of headers in the collection.
  53. */
  54. #[\ReturnTypeWillChange]
  55. public function getCount()
  56. {
  57. return count($this->_headers);
  58. }
  59. /**
  60. * Returns the named header(s).
  61. * @param string $name the name of the header to return
  62. * @param mixed $default the value to return in case the named header does not exist
  63. * @param bool $first whether to only return the first header of the specified name.
  64. * If false, all headers of the specified name will be returned.
  65. * @return string|array|null the named header(s). If `$first` is true, a string will be returned;
  66. * If `$first` is false, an array will be returned.
  67. */
  68. public function get($name, $default = null, $first = true)
  69. {
  70. $normalizedName = strtolower($name);
  71. if (isset($this->_headers[$normalizedName])) {
  72. return $first ? reset($this->_headers[$normalizedName]) : $this->_headers[$normalizedName];
  73. }
  74. return $default;
  75. }
  76. /**
  77. * Adds a new header.
  78. * If there is already a header with the same name, it will be replaced.
  79. * @param string $name the name of the header
  80. * @param string $value the value of the header
  81. * @return $this the collection object itself
  82. */
  83. public function set($name, $value = '')
  84. {
  85. $normalizedName = strtolower($name);
  86. $this->_headers[$normalizedName] = (array) $value;
  87. $this->_originalHeaderNames[$normalizedName] = $name;
  88. return $this;
  89. }
  90. /**
  91. * Adds a new header.
  92. * If there is already a header with the same name, the new one will
  93. * be appended to it instead of replacing it.
  94. * @param string $name the name of the header
  95. * @param string $value the value of the header
  96. * @return $this the collection object itself
  97. */
  98. public function add($name, $value)
  99. {
  100. $normalizedName = strtolower($name);
  101. $this->_headers[$normalizedName][] = $value;
  102. if (!\array_key_exists($normalizedName, $this->_originalHeaderNames)) {
  103. $this->_originalHeaderNames[$normalizedName] = $name;
  104. }
  105. return $this;
  106. }
  107. /**
  108. * Sets a new header only if it does not exist yet.
  109. * If there is already a header with the same name, the new one will be ignored.
  110. * @param string $name the name of the header
  111. * @param string $value the value of the header
  112. * @return $this the collection object itself
  113. */
  114. public function setDefault($name, $value)
  115. {
  116. $normalizedName = strtolower($name);
  117. if (empty($this->_headers[$normalizedName])) {
  118. $this->_headers[$normalizedName][] = $value;
  119. $this->_originalHeaderNames[$normalizedName] = $name;
  120. }
  121. return $this;
  122. }
  123. /**
  124. * Returns a value indicating whether the named header exists.
  125. * @param string $name the name of the header
  126. * @return bool whether the named header exists
  127. */
  128. public function has($name)
  129. {
  130. return isset($this->_headers[strtolower($name)]);
  131. }
  132. /**
  133. * Removes a header.
  134. * @param string $name the name of the header to be removed.
  135. * @return array|null the value of the removed header. Null is returned if the header does not exist.
  136. */
  137. public function remove($name)
  138. {
  139. $normalizedName = strtolower($name);
  140. if (isset($this->_headers[$normalizedName])) {
  141. $value = $this->_headers[$normalizedName];
  142. unset($this->_headers[$normalizedName], $this->_originalHeaderNames[$normalizedName]);
  143. return $value;
  144. }
  145. return null;
  146. }
  147. /**
  148. * Removes all headers.
  149. */
  150. public function removeAll()
  151. {
  152. $this->_headers = [];
  153. $this->_originalHeaderNames = [];
  154. }
  155. /**
  156. * Returns the collection as a PHP array.
  157. * @return array the array representation of the collection.
  158. * The array keys are header names, and the array values are the corresponding header values.
  159. */
  160. public function toArray()
  161. {
  162. return $this->_headers;
  163. }
  164. /**
  165. * Returns the collection as a PHP array but instead of using normalized header names as keys (like [[toArray()]])
  166. * it uses original header names (case-sensitive).
  167. * @return array the array representation of the collection.
  168. * @since 2.0.45
  169. */
  170. public function toOriginalArray()
  171. {
  172. return \array_map(function ($normalizedName) {
  173. return $this->_headers[$normalizedName];
  174. }, \array_flip($this->_originalHeaderNames));
  175. }
  176. /**
  177. * Populates the header collection from an array.
  178. * @param array $array the headers to populate from
  179. * @since 2.0.3
  180. */
  181. public function fromArray(array $array)
  182. {
  183. foreach ($array as $name => $value) {
  184. $this->set($name, $value);
  185. }
  186. }
  187. /**
  188. * Returns whether there is a header with the specified name.
  189. * This method is required by the SPL interface [[\ArrayAccess]].
  190. * It is implicitly called when you use something like `isset($collection[$name])`.
  191. * @param string $name the header name
  192. * @return bool whether the named header exists
  193. */
  194. #[\ReturnTypeWillChange]
  195. public function offsetExists($name)
  196. {
  197. return $this->has($name);
  198. }
  199. /**
  200. * Returns the header with the specified name.
  201. * This method is required by the SPL interface [[\ArrayAccess]].
  202. * It is implicitly called when you use something like `$header = $collection[$name];`.
  203. * This is equivalent to [[get()]].
  204. * @param string $name the header name
  205. * @return string|null the header value with the specified name, null if the named header does not exist.
  206. */
  207. #[\ReturnTypeWillChange]
  208. public function offsetGet($name)
  209. {
  210. return $this->get($name);
  211. }
  212. /**
  213. * Adds the header to the collection.
  214. * This method is required by the SPL interface [[\ArrayAccess]].
  215. * It is implicitly called when you use something like `$collection[$name] = $header;`.
  216. * This is equivalent to [[add()]].
  217. * @param string $name the header name
  218. * @param string $value the header value to be added
  219. */
  220. #[\ReturnTypeWillChange]
  221. public function offsetSet($name, $value)
  222. {
  223. $this->set($name, $value);
  224. }
  225. /**
  226. * Removes the named header.
  227. * This method is required by the SPL interface [[\ArrayAccess]].
  228. * It is implicitly called when you use something like `unset($collection[$name])`.
  229. * This is equivalent to [[remove()]].
  230. * @param string $name the header name
  231. */
  232. #[\ReturnTypeWillChange]
  233. public function offsetUnset($name)
  234. {
  235. $this->remove($name);
  236. }
  237. }