1<?php 2 3namespace Sabre\HTTP; 4 5/** 6 * This is the abstract base class for both the Request and Response objects. 7 * 8 * This object contains a few simple methods that are shared by both. 9 * 10 * @copyright Copyright (C) 2009-2015 fruux GmbH (https://fruux.com/). 11 * @author Evert Pot (http://evertpot.com/) 12 * @license http://sabre.io/license/ Modified BSD License 13 */ 14abstract class Message implements MessageInterface { 15 16 /** 17 * Request body 18 * 19 * This should be a stream resource 20 * 21 * @var resource 22 */ 23 protected $body; 24 25 /** 26 * Contains the list of HTTP headers 27 * 28 * @var array 29 */ 30 protected $headers = []; 31 32 /** 33 * HTTP message version (1.0 or 1.1) 34 * 35 * @var string 36 */ 37 protected $httpVersion = '1.1'; 38 39 /** 40 * Returns the body as a readable stream resource. 41 * 42 * Note that the stream may not be rewindable, and therefore may only be 43 * read once. 44 * 45 * @return resource 46 */ 47 function getBodyAsStream() { 48 49 $body = $this->getBody(); 50 if (is_string($body) || is_null($body)) { 51 $stream = fopen('php://temp', 'r+'); 52 fwrite($stream, $body); 53 rewind($stream); 54 return $stream; 55 } 56 return $body; 57 58 } 59 60 /** 61 * Returns the body as a string. 62 * 63 * Note that because the underlying data may be based on a stream, this 64 * method could only work correctly the first time. 65 * 66 * @return string 67 */ 68 function getBodyAsString() { 69 70 $body = $this->getBody(); 71 if (is_string($body)) { 72 return $body; 73 } 74 if (is_null($body)) { 75 return ''; 76 } 77 return stream_get_contents($body); 78 79 } 80 81 /** 82 * Returns the message body, as it's internal representation. 83 * 84 * This could be either a string or a stream. 85 * 86 * @return resource|string 87 */ 88 function getBody() { 89 90 return $this->body; 91 92 } 93 94 /** 95 * Replaces the body resource with a new stream or string. 96 * 97 * @param resource|string $body 98 */ 99 function setBody($body) { 100 101 $this->body = $body; 102 103 } 104 105 /** 106 * Returns all the HTTP headers as an array. 107 * 108 * Every header is returned as an array, with one or more values. 109 * 110 * @return array 111 */ 112 function getHeaders() { 113 114 $result = []; 115 foreach ($this->headers as $headerInfo) { 116 $result[$headerInfo[0]] = $headerInfo[1]; 117 } 118 return $result; 119 120 } 121 122 /** 123 * Will return true or false, depending on if a HTTP header exists. 124 * 125 * @param string $name 126 * @return bool 127 */ 128 function hasHeader($name) { 129 130 return isset($this->headers[strtolower($name)]); 131 132 } 133 134 /** 135 * Returns a specific HTTP header, based on it's name. 136 * 137 * The name must be treated as case-insensitive. 138 * If the header does not exist, this method must return null. 139 * 140 * If a header appeared more than once in a HTTP request, this method will 141 * concatenate all the values with a comma. 142 * 143 * Note that this not make sense for all headers. Some, such as 144 * `Set-Cookie` cannot be logically combined with a comma. In those cases 145 * you *should* use getHeaderAsArray(). 146 * 147 * @param string $name 148 * @return string|null 149 */ 150 function getHeader($name) { 151 152 $name = strtolower($name); 153 154 if (isset($this->headers[$name])) { 155 return implode(',', $this->headers[$name][1]); 156 } 157 return null; 158 159 } 160 161 /** 162 * Returns a HTTP header as an array. 163 * 164 * For every time the HTTP header appeared in the request or response, an 165 * item will appear in the array. 166 * 167 * If the header did not exists, this method will return an empty array. 168 * 169 * @param string $name 170 * @return string[] 171 */ 172 function getHeaderAsArray($name) { 173 174 $name = strtolower($name); 175 176 if (isset($this->headers[$name])) { 177 return $this->headers[$name][1]; 178 } 179 180 return []; 181 182 } 183 184 /** 185 * Updates a HTTP header. 186 * 187 * The case-sensitity of the name value must be retained as-is. 188 * 189 * If the header already existed, it will be overwritten. 190 * 191 * @param string $name 192 * @param string|string[] $value 193 * @return void 194 */ 195 function setHeader($name, $value) { 196 197 $this->headers[strtolower($name)] = [$name, (array)$value]; 198 199 } 200 201 /** 202 * Sets a new set of HTTP headers. 203 * 204 * The headers array should contain headernames for keys, and their value 205 * should be specified as either a string or an array. 206 * 207 * Any header that already existed will be overwritten. 208 * 209 * @param array $headers 210 * @return void 211 */ 212 function setHeaders(array $headers) { 213 214 foreach ($headers as $name => $value) { 215 $this->setHeader($name, $value); 216 } 217 218 } 219 220 /** 221 * Adds a HTTP header. 222 * 223 * This method will not overwrite any existing HTTP header, but instead add 224 * another value. Individual values can be retrieved with 225 * getHeadersAsArray. 226 * 227 * @param string $name 228 * @param string $value 229 * @return void 230 */ 231 function addHeader($name, $value) { 232 233 $lName = strtolower($name); 234 if (isset($this->headers[$lName])) { 235 $this->headers[$lName][1] = array_merge( 236 $this->headers[$lName][1], 237 (array)$value 238 ); 239 } else { 240 $this->headers[$lName] = [ 241 $name, 242 (array)$value 243 ]; 244 } 245 246 } 247 248 /** 249 * Adds a new set of HTTP headers. 250 * 251 * Any existing headers will not be overwritten. 252 * 253 * @param array $headers 254 * @return void 255 */ 256 function addHeaders(array $headers) { 257 258 foreach ($headers as $name => $value) { 259 $this->addHeader($name, $value); 260 } 261 262 } 263 264 265 /** 266 * Removes a HTTP header. 267 * 268 * The specified header name must be treated as case-insenstive. 269 * This method should return true if the header was successfully deleted, 270 * and false if the header did not exist. 271 * 272 * @return bool 273 */ 274 function removeHeader($name) { 275 276 $name = strtolower($name); 277 if (!isset($this->headers[$name])) { 278 return false; 279 } 280 unset($this->headers[$name]); 281 return true; 282 283 } 284 285 /** 286 * Sets the HTTP version. 287 * 288 * Should be 1.0 or 1.1. 289 * 290 * @param string $version 291 * @return void 292 */ 293 function setHttpVersion($version) { 294 295 $this->httpVersion = $version; 296 297 } 298 299 /** 300 * Returns the HTTP version. 301 * 302 * @return string 303 */ 304 function getHttpVersion() { 305 306 return $this->httpVersion; 307 308 } 309} 310