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