1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: namespace Kotchasan\Http;
12:
13: use Psr\Http\Message\ResponseInterface;
14:
15: 16: 17: 18: 19: 20: 21:
22: class Response extends Message implements ResponseInterface
23: {
24: 25: 26: 27: 28:
29: public static $statusTexts = array(
30: 100 => 'Continue',
31: 101 => 'Switching Protocols',
32: 102 => 'Processing',
33: 200 => 'OK',
34: 201 => 'Created',
35: 202 => 'Accepted',
36: 203 => 'Non-Authoritative Information',
37: 204 => 'No Content',
38: 205 => 'Reset Content',
39: 206 => 'Partial Content',
40: 207 => 'Multi-Status',
41: 208 => 'Already Reported',
42: 226 => 'IM Used',
43: 300 => 'Multiple Choices',
44: 301 => 'Moved Permanently',
45: 302 => 'Found',
46: 303 => 'See Other',
47: 304 => 'Not Modified',
48: 305 => 'Use Proxy',
49: 306 => 'Reserved',
50: 307 => 'Temporary Redirect',
51: 308 => 'Permanent Redirect',
52: 400 => 'Bad Request',
53: 401 => 'Unauthorized',
54: 402 => 'Payment Required',
55: 403 => 'Forbidden',
56: 404 => 'Not Found',
57: 405 => 'Method Not Allowed',
58: 406 => 'Not Acceptable',
59: 407 => 'Proxy Authentication Required',
60: 408 => 'Request Timeout',
61: 409 => 'Conflict',
62: 410 => 'Gone',
63: 411 => 'Length Required',
64: 412 => 'Precondition Failed',
65: 413 => 'Request Entity Too Large',
66: 414 => 'Request-URI Too Long',
67: 415 => 'Unsupported Media Type',
68: 416 => 'Requested Range Not Satisfiable',
69: 417 => 'Expectation Failed',
70: 418 => 'I\'m a teapot',
71: 422 => 'Unprocessable Entity',
72: 423 => 'Locked',
73: 424 => 'Failed Dependency',
74: 425 => 'Reserved for WebDAV advanced collections expired proposal',
75: 426 => 'Upgrade Required',
76: 428 => 'Precondition Required',
77: 429 => 'Too Many Requests',
78: 431 => 'Request Header Fields Too Large',
79: 500 => 'Internal Server Error',
80: 501 => 'Not Implemented',
81: 502 => 'Bad Gateway',
82: 503 => 'Service Unavailable',
83: 504 => 'Gateway Timeout',
84: 505 => 'HTTP Version Not Supported',
85: 506 => 'Variant Also Negotiates (Experimental)',
86: 507 => 'Insufficient Storage',
87: 508 => 'Loop Detected',
88: 510 => 'Not Extended',
89: 511 => 'Network Authentication Required',
90: );
91: 92: 93: 94: 95:
96: protected $content;
97: 98: 99:
100: protected $reasonPhrase;
101: 102: 103:
104: protected $statusCode;
105:
106: 107: 108: 109: 110: 111:
112: public function __construct($code = 200, $reasonPhrase = null)
113: {
114: $this->statusCode = $code;
115: $this->reasonPhrase = $reasonPhrase;
116: }
117:
118: 119: 120: 121: 122:
123: public function getContent()
124: {
125: return $this->content;
126: }
127:
128: 129: 130: 131: 132: 133: 134: 135:
136: public function getReasonPhrase()
137: {
138: if ($this->reasonPhrase) {
139: return $this->reasonPhrase;
140: }
141: if (isset(static::$statusTexts[$this->statusCode])) {
142: return static::$statusTexts[$this->statusCode];
143: }
144:
145: return '';
146: }
147:
148: 149: 150: 151: 152:
153: public function getStatusCode()
154: {
155: return $this->statusCode;
156: }
157:
158: 159: 160: 161: 162:
163: public function send()
164: {
165: $this->sendHeaders();
166: $this->sendContent();
167:
168: return $this;
169: }
170:
171: 172: 173: 174: 175: 176: 177: 178: 179:
180: public function withContent($content)
181: {
182: if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable(array($content, '__toString'))) {
183: throw new \InvalidArgumentException(sprintf('The Response content must be a string or object implementing __toString(), "%s" given.', gettype($content)));
184: }
185: $this->content = (string) $content;
186:
187: return $this;
188: }
189:
190: 191: 192: 193: 194: 195: 196: 197:
198: public function withStatus($code, $reasonPhrase = '')
199: {
200: $clone = clone $this;
201: $clone->statusCode = $code;
202: $clone->reasonPhrase = $reasonPhrase;
203:
204: return $clone;
205: }
206:
207: 208: 209: 210: 211:
212: protected function sendContent()
213: {
214: if ($this->content) {
215: echo $this->content;
216: }
217:
218: return $this;
219: }
220:
221: 222: 223: 224: 225:
226: protected function sendHeaders()
227: {
228: if (headers_sent()) {
229: return $this;
230: }
231: header(sprintf('HTTP/%s %s %s', $this->protocol, $this->statusCode, $this->getReasonPhrase()), true, $this->statusCode);
232: foreach ($this->headers as $name => $values) {
233: foreach ($values as $value) {
234: header($name.': '.$value);
235: }
236: }
237:
238: return $this;
239: }
240: }
241: