1: <?php
2: /**
3: * Slim - a micro PHP 5 framework
4: *
5: * @author Josh Lockhart <info@slimframework.com>
6: * @copyright 2011 Josh Lockhart
7: * @link http://www.slimframework.com
8: * @license http://www.slimframework.com/license
9: * @version 2.2.0
10: * @package Slim
11: *
12: * MIT LICENSE
13: *
14: * Permission is hereby granted, free of charge, to any person obtaining
15: * a copy of this software and associated documentation files (the
16: * "Software"), to deal in the Software without restriction, including
17: * without limitation the rights to use, copy, modify, merge, publish,
18: * distribute, sublicense, and/or sell copies of the Software, and to
19: * permit persons to whom the Software is furnished to do so, subject to
20: * the following conditions:
21: *
22: * The above copyright notice and this permission notice shall be
23: * included in all copies or substantial portions of the Software.
24: *
25: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26: * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28: * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29: * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30: * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31: * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32: */
33: namespace Slim\Http;
34:
35: /**
36: * HTTP Headers
37: *
38: * This class is an abstraction of the HTTP response headers and
39: * provides array access to the header list while automatically
40: * stores and retrieves headers with lowercase canonical keys regardless
41: * of the input format.
42: *
43: * This class also implements the `Iterator` and `Countable`
44: * interfaces for even more convenient usage.
45: *
46: * @package Slim
47: * @author Josh Lockhart
48: * @since 1.6.0
49: */
50: class Headers implements \ArrayAccess, \Iterator, \Countable
51: {
52: /**
53: * @var array HTTP headers
54: */
55: protected $headers;
56:
57: /**
58: * @var array Map canonical header name to original header name
59: */
60: protected $map;
61:
62: /**
63: * Constructor
64: * @param array $headers
65: */
66: public function __construct($headers = array())
67: {
68: $this->merge($headers);
69: }
70:
71: /**
72: * Merge Headers
73: * @param array $headers
74: */
75: public function merge($headers)
76: {
77: foreach ($headers as $name => $value) {
78: $this[$name] = $value;
79: }
80: }
81:
82: /**
83: * Transform header name into canonical form
84: * @param string $name
85: * @return string
86: */
87: protected function canonical($name)
88: {
89: return strtolower(trim($name));
90: }
91:
92: /**
93: * Array Access: Offset Exists
94: */
95: public function offsetExists($offset)
96: {
97: return isset($this->headers[$this->canonical($offset)]);
98: }
99:
100: /**
101: * Array Access: Offset Get
102: */
103: public function offsetGet($offset)
104: {
105: $canonical = $this->canonical($offset);
106: if (isset($this->headers[$canonical])) {
107: return $this->headers[$canonical];
108: } else {
109: return null;
110: }
111: }
112:
113: /**
114: * Array Access: Offset Set
115: */
116: public function offsetSet($offset, $value)
117: {
118: $canonical = $this->canonical($offset);
119: $this->headers[$canonical] = $value;
120: $this->map[$canonical] = $offset;
121: }
122:
123: /**
124: * Array Access: Offset Unset
125: */
126: public function offsetUnset($offset)
127: {
128: $canonical = $this->canonical($offset);
129: unset($this->headers[$canonical], $this->map[$canonical]);
130: }
131:
132: /**
133: * Countable: Count
134: */
135: public function count()
136: {
137: return count($this->headers);
138: }
139:
140: /**
141: * Iterator: Rewind
142: */
143: public function rewind()
144: {
145: reset($this->headers);
146: }
147:
148: /**
149: * Iterator: Current
150: */
151: public function current()
152: {
153: return current($this->headers);
154: }
155:
156: /**
157: * Iterator: Key
158: */
159: public function key()
160: {
161: $key = key($this->headers);
162:
163: return $this->map[$key];
164: }
165:
166: /**
167: * Iterator: Next
168: */
169: public function next()
170: {
171: return next($this->headers);
172: }
173:
174: /**
175: * Iterator: Valid
176: */
177: public function valid()
178: {
179: return current($this->headers) !== false;
180: }
181: }
182: