<?php
/**
 * Action.
 * @package magic.core
 * @subpackage helper.base
 */
/**
 * Actionの基底クラスです.
 * <p>
 * アプリケーションには、最低一つ以上のActionクラスが必要です。<br/>
 * アプリケーションのActionクラスは、必ずこのクラスを継承して作成してください。
 * Actionクラスが正常に終了した場合は、必ず下記の何れか
 * <ul>
 * <li>{@link Direct}</li>
 * <li>{@link Forward}</li>
 * <li>{@link Redirect}</li>
 * <li>{@link SessionForward}</li>
 * <li>{@link SessionRedirect}</li>
 * </ul>
 * を返すようにしてください。
 * </p>
 * @package magic.core
 * @subpackage helper.base
 * @author T.Okumura
 * @version 1.0.0
 */
class Action {
    /**
     * HttpRequestクラスを保持します.
     * @var HttpRequest
     */
    protected $request = NULL;
    /**
     * HttpResponseクラスを保持します.
     * @var HttpResponse
     */
    protected $response = NULL;
    /**
     * HttpSessionクラスを保持します.
     * @var HttpSession
     */
    protected $session = NULL;
    /**
     * HttpFileクラスを保持します.
     * @var HttpFile
     */
    protected $file = NULL;
    /**
     * ActionErrorクラスを保持します.
     * @var ActionError
     */
    protected $error = NULL;
    /**
     * HttpFlashクラスを保持します.
     * @var HttpFlash
     */
    protected $flash = NULL;
    /**
     * コンストラクタ.
     */
    public function __construct() {
    }
    /**
     * Actionクラスのプロパティにinjectします.
     * <p>
     * 自動的にinjectさせるために、プロパティのスコープは
     * 親クラスに対して可視(publicまたはprotected)でなければいけません。
     * </p>
     * @param string $property inject対象のプロパティ名
     * @param mixed $value injectするオブジェクト
     * @final
     */
    public final function inject($property, $value) {
        $this->$property = $value;
    }
    /**
     * 初期処理.
     * <p>
     * 自身のプロパティに値を設定、または初期化し、
     * {@link Action::intializeAction()}をコールします。
     * </p>
     * @final
     */
    public final function intialize(HttpRequest $request, HttpSession $session) {
        $this->request = $request;
        $this->session = $session;
        $this->response = new HttpResponse();
        $this->file = new HttpFile();
        $this->error = new ActionError();
        $this->flash = new HttpFlash();
        $this->intializeAction();
    }
    /**
     * クラスの初期処理.
     * <p>
     * {@link Action::intialize()}の後に、
     * フレームワークによってコールされます。<br/>
     * アプリケーション側で共通のクラス初期処理を実装したい場合は、
     * このファンクションをオーバーライドしてください。<br/>
     * {@link HttpRequest}クラスや{@link HttpSession}クラスは、
     * すでに利用できる状態です。
     * </p>
     */
    protected function intializeAction() {
    }
    /**
     * 最初にコールされるファンクション.
     * <p>
     * これは、エントリポイントのファンクションがコールされる前にコールされます。<br/>
     * このタイミングで、初めて{@link HttpFlash}クラスが利用できます。<br/>
     * なぜなら、アプリケーション側がすべてのページにおいて、
     * セッションを必要とするかどうかの判断は、フレームワークにはできないからです。<br/>
     * すべてのページにセッションが必要な場合は、{@link Controller}クラスでスタートさせても構いませんが、
     * ページごとに処理を分ける場合は、少なくとも{@link Action::intializeAction()}ファンクションで、
     * セッションをスタートさせておく必要があります。<br/>
     * エントリポイントのファンクションを引き続きコールする場合には、NULLを返す必要があります。<br/>
     * そうでなければ、適切な{@link ActionResult}を返すように実装してください。
     * </p>
     * @return mixed 処理を続行するにはNULL、そうでなければActionResultクラス
     */
    protected function intializeMethod() {
        return NULL;
    }
    /**
     * アプリケーション側のエントリポイントをコールします.
     * <p>
     * セッションが開始されていれば、{@link HttpFlash}クラスを準備してから、
     * {@link Action::intializeMethod()}をコールします。<br/>
     * 処理を続行する必要があれば、エントリポイントのファンクションをコールします。
     * </p>
     * @param string $method エントリポイントのファンクション名
     * @return ActionResult Actionクラスの実行結果
     * @throws MagicException ActionResultクラスが返されなかった場合
     */
    public final function invoke($method) {
        if ($this->session->isStarted() && $flash = $this->session->get('flash')) {
            $this->flash->setAll($flash);
            $this->session->remove('flash');
        }
        if (is_null($result = $this->intializeMethod())) {
            if (is_null($result = $this->$method())) {
                throw new MagicException(
                        MessageBehavior::getMessage('SYS006',
                                array('ActionResult', get_class($this) . '::' . $method . '()')));
            }
        }
        if ($result instanceof ActionResult) {
            $this->response->set('error', $this->error->get());
            $this->session->set('flash', $this->flash->getAll());
            $result->setResponse($this->response);
            $result->setSession($this->session);
            return $result;
        }
        throw new MagicException(MessageBehavior::getMessage('SYS003', array('ActionResult', get_class($result))));
    }
}
// EOF.