<?php
/**
 * View.
 * @package magic.core
 * @subpackage helper.base
 */
/**
 * Viewの基底クラスです.
 * <p>
 * アプリケーションには、最低一つ以上のViewクラスが必要です。<br/>
 * アプリケーションのViewクラスは、必ずこのクラスを継承して作成してください。
 * </p>
 * @package magic.core
 * @subpackage helper.base
 * @author T.Okumura
 * @version 1.0.0
 */
class View {
    /**
     * HttpResponseクラスを保持します.
     * @var HttpResponse
     */
    protected $response = NULL;
    /**
     * HttpSessionクラスを保持します.
     * @var HttpSession
     */
    protected $session = NULL;
    /**
     * NameConfigureクラスを保持します.
     * @var NameConfigure
     */
    protected $name = NULL;
    /**
     * PathConfigureクラスを保持します.
     * @var PathConfigure
     */
    protected $path = NULL;
    /**
     * 出力バッファを保持します.
     * @var string
     */
    protected $output = NULL;
    /**
     * __construct.
     */
    public function __construct() {
    }
    /**
     * リダイレクト処理を実行します.
     * <p>
     * <var>$transSid</var>がTRUEに設定されていても、
     * Cookieが利用できる場合は、クエリパラメータにセッションIDを付与しません。
     * これはセキュリティの観点からも重要です。
     * </p>
     * @param string $path リダイレクト先のパス
     * @param HttpSession $session HttpSessionクラス
     * @param bool $transSid セッションIDをクエリパラメータに付与するかどうかのフラグ
     * @param array $parameters クエリパラメータ
     * @final
     */
    public final function redirect($path, HttpSession $session, $transSid = FALSE, array $parameters = array()) {
        $sid = '';
        $separator = '';
        $get = array();
        if ($transSid && $session->getCookieValue('MAGIC', 0) !== 'MAGIC') {
            $sid = '?' . $session->getName() . '=' . $session->getId();
        }
        if (!empty($parameters)) {
            $separator = empty($sid) ? '?' : '&';
            foreach ($parameters as $key => $value) {
                $get[] = $key . '=' . $value;
            }
        }
        header('Location: /' . $path . $sid . $separator . implode('&', $get));
        exit();
    }
    /**
     * フォワード処理を実行します.
     * <p>
     * <var>$transSid</var>がTRUEに設定されていても、
     * Cookieが利用できる場合は、hiddenにセッションIDを書き出しません。
     * これはセキュリティの観点からも重要です。
     * </p>
     * @param Response $response
     * @param Session $session
     * @param NameConfigure $name 命名規則設定クラス
     * @param PathConfigure $path パス設定クラス
     * @param bool $transSid [optional] セッションIDをhiddenに書き出すかどうかのフラグ
     * @throws MagicException HTMLファイルが存在しない場合
     * @final
     */
    public final function forward(HttpResponse $response, HttpSession $session, NameConfigure $name,
            PathConfigure $path, $transSid = FALSE) {
        $this->response = $response;
        $this->session = $session;
        $this->name = $name;
        $this->path = $path;
        if ($transSid && $session->getCookieValue('MAGIC', 0) !== 'MAGIC') {
            $this->response
                    ->set('magic',
                            '<input type="hidden" name="' . $session->getName() . '" value="' . $session->getId()
                                    . '" />');
        } else {
            $this->response->set('magic', '');
        }
        $this->preRender();
        if (!file_exists($html = $this->loadHtml())) {
            throw new MagicException(MessageBehavior::getMessage('SYS007', $html));
        }
        ob_start();
        extract($this->response->getAll(), EXTR_OVERWRITE);
        extract($this->session->getAll(), EXTR_OVERWRITE);
        require_once $html;
        $this->output = ob_get_clean();
        $this->postRender();
        exit($this->output);
    }
    /**
     * HTMLファイルが読み込まれる前に実行されます.
     * <p>
     * レスポンスに追加の値などを設定する場合に使用してください。
     * 例えば、テーブルの行をループさせてレスポンスにセットするなどで利用できます。
     * </p>
     */
    protected function preRender() {
    }
    /**
     * HTMLファイルを読み込んだ後に実行されます.
     * <p>
     * 例えば、出力バッファの文字コードを
     * まとめてエンコードするなどで利用できます。
     * </p>
     */
    protected function postRender() {
    }
    /**
     * HTMLファイルを読み込みます.
     * <p>
     * デフォルトでは、現在ロードされているViewクラスと同じ名前で探します。
     * Actionクラスから{@link ActionResult}クラスを返す際に、
     * コールするViewの名前が省略されていた場合は、
     * 実行されていたActionクラスの名前と等価です。
     * アプリケーション側で、呼び出すHTMLファイルを指定したい場合は、
     * このファンクションをオーバーライドして、適切なHTMLファイル名を返すようにしてください。
     * </p>
     * @return string HTMLファイルの名前
     */
    protected function loadHtml() {
        return $this->path->getHtmlPath()
                . $this->name->getHtmlFileNamingType()
                        ->apply(substr(get_class($this), 0, -strlen($this->path->getViewSuffix()))) . '.'
                . $this->path->getHtmlSuffix();
    }
}
// EOF.