Response.php (14203B)
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.4.2 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 * Response 37 * 38 * This is a simple abstraction over top an HTTP response. This 39 * provides methods to set the HTTP status, the HTTP headers, 40 * and the HTTP body. 41 * 42 * @package Slim 43 * @author Josh Lockhart 44 * @since 1.0.0 45 */ 46 class Response implements \ArrayAccess, \Countable, \IteratorAggregate 47 { 48 /** 49 * @var int HTTP status code 50 */ 51 protected $status; 52 53 /** 54 * @var \Slim\Http\Headers 55 */ 56 public $headers; 57 58 /** 59 * @var \Slim\Http\Cookies 60 */ 61 public $cookies; 62 63 /** 64 * @var string HTTP response body 65 */ 66 protected $body; 67 68 /** 69 * @var int Length of HTTP response body 70 */ 71 protected $length; 72 73 /** 74 * @var array HTTP response codes and messages 75 */ 76 protected static $messages = array( 77 //Informational 1xx 78 100 => '100 Continue', 79 101 => '101 Switching Protocols', 80 //Successful 2xx 81 200 => '200 OK', 82 201 => '201 Created', 83 202 => '202 Accepted', 84 203 => '203 Non-Authoritative Information', 85 204 => '204 No Content', 86 205 => '205 Reset Content', 87 206 => '206 Partial Content', 88 //Redirection 3xx 89 300 => '300 Multiple Choices', 90 301 => '301 Moved Permanently', 91 302 => '302 Found', 92 303 => '303 See Other', 93 304 => '304 Not Modified', 94 305 => '305 Use Proxy', 95 306 => '306 (Unused)', 96 307 => '307 Temporary Redirect', 97 //Client Error 4xx 98 400 => '400 Bad Request', 99 401 => '401 Unauthorized', 100 402 => '402 Payment Required', 101 403 => '403 Forbidden', 102 404 => '404 Not Found', 103 405 => '405 Method Not Allowed', 104 406 => '406 Not Acceptable', 105 407 => '407 Proxy Authentication Required', 106 408 => '408 Request Timeout', 107 409 => '409 Conflict', 108 410 => '410 Gone', 109 411 => '411 Length Required', 110 412 => '412 Precondition Failed', 111 413 => '413 Request Entity Too Large', 112 414 => '414 Request-URI Too Long', 113 415 => '415 Unsupported Media Type', 114 416 => '416 Requested Range Not Satisfiable', 115 417 => '417 Expectation Failed', 116 418 => '418 I\'m a teapot', 117 422 => '422 Unprocessable Entity', 118 423 => '423 Locked', 119 //Server Error 5xx 120 500 => '500 Internal Server Error', 121 501 => '501 Not Implemented', 122 502 => '502 Bad Gateway', 123 503 => '503 Service Unavailable', 124 504 => '504 Gateway Timeout', 125 505 => '505 HTTP Version Not Supported' 126 ); 127 128 /** 129 * Constructor 130 * @param string $body The HTTP response body 131 * @param int $status The HTTP response status 132 * @param \Slim\Http\Headers|array $headers The HTTP response headers 133 */ 134 public function __construct($body = '', $status = 200, $headers = array()) 135 { 136 $this->setStatus($status); 137 $this->headers = new \Slim\Http\Headers(array('Content-Type' => 'text/html')); 138 $this->headers->replace($headers); 139 $this->cookies = new \Slim\Http\Cookies(); 140 $this->write($body); 141 } 142 143 public function getStatus() 144 { 145 return $this->status; 146 } 147 148 public function setStatus($status) 149 { 150 $this->status = (int)$status; 151 } 152 153 /** 154 * DEPRECATION WARNING! Use `getStatus` or `setStatus` instead. 155 * 156 * Get and set status 157 * @param int|null $status 158 * @return int 159 */ 160 public function status($status = null) 161 { 162 if (!is_null($status)) { 163 $this->status = (int) $status; 164 } 165 166 return $this->status; 167 } 168 169 /** 170 * DEPRECATION WARNING! Access `headers` property directly. 171 * 172 * Get and set header 173 * @param string $name Header name 174 * @param string|null $value Header value 175 * @return string Header value 176 */ 177 public function header($name, $value = null) 178 { 179 if (!is_null($value)) { 180 $this->headers->set($name, $value); 181 } 182 183 return $this->headers->get($name); 184 } 185 186 /** 187 * DEPRECATION WARNING! Access `headers` property directly. 188 * 189 * Get headers 190 * @return \Slim\Http\Headers 191 */ 192 public function headers() 193 { 194 return $this->headers; 195 } 196 197 public function getBody() 198 { 199 return $this->body; 200 } 201 202 public function setBody($content) 203 { 204 $this->write($content, true); 205 } 206 207 /** 208 * DEPRECATION WARNING! use `getBody` or `setBody` instead. 209 * 210 * Get and set body 211 * @param string|null $body Content of HTTP response body 212 * @return string 213 */ 214 public function body($body = null) 215 { 216 if (!is_null($body)) { 217 $this->write($body, true); 218 } 219 220 return $this->body; 221 } 222 223 /** 224 * Append HTTP response body 225 * @param string $body Content to append to the current HTTP response body 226 * @param bool $replace Overwrite existing response body? 227 * @return string The updated HTTP response body 228 */ 229 public function write($body, $replace = false) 230 { 231 if ($replace) { 232 $this->body = $body; 233 } else { 234 $this->body .= (string)$body; 235 } 236 $this->length = strlen($this->body); 237 238 return $this->body; 239 } 240 241 public function getLength() 242 { 243 return $this->length; 244 } 245 246 /** 247 * DEPRECATION WARNING! Use `getLength` or `write` or `body` instead. 248 * 249 * Get and set length 250 * @param int|null $length 251 * @return int 252 */ 253 public function length($length = null) 254 { 255 if (!is_null($length)) { 256 $this->length = (int) $length; 257 } 258 259 return $this->length; 260 } 261 262 /** 263 * Finalize 264 * 265 * This prepares this response and returns an array 266 * of [status, headers, body]. This array is passed to outer middleware 267 * if available or directly to the Slim run method. 268 * 269 * @return array[int status, array headers, string body] 270 */ 271 public function finalize() 272 { 273 // Prepare response 274 if (in_array($this->status, array(204, 304))) { 275 $this->headers->remove('Content-Type'); 276 $this->headers->remove('Content-Length'); 277 $this->setBody(''); 278 } 279 280 return array($this->status, $this->headers, $this->body); 281 } 282 283 /** 284 * DEPRECATION WARNING! Access `cookies` property directly. 285 * 286 * Set cookie 287 * 288 * Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie` 289 * header on its own and delegates this responsibility to the `Slim_Http_Util` class. This 290 * response's header is passed by reference to the utility class and is directly modified. By not 291 * relying on PHP's native implementation, Slim allows middleware the opportunity to massage or 292 * analyze the raw header before the response is ultimately delivered to the HTTP client. 293 * 294 * @param string $name The name of the cookie 295 * @param string|array $value If string, the value of cookie; if array, properties for 296 * cookie including: value, expire, path, domain, secure, httponly 297 */ 298 public function setCookie($name, $value) 299 { 300 // Util::setCookieHeader($this->header, $name, $value); 301 $this->cookies->set($name, $value); 302 } 303 304 /** 305 * DEPRECATION WARNING! Access `cookies` property directly. 306 * 307 * Delete cookie 308 * 309 * Instead of using PHP's `setcookie()` function, Slim manually constructs the HTTP `Set-Cookie` 310 * header on its own and delegates this responsibility to the `Slim_Http_Util` class. This 311 * response's header is passed by reference to the utility class and is directly modified. By not 312 * relying on PHP's native implementation, Slim allows middleware the opportunity to massage or 313 * analyze the raw header before the response is ultimately delivered to the HTTP client. 314 * 315 * This method will set a cookie with the given name that has an expiration time in the past; this will 316 * prompt the HTTP client to invalidate and remove the client-side cookie. Optionally, you may 317 * also pass a key/value array as the second argument. If the "domain" key is present in this 318 * array, only the Cookie with the given name AND domain will be removed. The invalidating cookie 319 * sent with this response will adopt all properties of the second argument. 320 * 321 * @param string $name The name of the cookie 322 * @param array $settings Properties for cookie including: value, expire, path, domain, secure, httponly 323 */ 324 public function deleteCookie($name, $settings = array()) 325 { 326 $this->cookies->remove($name, $settings); 327 // Util::deleteCookieHeader($this->header, $name, $value); 328 } 329 330 /** 331 * Redirect 332 * 333 * This method prepares this response to return an HTTP Redirect response 334 * to the HTTP client. 335 * 336 * @param string $url The redirect destination 337 * @param int $status The redirect HTTP status code 338 */ 339 public function redirect ($url, $status = 302) 340 { 341 $this->setStatus($status); 342 $this->headers->set('Location', $url); 343 } 344 345 /** 346 * Helpers: Empty? 347 * @return bool 348 */ 349 public function isEmpty() 350 { 351 return in_array($this->status, array(201, 204, 304)); 352 } 353 354 /** 355 * Helpers: Informational? 356 * @return bool 357 */ 358 public function isInformational() 359 { 360 return $this->status >= 100 && $this->status < 200; 361 } 362 363 /** 364 * Helpers: OK? 365 * @return bool 366 */ 367 public function isOk() 368 { 369 return $this->status === 200; 370 } 371 372 /** 373 * Helpers: Successful? 374 * @return bool 375 */ 376 public function isSuccessful() 377 { 378 return $this->status >= 200 && $this->status < 300; 379 } 380 381 /** 382 * Helpers: Redirect? 383 * @return bool 384 */ 385 public function isRedirect() 386 { 387 return in_array($this->status, array(301, 302, 303, 307)); 388 } 389 390 /** 391 * Helpers: Redirection? 392 * @return bool 393 */ 394 public function isRedirection() 395 { 396 return $this->status >= 300 && $this->status < 400; 397 } 398 399 /** 400 * Helpers: Forbidden? 401 * @return bool 402 */ 403 public function isForbidden() 404 { 405 return $this->status === 403; 406 } 407 408 /** 409 * Helpers: Not Found? 410 * @return bool 411 */ 412 public function isNotFound() 413 { 414 return $this->status === 404; 415 } 416 417 /** 418 * Helpers: Client error? 419 * @return bool 420 */ 421 public function isClientError() 422 { 423 return $this->status >= 400 && $this->status < 500; 424 } 425 426 /** 427 * Helpers: Server Error? 428 * @return bool 429 */ 430 public function isServerError() 431 { 432 return $this->status >= 500 && $this->status < 600; 433 } 434 435 /** 436 * DEPRECATION WARNING! ArrayAccess interface will be removed from \Slim\Http\Response. 437 * Iterate `headers` or `cookies` properties directly. 438 */ 439 440 /** 441 * Array Access: Offset Exists 442 */ 443 public function offsetExists($offset) 444 { 445 return isset($this->headers[$offset]); 446 } 447 448 /** 449 * Array Access: Offset Get 450 */ 451 public function offsetGet($offset) 452 { 453 return $this->headers[$offset]; 454 } 455 456 /** 457 * Array Access: Offset Set 458 */ 459 public function offsetSet($offset, $value) 460 { 461 $this->headers[$offset] = $value; 462 } 463 464 /** 465 * Array Access: Offset Unset 466 */ 467 public function offsetUnset($offset) 468 { 469 unset($this->headers[$offset]); 470 } 471 472 /** 473 * DEPRECATION WARNING! Countable interface will be removed from \Slim\Http\Response. 474 * Call `count` on `headers` or `cookies` properties directly. 475 * 476 * Countable: Count 477 */ 478 public function count() 479 { 480 return count($this->headers); 481 } 482 483 /** 484 * DEPRECATION WARNING! IteratorAggregate interface will be removed from \Slim\Http\Response. 485 * Iterate `headers` or `cookies` properties directly. 486 * 487 * Get Iterator 488 * 489 * This returns the contained `\Slim\Http\Headers` instance which 490 * is itself iterable. 491 * 492 * @return \Slim\Http\Headers 493 */ 494 public function getIterator() 495 { 496 return $this->headers->getIterator(); 497 } 498 499 /** 500 * Get message for HTTP status code 501 * @param int $status 502 * @return string|null 503 */ 504 public static function getMessageForCode($status) 505 { 506 if (isset(self::$messages[$status])) { 507 return self::$messages[$status]; 508 } else { 509 return null; 510 } 511 } 512 }