Added the zend framework 2 library, the path is specified in line no.26 in zend_modul...
[openemr.git] / interface / modules / zend_modules / library / Zend / Http / Headers.php
blob6843fe12a92a8ed9874749b7f386342ac8c9c9f3
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
10 namespace Zend\Http;
12 use ArrayIterator;
13 use Countable;
14 use Iterator;
15 use Traversable;
16 use Zend\Http\HeaderLoader;
17 use Zend\Loader\PluginClassLocator;
19 /**
20 * Basic HTTP headers collection functionality
21 * Handles aggregation of headers
23 * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
25 class Headers implements Countable, Iterator
27 /**
28 * @var PluginClassLoader
30 protected $pluginClassLoader = null;
32 /**
33 * @var array key names for $headers array
35 protected $headersKeys = array();
37 /**
38 * @var array Array of header array information or Header instances
40 protected $headers = array();
42 /**
43 * Populates headers from string representation
45 * Parses a string for headers, and aggregates them, in order, in the
46 * current instance, primarily as strings until they are needed (they
47 * will be lazy loaded)
49 * @param string $string
50 * @return Headers
51 * @throws Exception\RuntimeException
53 public static function fromString($string)
55 $headers = new static();
56 $current = array();
58 // iterate the header lines, some might be continuations
59 foreach (explode("\r\n", $string) as $line) {
61 // check if a header name is present
62 if (preg_match('/^(?P<name>[^()><@,;:\"\\/\[\]?=}{ \t]+):.*$/', $line, $matches)) {
63 if ($current) {
64 // a header name was present, then store the current complete line
65 $headers->headersKeys[] = static::createKey($current['name']);
66 $headers->headers[] = $current;
68 $current = array(
69 'name' => $matches['name'],
70 'line' => trim($line)
72 } elseif (preg_match('/^\s+.*$/', $line, $matches)) {
73 // continuation: append to current line
74 $current['line'] .= trim($line);
75 } elseif (preg_match('/^\s*$/', $line)) {
76 // empty line indicates end of headers
77 break;
78 } else {
79 // Line does not match header format!
80 throw new Exception\RuntimeException(sprintf(
81 'Line "%s"does not match header format!',
82 $line
83 ));
86 if ($current) {
87 $headers->headersKeys[] = static::createKey($current['name']);
88 $headers->headers[] = $current;
90 return $headers;
93 /**
94 * Set an alternate implementation for the PluginClassLoader
96 * @param \Zend\Loader\PluginClassLocator $pluginClassLoader
97 * @return Headers
99 public function setPluginClassLoader(PluginClassLocator $pluginClassLoader)
101 $this->pluginClassLoader = $pluginClassLoader;
102 return $this;
106 * Return an instance of a PluginClassLocator, lazyload and inject map if necessary
108 * @return PluginClassLocator
110 public function getPluginClassLoader()
112 if ($this->pluginClassLoader === null) {
113 $this->pluginClassLoader = new HeaderLoader();
115 return $this->pluginClassLoader;
119 * Add many headers at once
121 * Expects an array (or Traversable object) of type/value pairs.
123 * @param array|Traversable $headers
124 * @return Headers
125 * @throws Exception\InvalidArgumentException
127 public function addHeaders($headers)
129 if (!is_array($headers) && !$headers instanceof Traversable) {
130 throw new Exception\InvalidArgumentException(sprintf(
131 'Expected array or Traversable; received "%s"',
132 (is_object($headers) ? get_class($headers) : gettype($headers))
136 foreach ($headers as $name => $value) {
137 if (is_int($name)) {
138 if (is_string($value)) {
139 $this->addHeaderLine($value);
140 } elseif (is_array($value) && count($value) == 1) {
141 $this->addHeaderLine(key($value), current($value));
142 } elseif (is_array($value) && count($value) == 2) {
143 $this->addHeaderLine($value[0], $value[1]);
144 } elseif ($value instanceof Header\HeaderInterface) {
145 $this->addHeader($value);
147 } elseif (is_string($name)) {
148 $this->addHeaderLine($name, $value);
153 return $this;
157 * Add a raw header line, either in name => value, or as a single string 'name: value'
159 * This method allows for lazy-loading in that the parsing and instantiation of Header object
160 * will be delayed until they are retrieved by either get() or current()
162 * @throws Exception\InvalidArgumentException
163 * @param string $headerFieldNameOrLine
164 * @param string $fieldValue optional
165 * @return Headers
167 public function addHeaderLine($headerFieldNameOrLine, $fieldValue = null)
169 $matches = null;
170 if (preg_match('/^(?P<name>[^()><@,;:\"\\/\[\]?=}{ \t]+):.*$/', $headerFieldNameOrLine, $matches)
171 && $fieldValue === null) {
172 // is a header
173 $headerName = $matches['name'];
174 $headerKey = static::createKey($matches['name']);
175 $line = $headerFieldNameOrLine;
176 } elseif ($fieldValue === null) {
177 throw new Exception\InvalidArgumentException('A field name was provided without a field value');
178 } else {
179 $headerName = $headerFieldNameOrLine;
180 $headerKey = static::createKey($headerFieldNameOrLine);
181 if (is_array($fieldValue)) {
182 $fieldValue = implode(', ', $fieldValue);
184 $line = $headerFieldNameOrLine . ': ' . $fieldValue;
187 $this->headersKeys[] = $headerKey;
188 $this->headers[] = array('name' => $headerName, 'line' => $line);
190 return $this;
194 * Add a Header to this container, for raw values @see addHeaderLine() and addHeaders()
196 * @param Header\HeaderInterface $header
197 * @return Headers
199 public function addHeader(Header\HeaderInterface $header)
201 $this->headersKeys[] = static::createKey($header->getFieldName());
202 $this->headers[] = $header;
204 return $this;
208 * Remove a Header from the container
210 * @param Header\HeaderInterface $header
211 * @return bool
213 public function removeHeader(Header\HeaderInterface $header)
215 $index = array_search($header, $this->headers, true);
216 if ($index !== false) {
217 unset($this->headersKeys[$index]);
218 unset($this->headers[$index]);
220 return true;
222 return false;
226 * Clear all headers
228 * Removes all headers from queue
230 * @return Headers
232 public function clearHeaders()
234 $this->headers = $this->headersKeys = array();
235 return $this;
239 * Get all headers of a certain name/type
241 * @param string $name
242 * @return bool|Header\HeaderInterface|ArrayIterator
244 public function get($name)
246 $key = static::createKey($name);
247 if (!in_array($key, $this->headersKeys)) {
248 return false;
251 $class = ($this->getPluginClassLoader()->load($key)) ?: 'Zend\Http\Header\GenericHeader';
253 if (in_array('Zend\Http\Header\MultipleHeaderInterface', class_implements($class, true))) {
254 $headers = array();
255 foreach (array_keys($this->headersKeys, $key) as $index) {
256 if (is_array($this->headers[$index])) {
257 $this->lazyLoadHeader($index);
260 foreach (array_keys($this->headersKeys, $key) as $index) {
261 $headers[] = $this->headers[$index];
263 return new ArrayIterator($headers);
266 $index = array_search($key, $this->headersKeys);
267 if ($index === false) {
268 return false;
271 if (is_array($this->headers[$index])) {
272 return $this->lazyLoadHeader($index);
274 return $this->headers[$index];
278 * Test for existence of a type of header
280 * @param string $name
281 * @return bool
283 public function has($name)
285 return (in_array(static::createKey($name), $this->headersKeys));
289 * Advance the pointer for this object as an iterator
291 * @return void
293 public function next()
295 next($this->headers);
299 * Return the current key for this object as an iterator
301 * @return mixed
303 public function key()
305 return (key($this->headers));
309 * Is this iterator still valid?
311 * @return bool
313 public function valid()
315 return (current($this->headers) !== false);
319 * Reset the internal pointer for this object as an iterator
321 * @return void
323 public function rewind()
325 reset($this->headers);
329 * Return the current value for this iterator, lazy loading it if need be
331 * @return array|Header\HeaderInterface
333 public function current()
335 $current = current($this->headers);
336 if (is_array($current)) {
337 $current = $this->lazyLoadHeader(key($this->headers));
339 return $current;
343 * Return the number of headers in this contain, if all headers have not been parsed, actual count could
344 * increase if MultipleHeader objects exist in the Request/Response. If you need an exact count, iterate
346 * @return int count of currently known headers
348 public function count()
350 return count($this->headers);
354 * Render all headers at once
356 * This method handles the normal iteration of headers; it is up to the
357 * concrete classes to prepend with the appropriate status/request line.
359 * @return string
361 public function toString()
363 $headers = '';
364 foreach ($this->toArray() as $fieldName => $fieldValue) {
365 if (is_array($fieldValue)) {
366 // Handle multi-value headers
367 foreach ($fieldValue as $value) {
368 $headers .= $fieldName . ': ' . $value . "\r\n";
370 continue;
372 // Handle single-value headers
373 $headers .= $fieldName . ': ' . $fieldValue . "\r\n";
375 return $headers;
379 * Return the headers container as an array
381 * @todo determine how to produce single line headers, if they are supported
382 * @return array
384 public function toArray()
386 $headers = array();
387 /* @var $header Header\HeaderInterface */
388 foreach ($this->headers as $header) {
389 if ($header instanceof Header\MultipleHeaderInterface) {
390 $name = $header->getFieldName();
391 if (!isset($headers[$name])) {
392 $headers[$name] = array();
394 $headers[$name][] = $header->getFieldValue();
395 } elseif ($header instanceof Header\HeaderInterface) {
396 $headers[$header->getFieldName()] = $header->getFieldValue();
397 } else {
398 $matches = null;
399 preg_match('/^(?P<name>[^()><@,;:\"\\/\[\]?=}{ \t]+):\s*(?P<value>.*)$/', $header['line'], $matches);
400 if ($matches) {
401 $headers[$matches['name']] = $matches['value'];
405 return $headers;
409 * By calling this, it will force parsing and loading of all headers, after this count() will be accurate
411 * @return bool
413 public function forceLoading()
415 foreach ($this as $item) {
416 // $item should now be loaded
418 return true;
422 * @param $index
423 * @return mixed|void
425 protected function lazyLoadHeader($index)
427 $current = $this->headers[$index];
429 $key = $this->headersKeys[$index];
430 /* @var $class Header\HeaderInterface */
431 $class = ($this->getPluginClassLoader()->load($key)) ?: 'Zend\Http\Header\GenericHeader';
433 $headers = $class::fromString($current['line']);
434 if (is_array($headers)) {
435 $this->headers[$index] = $current = array_shift($headers);
436 foreach ($headers as $header) {
437 $this->headersKeys[] = $key;
438 $this->headers[] = $header;
440 return $current;
443 $this->headers[$index] = $current = $headers;
444 return $current;
448 * Create array key from header name
450 * @param string $name
451 * @return string
453 protected static function createKey($name)
455 return str_replace(array('-', '_', ' ', '.'), '', strtolower($name));