<?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_ComponentMethod.php,v 1.5 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_ComponentMethod.php,v 1.5 2007/01/03 11:17:37 seasonstream Exp $
 * @link      http://www.syl.jp/
 */
class SyL_ComponentMethod
{
    /**
     * ダイレクト取得メソッド名
     * 
     * @access private
     * @var string
     */
    var $direct_method = 'trigger';
    /**
     * コントローラオブジェクト
     * 
     * @access private
     * @var object
     */
    var $controller = null;
    /**
     * アプリケーションコンポーネント名とその最終実行メソッド配列
     * 
     * @access private
     * @var array
     */
    var $app_components = array();

    /**
     * コンストラクタ
     * 
     * @access public
     */
    function SyL_ComponentMethod(&$controller)
    {
        $this->controller =& $controller;
    }

    /**
     * フィルタから値を取得する
     * 
     * @access public
     * @param string フィルタ名
     * @return mixed フィルタからの戻り値
     */
    function triggerFilter($name)
    {
        $name = "__filter_{$name}";
        $component =& $this->getComponent($name);
        $args = func_get_args();
        array_shift($args);
        return call_user_func_array(array(&$component, $this->direct_method), $args);
    }

    /**
     * アプリケーションコンポーネントから値を取得する
     * 
     * @access public
     * @param string アプリケーションコンポーネント名
     * @return mixed アプリケーションコンポーネントからの戻り値
     */
    function triggerApp($name)
    {
        // 既登録チェック
        $match = false;
        foreach (array_keys($this->app_components) as $value) {
            if (preg_match ('/^' . preg_quote($name, '/') . '/', $value)) {
                $match = true;
                break;
            }
        }

        if (!$match) {
            trigger_error("[SyL error] AppComponent not registered ({$name})", E_USER_ERROR);
        }

        $component =& $this->getComponent($name);
        $args = func_get_args();
        array_shift($args);
        return call_user_func_array(array(&$component, $this->direct_method), $args);
    }

    /**
     * コンポーネントを取得する
     * 
     * @access public
     * @param string コンポーネント名
     * @return object コンポーネント
     */
    function &getComponent($name)
    {
        if (!$this->controller->container->isComponent($name)) {
            trigger_error("[SyL error] Filter or AppComponent not registered ({$name})", E_USER_ERROR);
        }
        $component =& $this->controller->container->getComponent($name);
        if (!method_exists($component, $this->direct_method)) {
            trigger_error("[SyL error] Filter or AppComponent method undefined ({$this->direct_method})", E_USER_ERROR);
        }
        return $component;
    }

    /**
     * アプリケーションコンポーネントをセット
     * 
     * @access public
     * @param string アプリケーションコンポーネント名
     * @param string アプリケーションコンポーネント最終メソッド名
     * @param float 実行順序
     */
    function addAppComponent($name, $method, $priority)
    {
        $name = "{$name}:{$method}";
        $this->app_components[$name] = $priority;
    }

    /**
     * アプリケーションコンポーネントの破棄
     * 
     * @access public
     */
    function deleteAppComponent()
    {
        // アプリケーションコンポーネント削除
        if (count($this->app_components) > 0) {
            // 実行順とは逆順にソート
            arsort($this->app_components, SORT_NUMERIC);
            foreach (array_keys($this->app_components) as $value) {
                list($name, $method) = explode(':', $value, 2);
                if ($method != '') {
                   $component =& $this->controller->container->getComponent($name);
                   $component->{$method}();
                }
                $this->controller->container->deleteComponent($name);
            }
        }
    }
}

?>
