<?php
/**
 * -----------------------------------------------------------------------------
 *
 * SyL - Web Application Framework for PHP
 *
 * PHP version 4 (>= 4.3.x) or 5
 *
 * Copyright (C) 2006 k.watanabe
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * -----------------------------------------------------------------------------
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_Response.php,v 1.3 2007/01/03 11:17:37 seasonstream Exp $
 * @link      http://www.syl.jp/
 * -----------------------------------------------------------------------------
 */

/**
 * 結果応答クラス
 *
 * @package   SyL
 * @author    k.watanabe <k.watanabe@syl.jp>
 * @copyright 2006 k.watanabe
 * @license   http://www.opensource.org/licenses/lgpl-license.php
 * @version   CVS: $Id: SyL_Response.php,v 1.3 2007/01/03 11:17:37 seasonstream Exp $
 * @link      http://www.syl.jp/
 */
class SyL_Response
{
    /**
     * HTTPレスポンスステータスコード
     * 
     * @access public
     * @var array
     */
/*
    var $status_codes = array(
      '100' => 'Continue',
      '101' => 'Switching Protocols',
      '200' => 'OK',
      '201' => 'Created',
      '202' => 'Accepted',
      '203' => 'Non-Authoritative Information',
      '204' => 'No Content',
      '205' => 'Reset Content',
      '206' => 'Partial Content',
      '300' => 'Multiple Choices',
      '301' => 'Moved Permanently',
      '302' => 'Found',
      '303' => 'See Other',
      '304' => 'Not Modified',
      '305' => 'Use Proxy',
      '306' => '(Unused)',
      '307' => 'Temporary 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',
      '500' => 'Internal Server Error',
      '501' => 'Not Implemented',
      '502' => 'Bad Gateway',
      '503' => 'Service Unavailable',
      '504' => 'Gateway Timeout',
      '505' => 'HTTP Version Not Supported'
    );
*/

    /**
     * 追加HTTPレスポンスヘッダ
     * 
     * @access public
     * @var array
     */
    var $headers = array();

    /**
     * HTTPレスポンスオブジェクトを取得
     * 
     * @access public
     * @return object HTTPレスポンスオブジェクト
     */
    function &getInstance()
    {
        static $singleton;
        if (!is_object($singleton)) {
            $class_name = __CLASS__;
            $singleton = new $class_name();
        }
        return $singleton;
    }

    /**
     * リダイレクトする
     * 
     * @static
     * @access public
     * @param string リダイレクト先URL
     */
    function redirect($url)
    {
        SyL_Response::setHeader('Location', $url);
        $obj =& SyL_Response::getInstance();
        $obj->sendHeader();
        exit;
    }

    /**
     * 404 Not Found リダイレクトする
     *
     * @access public
     * @param string カレントURL
     */
    function redirect404()
    {
        $request_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
        SyL_Loggers::info("[Response] 404 Not Found - {$request_uri}");

        SyL_Response::setHeader('HTTP/1.0 404 Not Found');
        if (defined('SYL_RESPONSE_URL_404') && SYL_RESPONSE_URL_404) {
            SyL_Response::redirect(SYL_RESPONSE_URL_404);
        } else {
            echo "<h2>HTTP/1.0 404 Not Found</h2>";
            exit;
        }
    }

    /**
     * HTTPレスポンスヘッダをセットする
     * 
     * @static
     * @access public
     * @param string ヘッダ名
     * @param string ヘッダ値
     */
    function setHeader($name, $value='')
    {
        $obj =& SyL_Response::getInstance();
        $obj->headers[$name] = $value;
    }

    /**
     * HTTPレスポンスヘッダを取得する
     * 
     * @static
     * @access public
     * @param string ヘッダ名
     */
    function getHeader($name)
    {
        $name = strtolower($name);

        $obj =& SyL_Response::getInstance();
        foreach ($obj->getCustomHeaders() as $tmp_name => $tmp_value) {
            if ($name == strtolower($tmp_name)) {
                return $tmp_value;
            }
        }

        if (function_exists('headers_list')) {
            // 5.0
            foreach (headers_list() as $header) {
                $header_values = explode(':', $header, 2);
                if ($name == strtolower(trim($header_values[0]))) {
                    return trim($header_values[1]);
                }
            }
        } else if (function_exists('apache_response_headers')) {
            foreach (apache_response_headers() as $tmp_name => $tmp_value) {
                if ($name == strtolower($tmp_name)) {
                    return $tmp_value;
                }
            }
        }

        return false;
    }

    /**
     * HTTPレスポンスヘッダを取得する
     * 
     * @access public
     * @return array ヘッダ配列
     */
    function getCustomHeaders()
    {
        return $this->headers;
    }

    /**
     * HTTPレスポンスヘッダを送信
     * 
     * @access public
     */
    function sendHeader()
    {
        foreach ($this->getCustomHeaders() as $tmp_name => $tmp_value) {
            if ($tmp_value) {
                header("$tmp_name: $tmp_value");
            } else {
                header("$tmp_name");
            }
        }
    }

    /**
     * レンダリングされたHTMLを出力
     * 
     * @access public
     * @param object ビューオブジェクト
     */
    function display(&$view)
    {
        // ヘッダ出力
        $this->sendHeader();
        // HTML出力
        echo $view->getRender();

        // 全バッファリング出力
        $neste = ob_get_level();
        for ($i=0; $i<$neste; $i++) {
            ob_end_flush();
        }
    }
}

?>
