|
1 <?php |
|
2 /** |
|
3 * Zend Framework |
|
4 * |
|
5 * LICENSE |
|
6 * |
|
7 * This source file is subject to the new BSD license that is bundled |
|
8 * with this package in the file LICENSE.txt. |
|
9 * It is also available through the world-wide-web at this URL: |
|
10 * http://framework.zend.com/license/new-bsd |
|
11 * If you did not receive a copy of the license and are unable to |
|
12 * obtain it through the world-wide-web, please send an email |
|
13 * to license@zend.com so we can send you a copy immediately. |
|
14 * |
|
15 * @category Zend |
|
16 * @package Zend_Controller |
|
17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 * @version $Id: Abstract.php 21301 2010-03-02 23:01:19Z yoshida@zend.co.jp $ |
|
20 */ |
|
21 |
|
22 /** |
|
23 * Zend_Controller_Response_Abstract |
|
24 * |
|
25 * Base class for Zend_Controller responses |
|
26 * |
|
27 * @package Zend_Controller |
|
28 * @subpackage Response |
|
29 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
30 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
31 */ |
|
32 abstract class Zend_Controller_Response_Abstract |
|
33 { |
|
34 /** |
|
35 * Body content |
|
36 * @var array |
|
37 */ |
|
38 protected $_body = array(); |
|
39 |
|
40 /** |
|
41 * Exception stack |
|
42 * @var Exception |
|
43 */ |
|
44 protected $_exceptions = array(); |
|
45 |
|
46 /** |
|
47 * Array of headers. Each header is an array with keys 'name' and 'value' |
|
48 * @var array |
|
49 */ |
|
50 protected $_headers = array(); |
|
51 |
|
52 /** |
|
53 * Array of raw headers. Each header is a single string, the entire header to emit |
|
54 * @var array |
|
55 */ |
|
56 protected $_headersRaw = array(); |
|
57 |
|
58 /** |
|
59 * HTTP response code to use in headers |
|
60 * @var int |
|
61 */ |
|
62 protected $_httpResponseCode = 200; |
|
63 |
|
64 /** |
|
65 * Flag; is this response a redirect? |
|
66 * @var boolean |
|
67 */ |
|
68 protected $_isRedirect = false; |
|
69 |
|
70 /** |
|
71 * Whether or not to render exceptions; off by default |
|
72 * @var boolean |
|
73 */ |
|
74 protected $_renderExceptions = false; |
|
75 |
|
76 /** |
|
77 * Flag; if true, when header operations are called after headers have been |
|
78 * sent, an exception will be raised; otherwise, processing will continue |
|
79 * as normal. Defaults to true. |
|
80 * |
|
81 * @see canSendHeaders() |
|
82 * @var boolean |
|
83 */ |
|
84 public $headersSentThrowsException = true; |
|
85 |
|
86 /** |
|
87 * Normalize a header name |
|
88 * |
|
89 * Normalizes a header name to X-Capitalized-Names |
|
90 * |
|
91 * @param string $name |
|
92 * @return string |
|
93 */ |
|
94 protected function _normalizeHeader($name) |
|
95 { |
|
96 $filtered = str_replace(array('-', '_'), ' ', (string) $name); |
|
97 $filtered = ucwords(strtolower($filtered)); |
|
98 $filtered = str_replace(' ', '-', $filtered); |
|
99 return $filtered; |
|
100 } |
|
101 |
|
102 /** |
|
103 * Set a header |
|
104 * |
|
105 * If $replace is true, replaces any headers already defined with that |
|
106 * $name. |
|
107 * |
|
108 * @param string $name |
|
109 * @param string $value |
|
110 * @param boolean $replace |
|
111 * @return Zend_Controller_Response_Abstract |
|
112 */ |
|
113 public function setHeader($name, $value, $replace = false) |
|
114 { |
|
115 $this->canSendHeaders(true); |
|
116 $name = $this->_normalizeHeader($name); |
|
117 $value = (string) $value; |
|
118 |
|
119 if ($replace) { |
|
120 foreach ($this->_headers as $key => $header) { |
|
121 if ($name == $header['name']) { |
|
122 unset($this->_headers[$key]); |
|
123 } |
|
124 } |
|
125 } |
|
126 |
|
127 $this->_headers[] = array( |
|
128 'name' => $name, |
|
129 'value' => $value, |
|
130 'replace' => $replace |
|
131 ); |
|
132 |
|
133 return $this; |
|
134 } |
|
135 |
|
136 /** |
|
137 * Set redirect URL |
|
138 * |
|
139 * Sets Location header and response code. Forces replacement of any prior |
|
140 * redirects. |
|
141 * |
|
142 * @param string $url |
|
143 * @param int $code |
|
144 * @return Zend_Controller_Response_Abstract |
|
145 */ |
|
146 public function setRedirect($url, $code = 302) |
|
147 { |
|
148 $this->canSendHeaders(true); |
|
149 $this->setHeader('Location', $url, true) |
|
150 ->setHttpResponseCode($code); |
|
151 |
|
152 return $this; |
|
153 } |
|
154 |
|
155 /** |
|
156 * Is this a redirect? |
|
157 * |
|
158 * @return boolean |
|
159 */ |
|
160 public function isRedirect() |
|
161 { |
|
162 return $this->_isRedirect; |
|
163 } |
|
164 |
|
165 /** |
|
166 * Return array of headers; see {@link $_headers} for format |
|
167 * |
|
168 * @return array |
|
169 */ |
|
170 public function getHeaders() |
|
171 { |
|
172 return $this->_headers; |
|
173 } |
|
174 |
|
175 /** |
|
176 * Clear headers |
|
177 * |
|
178 * @return Zend_Controller_Response_Abstract |
|
179 */ |
|
180 public function clearHeaders() |
|
181 { |
|
182 $this->_headers = array(); |
|
183 |
|
184 return $this; |
|
185 } |
|
186 |
|
187 /** |
|
188 * Clears the specified HTTP header |
|
189 * |
|
190 * @param string $name |
|
191 * @return Zend_Controller_Response_Abstract |
|
192 */ |
|
193 public function clearHeader($name) |
|
194 { |
|
195 if (! count($this->_headers)) { |
|
196 return $this; |
|
197 } |
|
198 |
|
199 foreach ($this->_headers as $index => $header) { |
|
200 if ($name == $header['name']) { |
|
201 unset($this->_headers[$index]); |
|
202 } |
|
203 } |
|
204 |
|
205 return $this; |
|
206 } |
|
207 |
|
208 /** |
|
209 * Set raw HTTP header |
|
210 * |
|
211 * Allows setting non key => value headers, such as status codes |
|
212 * |
|
213 * @param string $value |
|
214 * @return Zend_Controller_Response_Abstract |
|
215 */ |
|
216 public function setRawHeader($value) |
|
217 { |
|
218 $this->canSendHeaders(true); |
|
219 if ('Location' == substr($value, 0, 8)) { |
|
220 $this->_isRedirect = true; |
|
221 } |
|
222 $this->_headersRaw[] = (string) $value; |
|
223 return $this; |
|
224 } |
|
225 |
|
226 /** |
|
227 * Retrieve all {@link setRawHeader() raw HTTP headers} |
|
228 * |
|
229 * @return array |
|
230 */ |
|
231 public function getRawHeaders() |
|
232 { |
|
233 return $this->_headersRaw; |
|
234 } |
|
235 |
|
236 /** |
|
237 * Clear all {@link setRawHeader() raw HTTP headers} |
|
238 * |
|
239 * @return Zend_Controller_Response_Abstract |
|
240 */ |
|
241 public function clearRawHeaders() |
|
242 { |
|
243 $this->_headersRaw = array(); |
|
244 return $this; |
|
245 } |
|
246 |
|
247 /** |
|
248 * Clears the specified raw HTTP header |
|
249 * |
|
250 * @param string $headerRaw |
|
251 * @return Zend_Controller_Response_Abstract |
|
252 */ |
|
253 public function clearRawHeader($headerRaw) |
|
254 { |
|
255 if (! count($this->_headersRaw)) { |
|
256 return $this; |
|
257 } |
|
258 |
|
259 $key = array_search($headerRaw, $this->_headersRaw); |
|
260 unset($this->_headersRaw[$key]); |
|
261 |
|
262 return $this; |
|
263 } |
|
264 |
|
265 /** |
|
266 * Clear all headers, normal and raw |
|
267 * |
|
268 * @return Zend_Controller_Response_Abstract |
|
269 */ |
|
270 public function clearAllHeaders() |
|
271 { |
|
272 return $this->clearHeaders() |
|
273 ->clearRawHeaders(); |
|
274 } |
|
275 |
|
276 /** |
|
277 * Set HTTP response code to use with headers |
|
278 * |
|
279 * @param int $code |
|
280 * @return Zend_Controller_Response_Abstract |
|
281 */ |
|
282 public function setHttpResponseCode($code) |
|
283 { |
|
284 if (!is_int($code) || (100 > $code) || (599 < $code)) { |
|
285 require_once 'Zend/Controller/Response/Exception.php'; |
|
286 throw new Zend_Controller_Response_Exception('Invalid HTTP response code'); |
|
287 } |
|
288 |
|
289 if ((300 <= $code) && (307 >= $code)) { |
|
290 $this->_isRedirect = true; |
|
291 } else { |
|
292 $this->_isRedirect = false; |
|
293 } |
|
294 |
|
295 $this->_httpResponseCode = $code; |
|
296 return $this; |
|
297 } |
|
298 |
|
299 /** |
|
300 * Retrieve HTTP response code |
|
301 * |
|
302 * @return int |
|
303 */ |
|
304 public function getHttpResponseCode() |
|
305 { |
|
306 return $this->_httpResponseCode; |
|
307 } |
|
308 |
|
309 /** |
|
310 * Can we send headers? |
|
311 * |
|
312 * @param boolean $throw Whether or not to throw an exception if headers have been sent; defaults to false |
|
313 * @return boolean |
|
314 * @throws Zend_Controller_Response_Exception |
|
315 */ |
|
316 public function canSendHeaders($throw = false) |
|
317 { |
|
318 $ok = headers_sent($file, $line); |
|
319 if ($ok && $throw && $this->headersSentThrowsException) { |
|
320 require_once 'Zend/Controller/Response/Exception.php'; |
|
321 throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent in ' . $file . ', line ' . $line); |
|
322 } |
|
323 |
|
324 return !$ok; |
|
325 } |
|
326 |
|
327 /** |
|
328 * Send all headers |
|
329 * |
|
330 * Sends any headers specified. If an {@link setHttpResponseCode() HTTP response code} |
|
331 * has been specified, it is sent with the first header. |
|
332 * |
|
333 * @return Zend_Controller_Response_Abstract |
|
334 */ |
|
335 public function sendHeaders() |
|
336 { |
|
337 // Only check if we can send headers if we have headers to send |
|
338 if (count($this->_headersRaw) || count($this->_headers) || (200 != $this->_httpResponseCode)) { |
|
339 $this->canSendHeaders(true); |
|
340 } elseif (200 == $this->_httpResponseCode) { |
|
341 // Haven't changed the response code, and we have no headers |
|
342 return $this; |
|
343 } |
|
344 |
|
345 $httpCodeSent = false; |
|
346 |
|
347 foreach ($this->_headersRaw as $header) { |
|
348 if (!$httpCodeSent && $this->_httpResponseCode) { |
|
349 header($header, true, $this->_httpResponseCode); |
|
350 $httpCodeSent = true; |
|
351 } else { |
|
352 header($header); |
|
353 } |
|
354 } |
|
355 |
|
356 foreach ($this->_headers as $header) { |
|
357 if (!$httpCodeSent && $this->_httpResponseCode) { |
|
358 header($header['name'] . ': ' . $header['value'], $header['replace'], $this->_httpResponseCode); |
|
359 $httpCodeSent = true; |
|
360 } else { |
|
361 header($header['name'] . ': ' . $header['value'], $header['replace']); |
|
362 } |
|
363 } |
|
364 |
|
365 if (!$httpCodeSent) { |
|
366 header('HTTP/1.1 ' . $this->_httpResponseCode); |
|
367 $httpCodeSent = true; |
|
368 } |
|
369 |
|
370 return $this; |
|
371 } |
|
372 |
|
373 /** |
|
374 * Set body content |
|
375 * |
|
376 * If $name is not passed, or is not a string, resets the entire body and |
|
377 * sets the 'default' key to $content. |
|
378 * |
|
379 * If $name is a string, sets the named segment in the body array to |
|
380 * $content. |
|
381 * |
|
382 * @param string $content |
|
383 * @param null|string $name |
|
384 * @return Zend_Controller_Response_Abstract |
|
385 */ |
|
386 public function setBody($content, $name = null) |
|
387 { |
|
388 if ((null === $name) || !is_string($name)) { |
|
389 $this->_body = array('default' => (string) $content); |
|
390 } else { |
|
391 $this->_body[$name] = (string) $content; |
|
392 } |
|
393 |
|
394 return $this; |
|
395 } |
|
396 |
|
397 /** |
|
398 * Append content to the body content |
|
399 * |
|
400 * @param string $content |
|
401 * @param null|string $name |
|
402 * @return Zend_Controller_Response_Abstract |
|
403 */ |
|
404 public function appendBody($content, $name = null) |
|
405 { |
|
406 if ((null === $name) || !is_string($name)) { |
|
407 if (isset($this->_body['default'])) { |
|
408 $this->_body['default'] .= (string) $content; |
|
409 } else { |
|
410 return $this->append('default', $content); |
|
411 } |
|
412 } elseif (isset($this->_body[$name])) { |
|
413 $this->_body[$name] .= (string) $content; |
|
414 } else { |
|
415 return $this->append($name, $content); |
|
416 } |
|
417 |
|
418 return $this; |
|
419 } |
|
420 |
|
421 /** |
|
422 * Clear body array |
|
423 * |
|
424 * With no arguments, clears the entire body array. Given a $name, clears |
|
425 * just that named segment; if no segment matching $name exists, returns |
|
426 * false to indicate an error. |
|
427 * |
|
428 * @param string $name Named segment to clear |
|
429 * @return boolean |
|
430 */ |
|
431 public function clearBody($name = null) |
|
432 { |
|
433 if (null !== $name) { |
|
434 $name = (string) $name; |
|
435 if (isset($this->_body[$name])) { |
|
436 unset($this->_body[$name]); |
|
437 return true; |
|
438 } |
|
439 |
|
440 return false; |
|
441 } |
|
442 |
|
443 $this->_body = array(); |
|
444 return true; |
|
445 } |
|
446 |
|
447 /** |
|
448 * Return the body content |
|
449 * |
|
450 * If $spec is false, returns the concatenated values of the body content |
|
451 * array. If $spec is boolean true, returns the body content array. If |
|
452 * $spec is a string and matches a named segment, returns the contents of |
|
453 * that segment; otherwise, returns null. |
|
454 * |
|
455 * @param boolean $spec |
|
456 * @return string|array|null |
|
457 */ |
|
458 public function getBody($spec = false) |
|
459 { |
|
460 if (false === $spec) { |
|
461 ob_start(); |
|
462 $this->outputBody(); |
|
463 return ob_get_clean(); |
|
464 } elseif (true === $spec) { |
|
465 return $this->_body; |
|
466 } elseif (is_string($spec) && isset($this->_body[$spec])) { |
|
467 return $this->_body[$spec]; |
|
468 } |
|
469 |
|
470 return null; |
|
471 } |
|
472 |
|
473 /** |
|
474 * Append a named body segment to the body content array |
|
475 * |
|
476 * If segment already exists, replaces with $content and places at end of |
|
477 * array. |
|
478 * |
|
479 * @param string $name |
|
480 * @param string $content |
|
481 * @return Zend_Controller_Response_Abstract |
|
482 */ |
|
483 public function append($name, $content) |
|
484 { |
|
485 if (!is_string($name)) { |
|
486 require_once 'Zend/Controller/Response/Exception.php'; |
|
487 throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")'); |
|
488 } |
|
489 |
|
490 if (isset($this->_body[$name])) { |
|
491 unset($this->_body[$name]); |
|
492 } |
|
493 $this->_body[$name] = (string) $content; |
|
494 return $this; |
|
495 } |
|
496 |
|
497 /** |
|
498 * Prepend a named body segment to the body content array |
|
499 * |
|
500 * If segment already exists, replaces with $content and places at top of |
|
501 * array. |
|
502 * |
|
503 * @param string $name |
|
504 * @param string $content |
|
505 * @return void |
|
506 */ |
|
507 public function prepend($name, $content) |
|
508 { |
|
509 if (!is_string($name)) { |
|
510 require_once 'Zend/Controller/Response/Exception.php'; |
|
511 throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")'); |
|
512 } |
|
513 |
|
514 if (isset($this->_body[$name])) { |
|
515 unset($this->_body[$name]); |
|
516 } |
|
517 |
|
518 $new = array($name => (string) $content); |
|
519 $this->_body = $new + $this->_body; |
|
520 |
|
521 return $this; |
|
522 } |
|
523 |
|
524 /** |
|
525 * Insert a named segment into the body content array |
|
526 * |
|
527 * @param string $name |
|
528 * @param string $content |
|
529 * @param string $parent |
|
530 * @param boolean $before Whether to insert the new segment before or |
|
531 * after the parent. Defaults to false (after) |
|
532 * @return Zend_Controller_Response_Abstract |
|
533 */ |
|
534 public function insert($name, $content, $parent = null, $before = false) |
|
535 { |
|
536 if (!is_string($name)) { |
|
537 require_once 'Zend/Controller/Response/Exception.php'; |
|
538 throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")'); |
|
539 } |
|
540 |
|
541 if ((null !== $parent) && !is_string($parent)) { |
|
542 require_once 'Zend/Controller/Response/Exception.php'; |
|
543 throw new Zend_Controller_Response_Exception('Invalid body segment parent key ("' . gettype($parent) . '")'); |
|
544 } |
|
545 |
|
546 if (isset($this->_body[$name])) { |
|
547 unset($this->_body[$name]); |
|
548 } |
|
549 |
|
550 if ((null === $parent) || !isset($this->_body[$parent])) { |
|
551 return $this->append($name, $content); |
|
552 } |
|
553 |
|
554 $ins = array($name => (string) $content); |
|
555 $keys = array_keys($this->_body); |
|
556 $loc = array_search($parent, $keys); |
|
557 if (!$before) { |
|
558 // Increment location if not inserting before |
|
559 ++$loc; |
|
560 } |
|
561 |
|
562 if (0 === $loc) { |
|
563 // If location of key is 0, we're prepending |
|
564 $this->_body = $ins + $this->_body; |
|
565 } elseif ($loc >= (count($this->_body))) { |
|
566 // If location of key is maximal, we're appending |
|
567 $this->_body = $this->_body + $ins; |
|
568 } else { |
|
569 // Otherwise, insert at location specified |
|
570 $pre = array_slice($this->_body, 0, $loc); |
|
571 $post = array_slice($this->_body, $loc); |
|
572 $this->_body = $pre + $ins + $post; |
|
573 } |
|
574 |
|
575 return $this; |
|
576 } |
|
577 |
|
578 /** |
|
579 * Echo the body segments |
|
580 * |
|
581 * @return void |
|
582 */ |
|
583 public function outputBody() |
|
584 { |
|
585 $body = implode('', $this->_body); |
|
586 echo $body; |
|
587 } |
|
588 |
|
589 /** |
|
590 * Register an exception with the response |
|
591 * |
|
592 * @param Exception $e |
|
593 * @return Zend_Controller_Response_Abstract |
|
594 */ |
|
595 public function setException(Exception $e) |
|
596 { |
|
597 $this->_exceptions[] = $e; |
|
598 return $this; |
|
599 } |
|
600 |
|
601 /** |
|
602 * Retrieve the exception stack |
|
603 * |
|
604 * @return array |
|
605 */ |
|
606 public function getException() |
|
607 { |
|
608 return $this->_exceptions; |
|
609 } |
|
610 |
|
611 /** |
|
612 * Has an exception been registered with the response? |
|
613 * |
|
614 * @return boolean |
|
615 */ |
|
616 public function isException() |
|
617 { |
|
618 return !empty($this->_exceptions); |
|
619 } |
|
620 |
|
621 /** |
|
622 * Does the response object contain an exception of a given type? |
|
623 * |
|
624 * @param string $type |
|
625 * @return boolean |
|
626 */ |
|
627 public function hasExceptionOfType($type) |
|
628 { |
|
629 foreach ($this->_exceptions as $e) { |
|
630 if ($e instanceof $type) { |
|
631 return true; |
|
632 } |
|
633 } |
|
634 |
|
635 return false; |
|
636 } |
|
637 |
|
638 /** |
|
639 * Does the response object contain an exception with a given message? |
|
640 * |
|
641 * @param string $message |
|
642 * @return boolean |
|
643 */ |
|
644 public function hasExceptionOfMessage($message) |
|
645 { |
|
646 foreach ($this->_exceptions as $e) { |
|
647 if ($message == $e->getMessage()) { |
|
648 return true; |
|
649 } |
|
650 } |
|
651 |
|
652 return false; |
|
653 } |
|
654 |
|
655 /** |
|
656 * Does the response object contain an exception with a given code? |
|
657 * |
|
658 * @param int $code |
|
659 * @return boolean |
|
660 */ |
|
661 public function hasExceptionOfCode($code) |
|
662 { |
|
663 $code = (int) $code; |
|
664 foreach ($this->_exceptions as $e) { |
|
665 if ($code == $e->getCode()) { |
|
666 return true; |
|
667 } |
|
668 } |
|
669 |
|
670 return false; |
|
671 } |
|
672 |
|
673 /** |
|
674 * Retrieve all exceptions of a given type |
|
675 * |
|
676 * @param string $type |
|
677 * @return false|array |
|
678 */ |
|
679 public function getExceptionByType($type) |
|
680 { |
|
681 $exceptions = array(); |
|
682 foreach ($this->_exceptions as $e) { |
|
683 if ($e instanceof $type) { |
|
684 $exceptions[] = $e; |
|
685 } |
|
686 } |
|
687 |
|
688 if (empty($exceptions)) { |
|
689 $exceptions = false; |
|
690 } |
|
691 |
|
692 return $exceptions; |
|
693 } |
|
694 |
|
695 /** |
|
696 * Retrieve all exceptions of a given message |
|
697 * |
|
698 * @param string $message |
|
699 * @return false|array |
|
700 */ |
|
701 public function getExceptionByMessage($message) |
|
702 { |
|
703 $exceptions = array(); |
|
704 foreach ($this->_exceptions as $e) { |
|
705 if ($message == $e->getMessage()) { |
|
706 $exceptions[] = $e; |
|
707 } |
|
708 } |
|
709 |
|
710 if (empty($exceptions)) { |
|
711 $exceptions = false; |
|
712 } |
|
713 |
|
714 return $exceptions; |
|
715 } |
|
716 |
|
717 /** |
|
718 * Retrieve all exceptions of a given code |
|
719 * |
|
720 * @param mixed $code |
|
721 * @return void |
|
722 */ |
|
723 public function getExceptionByCode($code) |
|
724 { |
|
725 $code = (int) $code; |
|
726 $exceptions = array(); |
|
727 foreach ($this->_exceptions as $e) { |
|
728 if ($code == $e->getCode()) { |
|
729 $exceptions[] = $e; |
|
730 } |
|
731 } |
|
732 |
|
733 if (empty($exceptions)) { |
|
734 $exceptions = false; |
|
735 } |
|
736 |
|
737 return $exceptions; |
|
738 } |
|
739 |
|
740 /** |
|
741 * Whether or not to render exceptions (off by default) |
|
742 * |
|
743 * If called with no arguments or a null argument, returns the value of the |
|
744 * flag; otherwise, sets it and returns the current value. |
|
745 * |
|
746 * @param boolean $flag Optional |
|
747 * @return boolean |
|
748 */ |
|
749 public function renderExceptions($flag = null) |
|
750 { |
|
751 if (null !== $flag) { |
|
752 $this->_renderExceptions = $flag ? true : false; |
|
753 } |
|
754 |
|
755 return $this->_renderExceptions; |
|
756 } |
|
757 |
|
758 /** |
|
759 * Send the response, including all headers, rendering exceptions if so |
|
760 * requested. |
|
761 * |
|
762 * @return void |
|
763 */ |
|
764 public function sendResponse() |
|
765 { |
|
766 $this->sendHeaders(); |
|
767 |
|
768 if ($this->isException() && $this->renderExceptions()) { |
|
769 $exceptions = ''; |
|
770 foreach ($this->getException() as $e) { |
|
771 $exceptions .= $e->__toString() . "\n"; |
|
772 } |
|
773 echo $exceptions; |
|
774 return; |
|
775 } |
|
776 |
|
777 $this->outputBody(); |
|
778 } |
|
779 |
|
780 /** |
|
781 * Magic __toString functionality |
|
782 * |
|
783 * Proxies to {@link sendResponse()} and returns response value as string |
|
784 * using output buffering. |
|
785 * |
|
786 * @return string |
|
787 */ |
|
788 public function __toString() |
|
789 { |
|
790 ob_start(); |
|
791 $this->sendResponse(); |
|
792 return ob_get_clean(); |
|
793 } |
|
794 } |