web/lib/Zend/Controller/Response/Abstract.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     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 }