<?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_ConfigActions.php,v 1.9 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_ConfigActions.php,v 1.9 2007/01/03 11:17:37 seasonstream Exp $
 * @link      http://www.syl.jp/
 */
class SyL_ConfigActions extends SyL_Config
{
    /**
     * コンテナアクション名
     * 
     * @access private
     * @var object
     */
    var $action_key = SYL_ACTION_KEY;
    /**
     * デフォルト実行順序
     * 
     * @access private
     * @param int
     */
    var $default_priority = 5;
    /**
     * デフォルトテンプレートタイプ
     * 
     * @access private
     * @param string
     */
    var $default_template_type = 'default';
    /**
     * アクション設定ファイルキャッシュキー
     * 
     * @access private
     * @param string
     */
    var $action_cache_key = '__syL_action_cache';
    /**
     * アクション設定ファイルキャッシュデータ
     * 
     * @access private
     * @var array
     */
    var $action_cache_value = array();
    /**
     * データ管理オブジェクト
     * 
     * @access private
     * @var object
     */
    var $dm = null;

    /**
     * コンストラクタ
     *
     * @access public
     * @param string XMLファイル名
     */
    function SyL_ConfigActions($file_name)
    {
        // 親クラスのコンストラクタ
        parent::SyL_Config($file_name);
    }

    /**
     * コントローラをセット
     * ※オーバーライド
     *
     * @access public
     * @param object コントローラオブジェクト
     */
    function setController(&$controller)
    {
        $this->dm =& $controller->container->getComponent('datamanager');
    }

    /**
     * XMLファイルの解析処理
     *
     * @access public
     */
    function parseXML()
    {
        if (SYL_WEBAPP_CACHE_DIR) {
            // キャッシュを使用する
            $key = $this->dm->getActionDir() . $this->dm->getActionFile() . $this->dm->getActionName();
            $cache =& SyL_Cache::getObject($key, 'fileupdate');
            $cache->setCacheDir(SYL_WEBAPP_CACHE_DIR . '/actions');
            $this->config = $cache->read($this->file_names);
            if (!$this->config) {
                parent::parseXML();
                // 一時キャッシュパラメータを保存
                $this->config[$this->action_cache_key] = $this->action_cache_value;
                $cache->write($this->config);
            } else {
                // 一時キャッシュパラメータを取得
                $this->action_cache_value = $this->config[$this->action_cache_key];
            }
            // 一時キャッシュパラメータを削除
            unset($this->config[$this->action_cache_key]);
        } else {
            // キャッシュを使用しない
            parent::parseXML();
        }

        $this->dm->setTemplateFile($this->action_cache_value['template']);
        if (isset($this->action_cache_value['view_parameters'])) {
            foreach ($this->action_cache_value['view_parameters'] as $name => $value) {
                $this->dm->setViewParameter(strtolower($name), $value);
            }
        }

        if (isset($this->action_cache_value['app_component'])) {
            foreach ($this->action_cache_value['app_component'] as $name => $value) {
                $this->dm->cm->addAppComponent($name, $value[0], $value[1]);
            }
        }
    }

/*

key = $this->dm->getActionDir() . $this->dm->getActionFile() . $this->dm->getActionName() が一致
　　テンプレート使用
　　　　取得してセット
　　　　$template
　　　　$view_type
　　　　$attribute['customizedViewFile'], 
　　　　$attribute['customizedViewClass']
　　　　$this->dm->cm->addAppComponent($component_name, '', $component_priority);
　　　　$this->dm->cm->addAppComponent($component_name, $attribute['name'], $component_priority);

一致しない
　　XMLパース
　　キャッシュ保存
　　

*/


    /**
     * XMLデータ内容取得ハンドラメソッド
     * ※オーバーライド
     *
     * @access protected
     * @param string 現在XML解析中のパス
     * @param string XMLのタグの属性値
     * @param string XMLのタグの値
     */
    function getElement($current_path, $attribute, $text)
    {
        static $name               = '';
        static $component_name     = '';
        static $component_priority = 0;
        static $method_name        = '';
        static $load               = false;

//echo $current_path . "<br>";
        // 1アクションロード済みの場合以降スキップ
        if ($load) return;

        // XML解析結果を取得
        switch ($current_path) {
        case '/actions/action':
            if ($name != '') {
                $name = '';
                $load = true;
                return;
            }
            if (isset($attribute['enable']) && ($attribute['enable'] === 'false')) {
                return;
            }

            // アクセスURL確認
            $reg = isset($attribute['path']) ? str_replace('/', '\\/', $attribute['path']) : '(.*)';
            if (preg_match('/^' . $reg . '$/', $this->dm->getActionFile(), $matches)) {
                $name = $this->action_key;
                $this->config[$name]['class']     = $this->dm->getClassName();
                $this->config[$name]['type']      = 'action';
                $this->config[$name]['file']      = $this->dm->getActionDir() . $this->dm->getActionFile();
                $this->config[$name]['reference'] = true;
                // 実行順序
                $this->config[$name]['priority'] = $this->default_priority;
                // コンストラクタインジェクションフラグ
                $this->config[$name]['constructor'] = false;
                // イベントタグ（オブジェクト作成時）
                $this->config[$name]['event'][$this->event][] = $name;
                // 引数
                $this->config[$name]['args'] = array();

                // デフォルトテンプレート取得
                $template = $attribute['template'];
                for ($i=0; $i<count($matches); $i++) {
                    $template = str_replace("\${$i}", $matches[$i], $template);
                }

                $this->action_cache_value['template']  = $template;
                // ビューパラメータセット
                $this->action_cache_value['view_parameters'] = $attribute;
            }
            break;

        default:
            if (!$name) return;

            switch ($current_path) {
            case '/actions/action/method':
                if (!isset($this->config[$name]['args'])) {
                    $this->config[$name]['args'] = array();
                }
                $method_name = 'method:' . str_replace('{$action}', $this->dm->getActionName(), $attribute['name']);
                $this->config[$name]['args'][$method_name] = array();
                // イベントタグ
                $this->config[$name]['event'][$this->event][] = $method_name;
                break;

            case '/actions/action/method/arg':
                $type = isset($attribute['type']) ? $attribute['type'] : 'value';
                $ref  = (isset($attribute['reference']) && ($attribute['reference'] === 'true')) ? 'true' : 'false';
                $this->config[$name]['args'][$method_name][] = $type . ':' . $ref . ':' . $text;
                break;

           case '/actions/action/components/component':
                if (isset($attribute['enable']) && ($attribute['enable'] === 'false')) {
                    $component_name = '';
                    return;
                }
                $component_name = $attribute['name'];
                $this->config[$component_name]['class']     = $attribute['class'];
                $this->config[$component_name]['type']      = 'component';
                $this->config[$component_name]['file']      = isset($attribute['file']) ? $attribute['file'] : '';
                $this->config[$component_name]['reference'] = false;
                // 実行順序(アクションより1段階早い)
                $default_priority = $this->default_priority - 1;
                $component_priority = isset($attribute['priority']) ? floatval($default_priority . '.' . $attribute['priority']) : $default_priority;
                $this->config[$component_name]['priority'] = $component_priority;
                // コンストラクタインジェクションフラグ
                $this->config[$component_name]['constructor'] = false;
                // イベントタグ
                $this->config[$component_name]['event'][$this->event][] = $component_name;
                // 引数
                $this->config[$component_name]['args'] = array();

                // アプリケーションコンポーネント名セット
                $this->action_cache_value['app_component'][$component_name] = array('', $component_priority);
                break;

            default:
                if (!$component_name) return;

                switch ($current_path) {
                case '/actions/action/components/component/constructor':
                    $method_name = 'constructor:' . (isset($attribute['static']) ? $attribute['static'] : '');
                    // コンストラクタインジェクションフラグ
                    $this->config[$component_name]['constructor'] = true;
                    // コンストラクタインジェクションの場合、元のメソッドは削除
                    $index = array_search($component_name, $this->config[$component_name]['event'][$this->event]);
                    if ($index !== false) {
                        unset($this->config[$component_name]['event'][$this->event][$index]);
                    }
                    $this->config[$component_name]['event'][$this->event][] = $method_name;
                    $this->config[$component_name]['args'][$method_name] = array();
                    break;

                case '/actions/action/components/component/constructor/arg':
                    $type = isset($attribute['type']) ? $attribute['type'] : 'value';
                    $ref  = (isset($attribute['reference']) && ($attribute['reference'] === 'true')) ? 'true' : 'false';
                    $this->config[$component_name]['args'][$method_name][] = $type . ':' . $ref . ':' . $text;
                    break;

                case '/actions/action/components/component/setter':
                    // ダイレクトセットタグ
                    if (isset($attribute['direct']) && ($attribute['direct'] === 'true')) {
                        $method_name = 'setter:' . $attribute['name'] . ':true';
                    } else {
                        $method_name = 'setter:set' . ucfirst(strtolower($attribute['name'])) . ':false';
                    }
                    $this->config[$component_name]['event'][$this->event][] = $method_name;
                    $this->config[$component_name]['args'][$method_name] = array();
                    break;

                case '/actions/action/components/component/setter/arg':
                    $type = isset($attribute['type']) ? $attribute['type'] : 'value';
                    $ref  = (isset($attribute['reference']) && ($attribute['reference'] === 'true')) ? 'true' : 'false';
                    $this->config[$component_name]['args'][$method_name][] = $type . ':' . $ref . ':' . $text;
                    break;

                case '/actions/action/components/component/method':
                    $method_name = 'method:' . $attribute['name'];
                    $this->config[$component_name]['event'][$this->event][] = $method_name;
                    $this->config[$component_name]['args'][$method_name] = array();
                    break;

                case '/actions/action/components/component/method/arg':
                    $type = isset($attribute['type']) ? $attribute['type'] : 'value';
                    $ref  = (isset($attribute['reference']) && ($attribute['reference'] === 'true')) ? 'true' : 'false';
                    $this->config[$component_name]['args'][$method_name][] = $type . ':' . $ref . ':' . $text;
                    break;

                case '/actions/action/components/component/final':
                    // アプリケーションコンポーネント名セット
                    $this->action_cache_value['app_component'][$component_name] = array($attribute['name'], $component_priority);
                    break;
                }
            }
        }
    }
}

?>
