You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PlexShare/fuel/core/classes/response.php

385 lines
8.9 KiB

<?php
/**
* Part of the Fuel framework.
*
* @package Fuel
* @version 1.8
* @author Fuel Development Team
* @license MIT License
* @copyright 2010 - 2016 Fuel Development Team
* @link http://fuelphp.com
*/
namespace Fuel\Core;
class Response
{
/**
* @var array An array of status codes and messages
*
* See http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
* for the complete and approved list, and links to the RFC's that define them
*/
public static $statuses = array(
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
208 => 'Already Reported',
226 => 'IM Used',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
308 => 'Permanent Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
418 => 'I\'m a Teapot',
422 => 'Unprocessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
426 => 'Upgrade Required',
428 => 'Precondition Required',
429 => 'Too Many Requests',
431 => 'Request Header Fields Too Large',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage',
508 => 'Loop Detected',
509 => 'Bandwidth Limit Exceeded',
510 => 'Not Extended',
511 => 'Network Authentication Required',
);
/**
* Creates an instance of the Response class
*
* @param string $body The response body
* @param int $status The HTTP response status for this response
* @param array $headers Array of HTTP headers for this response
*
* @return Response
*/
public static function forge($body = null, $status = 200, array $headers = array())
{
$response = new static($body, $status, $headers);
// fire any response created events
\Event::instance()->has_events('response_created') and \Event::instance()->trigger('response_created', '', 'none');
return $response;
}
/**
* Redirects to another uri/url. Sets the redirect header,
* sends the headers and exits. Can redirect via a Location header
* or using a refresh header.
*
* The refresh header works better on certain servers like IIS.
*
* @param string $url The url
* @param string $method The redirect method
* @param int $code The redirect status code
*
* @return void
*/
public static function redirect($url = '', $method = 'location', $code = 302)
{
$response = new static;
$response->set_status($code);
if (strpos($url, '://') === false)
{
$url = $url !== '' ? \Uri::create($url) : \Uri::base();
}
if (\Config::get('response.redirect_with_wildcards', true))
{
strpos($url, '*') !== false and $url = \Uri::segment_replace($url);
}
if ($method == 'location')
{
$response->set_header('Location', $url);
}
elseif ($method == 'refresh')
{
$response->set_header('Refresh', '0;url='.$url);
}
else
{
return;
}
$response->send(true);
exit;
}
/**
* Redirects back to the previous page, if that page is within the current
* application. If not, it will redirect to the given url, and if none is
* given, back to the application root. If the current page is the application
* root, an exception is thrown
*
* @param string $url The url
* @param string $method The redirect method
* @param int $code The redirect status code
*
* @return void
*
* @throws \RuntimeException If it would redirect back to itself
*/
public static function redirect_back($url = '', $method = 'location', $code = 302)
{
// do we have a referrer?
if ($referrer = \Input::referrer())
{
// is it within our website? And not equal to the current url?
if (strpos($referrer, \Uri::base()) === 0 and $referrer != \Uri::current())
{
// redirect back to where we came from
static::redirect($referrer, $method, $code);
}
}
// make sure we're not redirecting back to ourself
if (\Uri::create($url) == \Uri::current())
{
throw new \RuntimeException('You can not redirect back here, it would result in a redirect loop!');
}
// no referrer or an external link, do a normal redirect
static::redirect($url, $method, $code);
}
/**
* @var int The HTTP status code
*/
public $status = 200;
/**
* @var array An array of HTTP headers
*/
public $headers = array();
/**
* @var string The content of the response
*/
public $body = null;
/**
* Sets up the response with a body and a status code.
*
* @param string $body The response body
* @param int $status The response status
* @param array $headers
*/
public function __construct($body = null, $status = 200, array $headers = array())
{
foreach ($headers as $k => $v)
{
$this->set_header($k, $v);
}
$this->body = $body;
$this->status = $status;
}
/**
* Sets the response status code
*
* @param int $status The status code
*
* @return Response
*/
public function set_status($status = 200)
{
$this->status = $status;
return $this;
}
/**
* Adds a header to the queue
*
* @param string $name The header name
* @param string $value The header value
* @param string|bool $replace Whether to replace existing value for the header, will never overwrite/be overwritten when false
*
* @return Response
*/
public function set_header($name, $value, $replace = true)
{
if ($replace)
{
$this->headers[$name] = $value;
}
else
{
$this->headers[] = array($name, $value);
}
return $this;
}
/**
* Adds multiple headers to the queue
*
* @param array $headers Assoc array with header name / value combinations
* @param string|bool $replace Whether to replace existing value for the header, will never overwrite/be overwritten when false
*
* @return Response
*/
public function set_headers($headers, $replace = true)
{
foreach ($headers as $key => $value)
{
$this->set_header($key, $value, $replace);
}
return $this;
}
/**
* Gets header information from the queue
*
* @param string $name The header name, or null for all headers
*
* @return mixed
*/
public function get_header($name = null)
{
if (func_num_args())
{
return isset($this->headers[$name]) ? $this->headers[$name] : null;
}
else
{
return $this->headers;
}
}
/**
* Sets (or returns) the body for the response
*
* @param string|bool $value The response content
*
* @return Response|string
*/
public function body($value = false)
{
if (func_num_args())
{
$this->body = $value;
return $this;
}
return $this->body;
}
/**
* Sends the headers if they haven't already been sent. Returns whether
* they were sent or not.
*
* @return bool
*/
public function send_headers()
{
if ( ! headers_sent())
{
// Send the protocol/status line first, FCGI servers need different status header
if ( ! empty($_SERVER['FCGI_SERVER_VERSION']))
{
header('Status: '.$this->status.' '.static::$statuses[$this->status]);
}
else
{
$protocol = \Input::server('SERVER_PROTOCOL') ? \Input::server('SERVER_PROTOCOL') : 'HTTP/1.1';
header($protocol.' '.$this->status.' '.static::$statuses[$this->status]);
}
foreach ($this->headers as $name => $value)
{
// Parse non-replace headers
if (is_int($name) and is_array($value))
{
isset($value[0]) and $name = $value[0];
isset($value[1]) and $value = $value[1];
}
// Create the header
is_string($name) and $value = "{$name}: {$value}";
// Send it
header($value, true);
}
return true;
}
return false;
}
/**
* Sends the response to the output buffer. Optionally will send the
* headers.
*
* @param bool $send_headers Whether or not to send the defined HTTP headers
*
* @return void
*/
public function send($send_headers = false)
{
$body = $this->__toString();
if ($send_headers)
{
$this->send_headers();
}
if ($this->body != null)
{
echo $body;
}
}
/**
* Returns the body as a string.
*
* @return string
*/
public function __toString()
{
return (string) $this->body;
}
}