Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 174 lines (156 sloc) 5.229 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
<?php
/**
* Lithium: the most rad php framework
*
* @copyright Copyright 2012, Union of RAD (http://union-of-rad.org)
* @license http://opensource.org/licenses/bsd-license.php The BSD License
*/

namespace lithium\action;

/**
* A `Response` object is typically instantiated automatically by the `Controller`. It is assigned
* any headers set in the course of the request, as well as any content rendered by the
* `Controller`. Once completed, the `Controller` returns the `Response` object to the `Dispatcher`.
*
* The `Response` object is responsible for writing its body content to output, and writing any
* headers to the browser.
*
* @see lithium\action\Dispatcher
* @see lithium\action\Controller
*/
class Response extends \lithium\net\http\Response {

/**
* Classes used by Response.
*
* @var array
*/
protected $_classes = array(
'router' => 'lithium\net\http\Router',
'media' => 'lithium\net\http\Media'
);

protected $_autoConfig = array('classes' => 'merge');

public function __construct(array $config = array()) {
$defaults = array(
'buffer' => 8192,
'location' => null,
'status' => 0,
'request' => null,
'decode' => false
);
parent::__construct($config + $defaults);
}

protected function _init() {
parent::_init();
$config = $this->_config;
$this->status($config['status']);
unset($this->_config['status']);

if ($config['location']) {
$classes = $this->_classes;
$location = $classes['router']::match($config['location'], $config['request']);
$this->headers('Location', $location);
}
}

/**
* Controls how or whether the client browser and web proxies should cache this response.
*
* @param mixed $expires This can be a Unix timestamp indicating when the page expires, or a
* string indicating the relative time offset that a page should expire, i.e.
* `"+5 hours". Finally, `$expires` can be set to `false` to completely disable
* browser or proxy caching.
* @return void
*/
public function cache($expires) {
if ($expires === false) {
return $this->headers(array(
'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT',
'Cache-Control' => array(
'no-store, no-cache, must-revalidate',
'post-check=0, pre-check=0',
'max-age=0'
),
'Pragma' => 'no-cache'
));
}
$expires = is_int($expires) ? $expires : strtotime($expires);

return $this->headers(array(
'Expires' => gmdate('D, d M Y H:i:s', $expires) . ' GMT',
'Cache-Control' => 'max-age=' . ($expires - time()),
'Pragma' => 'cache'
));
}

/**
* Sets/Gets the content type. If `'type'` is null, the method will attempt to determine the
* type from the params, then from the environment setting
*
* @param string $type a full content type i.e. `'application/json'` or simple name `'json'`
* @return string A simple content type name, i.e. `'html'`, `'xml'`, `'json'`, etc., depending
* on the content type of the request.
*/
public function type($type = null) {
if ($type === null && $this->_type === null) {
$type = 'html';
}
return parent::type($type);
}

/**
* Render a response by writing headers and output. Output is echoed in chunks because of an
* issue where `echo` time increases exponentially on long message bodies.
*
* @return void
*/
public function render() {
$code = null;

if (isset($this->headers['location']) && $this->status['code'] === 200) {
$code = 302;
}
$this->_writeHeader($this->status($code) ?: $this->status(500));

foreach ($this->headers as $name => $value) {
$key = strtolower($name);

if ($key == 'location') {
$this->_writeHeader("Location: {$value}", $this->status['code']);
} elseif ($key == 'download') {
$this->_writeHeader('Content-Disposition: attachment; filename="' . $value . '"');
} elseif (is_array($value)) {
$this->_writeHeader(
array_map(function($v) use ($name) { return "{$name}: {$v}"; }, $value)
);
} elseif (!is_numeric($name)) {
$this->_writeHeader("{$name}: {$value}");
}
}
if ($code == 302 || $code == 204) {
return;
}
$chunked = $this->body(null, $this->_config);

foreach ($chunked as $chunk) {
echo $chunk;
}
}

/**
* Casts the Response object to a string. This doesn't actually return a string, but does
* a direct render and returns null.
*
* @return string An empty string.
*/
public function __toString() {
$this->render();
return '';
}

/**
* Writes raw headers to output.
*
* @param string|array $header Either a raw header string, or an array of header strings. Use
* an array if a single header must be written multiple times with different values.
* Otherwise, additional values for duplicate headers will overwrite previous values.
* @param integer $code Optional. If present, forces a specific HTTP response code. Used
* primarily in conjunction with the 'Location' header.
* @return void
*/
protected function _writeHeader($header, $code = null) {
if (is_array($header)) {
array_map(function($h) { header($h, false); }, $header);
return;
}
$code ? header($header, true, $code) : header($header, true);
}
}

?>
Something went wrong with that request. Please try again.