2 // vim: foldmethod=marker
6 * @author Masaki Fujimoto <fujimoto@php.net>
7 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
12 // {{{ Ethna_Controller
16 * @todo gatewayでswitchしてるところがダサダサ
18 * @author Masaki Fujimoto <fujimoto@php.net>
22 class Ethna_Controller
28 /** @var string アプリケーションID */
31 /** @var string アプリケーションベースディレクトリ */
34 /** @var string アプリケーションベースURL */
37 /** @var string アプリケーションDSN(Data Source Name) */
40 /** @var array アプリケーションディレクトリ */
41 var $directory = array();
43 /** @var array アプリケーションディレクトリ(デフォルト) */
44 var $directory_default = array(
45 'action' => 'app/action',
46 'action_cli' => 'app/action_cli',
47 'action_xmlrpc' => 'app/action_xmlrpc',
49 'plugin' => 'app/plugin',
52 'filter' => 'app/filter',
56 'template' => 'template',
57 'template_c' => 'tmp',
64 /** @var array DBアクセス定義 */
69 /** @var array 拡張子設定 */
75 /** @var array クラス設定 */
78 /** @var array クラス設定(デフォルト) */
79 var $class_default = array(
80 'class' => 'Ethna_ClassFactory',
81 'backend' => 'Ethna_Backend',
82 'config' => 'Ethna_Config',
84 'error' => 'Ethna_ActionError',
85 'form' => 'Ethna_ActionForm',
86 'i18n' => 'Ethna_I18N',
87 'logger' => 'Ethna_Logger',
88 'plugin' => 'Ethna_Plugin',
89 'renderer' => 'Ethna_Renderer_Smarty',
90 'session' => 'Ethna_Session',
91 'sql' => 'Ethna_AppSQL',
92 'view' => 'Ethna_ViewClass',
93 'url_handler' => 'Ethna_UrlHandler',
96 /** @var array 検索対象となるプラグインのアプリケーションIDのリスト */
97 var $plugin_search_appids;
99 /** @var array フィルタ設定 */
103 /** @var string 使用言語設定 */
106 /** @var string システム側エンコーディング */
107 var $system_encoding;
109 /** @var string クライアント側エンコーディング */
110 var $client_encoding;
112 /** @var string 現在実行中のアクション名 */
115 /** @var string 現在実行中のXMLRPCメソッド名 */
116 var $xmlrpc_method_name;
118 /** @var array forward定義 */
119 var $forward = array();
121 /** @var array action定義 */
122 var $action = array();
124 /** @var array action(CLI)定義 */
125 var $action_cli = array();
127 /** @var array action(XMLRPC)定義 */
128 var $action_xmlrpc = array();
130 /** @var array アプリケーションマネージャ定義 */
131 var $manager = array();
133 /** @var object レンダラー */
134 var $renderer = null;
136 /** @var array smarty modifier定義 */
137 var $smarty_modifier_plugin = array();
139 /** @var array smarty function定義 */
140 var $smarty_function_plugin = array();
142 /** @var array smarty block定義 */
143 var $smarty_block_plugin = array();
145 /** @var array smarty prefilter定義 */
146 var $smarty_prefilter_plugin = array();
148 /** @var array smarty postfilter定義 */
149 var $smarty_postfilter_plugin = array();
151 /** @var array smarty outputfilter定義 */
152 var $smarty_outputfilter_plugin = array();
155 /** @var array フィルターチェイン(Ethna_Filterオブジェクトの配列) */
156 var $filter_chain = array();
158 /** @var object Ethna_ClassFactory クラスファクトリオブジェクト */
159 var $class_factory = null;
161 /** @var object Ethna_ActionForm フォームオブジェクト */
162 var $action_form = null;
164 /** @var object Ethna_View ビューオブジェクト */
167 /** @var object Ethna_Config 設定オブジェクト */
170 /** @var object Ethna_Logger ログオブジェクト */
173 /** @var object Ethna_Plugin プラグインオブジェクト */
176 /** @var string リクエストのゲートウェイ(www/cli/rest/xmlrpc/soap...) */
177 var $gateway = GATEWAY_WWW;
183 * Ethna_Controllerクラスのコンストラクタ
187 function Ethna_Controller($gateway = GATEWAY_WWW)
189 $GLOBALS['_Ethna_controller'] =& $this;
190 if ($this->base === "") {
191 // EthnaコマンドなどでBASEが定義されていない場合がある
192 if (defined('BASE')) {
197 $this->gateway = $gateway;
200 foreach ($this->class_default as $key => $val) {
201 if (isset($this->class[$key]) == false) {
202 $this->class[$key] = $val;
207 foreach ($this->directory_default as $key => $val) {
208 if (isset($this->directory[$key]) == false) {
209 $this->directory[$key] = $val;
214 $class_factory = $this->class['class'];
215 $this->class_factory =& new $class_factory($this, $this->class);
218 Ethna::setErrorCallback(array(&$this, 'handleError'));
220 // ディレクトリ名の設定(相対パス->絶対パス)
221 foreach ($this->directory as $key => $value) {
222 if ($key == 'plugins') {
223 // Smartyプラグインディレクトリは配列で指定する
225 foreach (to_array($value) as $elt) {
226 if (Ethna_Util::isAbsolute($elt) == false) {
227 $tmp[] = $this->base . (empty($this->base) ? '' : '/') . $elt;
230 $this->directory[$key] = $tmp;
232 if (Ethna_Util::isAbsolute($value) == false) {
233 $this->directory[$key] = $this->base . (empty($this->base) ? '' : '/') . $value;
239 list($this->language, $this->system_encoding, $this->client_encoding) = $this->_getDefaultLanguage();
241 $this->config =& $this->getConfig();
242 $this->dsn = $this->_prepareDSN();
243 $this->url = $this->config->get('url');
246 $this->plugin =& $this->getPlugin();
248 //// assert (experimental)
249 //if ($this->config->get('debug') === false) {
250 // ini_set('assert.active', 0);
254 $this->logger =& $this->getLogger();
255 $this->plugin->setLogger($this->logger);
256 $this->logger->begin();
259 $this->_activateEthnaManager();
263 * (現在アクティブな)コントローラのインスタンスを返す
266 * @return object Ethna_Controller コントローラのインスタンス
269 function &getInstance()
271 if (isset($GLOBALS['_Ethna_controller'])) {
272 return $GLOBALS['_Ethna_controller'];
283 * @return string アプリケーションID
287 return ucfirst(strtolower($this->appid));
294 * @param string $id アプリケーションID
295 * @return mixed true:OK Ethna_Error:NG
298 function &checkAppId($id)
301 if (strcasecmp($id, 'ethna') === 0
302 || strcasecmp($id, 'app') === 0) {
303 return Ethna::raiseError("Application Id [$id] is reserved\n");
305 if (preg_match('/^[0-9a-zA-Z]+$/', $id) === 0) {
306 return Ethna::raiseError(
307 "Only Numeric(0-9) and Alphabetical(A-Z) is allowed for Application Id\n"
317 * @param string $action_name アクション名
318 * @return mixed true:OK Ethna_Error:NG
321 function &checkActionName($action_name)
324 if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
325 $action_name) === 0) {
326 return Ethna::raiseError("invalid action name [$action_name]");
335 * @param string $view_name ビュー名
336 * @return mixed true:OK Ethna_Error:NG
339 function &checkViewName($view_name)
342 if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
344 return Ethna::raiseError("invalid view name [$view_name]");
353 * @param string $db_key DBキー
356 function getDSN($db_key = "")
358 if (isset($this->dsn[$db_key]) == false) {
361 return $this->dsn[$db_key];
368 * @param string $db_key DBキー
369 * @return bool true:persistent false:non-persistent(あるいは設定無し)
371 function getDSN_persistent($db_key = "")
373 $key = sprintf("dsn%s_persistent", $db_key == "" ? "" : "_$db_key");
375 $dsn_persistent = $this->config->get($key);
376 if (is_null($dsn_persistent)) {
379 return $dsn_persistent;
386 * @param string $db_key DBキー("", "r", "rw", "default", "blog_r"...)
387 * @return string $db_keyに対応するDB種別定義(設定が無い場合はnull)
389 function getDBType($db_key = null)
391 if (is_null($db_key)) {
396 if (isset($this->db[$db_key]) == false) {
399 return $this->db[$db_key];
406 * @return string アプリケーションベースURL
414 * アプリケーションベースディレクトリを返す
417 * @return string アプリケーションベースディレクトリ
419 function getBasedir()
425 * クライアントタイプ/言語からテンプレートディレクトリ名を決定する
428 * @return string テンプレートディレクトリ
430 function getTemplatedir()
432 $template = $this->getDirectory('template');
435 if (file_exists($template . '/' . $this->language)) {
436 $template .= '/' . $this->language;
446 * @return string アクションディレクトリ
448 function getActiondir($gateway = null)
451 $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
460 $key = 'action_xmlrpc';
464 return (empty($this->directory[$key]) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory[$key] . "/"));
471 * @return string ビューディレクトリ
473 function getViewdir()
475 return (empty($this->directory['view']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['view'] . "/"));
479 * (action,view以外の)テストケースを置くディレクトリ名を決定する
482 * @return string テストケースを置くディレクトリ
484 function getTestdir()
486 return (empty($this->directory['test']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['test'] . "/"));
490 * アプリケーションディレクトリ設定を返す
493 * @param string $key ディレクトリタイプ("tmp", "template"...)
494 * @return string $keyに対応したアプリケーションディレクトリ(設定が無い場合はnull)
496 function getDirectory($key)
499 if ($key == 'app' && isset($this->directory[$key]) == false) {
500 return BASE . '/app';
503 if (isset($this->directory[$key]) == false) {
506 return $this->directory[$key];
513 * @param string $key 拡張子タイプ("php", "tpl"...)
514 * @return string $keyに対応した拡張子(設定が無い場合はnull)
516 function getExt($key)
518 if (isset($this->ext[$key]) == false) {
521 return $this->ext[$key];
525 * クラスファクトリオブジェクトのアクセサ(R)
528 * @return object Ethna_ClassFactory クラスファクトリオブジェクト
530 function &getClassFactory()
532 return $this->class_factory;
536 * アクションエラーオブジェクトのアクセサ
539 * @return object Ethna_ActionError アクションエラーオブジェクト
541 function &getActionError()
543 return $this->class_factory->getObject('error');
547 * アクションフォームオブジェクトのアクセサ
550 * @return object Ethna_ActionForm アクションフォームオブジェクト
552 function &getActionForm()
554 // 明示的にクラスファクトリを利用していない
555 return $this->action_form;
562 * @return object Ethna_View ビューオブジェクト
566 // 明示的にクラスファクトリを利用していない
574 * @return object Ethna_Backend backendオブジェクト
576 function &getBackend()
578 return $this->class_factory->getObject('backend');
585 * @return object Ethna_Config 設定オブジェクト
587 function &getConfig()
589 return $this->class_factory->getObject('config');
596 * @return object Ethna_I18N i18nオブジェクト
600 return $this->class_factory->getObject('i18n');
607 * @return object Ethna_Logger ログオブジェクト
609 function &getLogger()
611 return $this->class_factory->getObject('logger');
618 * @return object Ethna_Session セッションオブジェクト
620 function &getSession()
622 return $this->class_factory->getObject('session');
629 * @return object Ethna_AppSQL SQLオブジェクト
633 return $this->class_factory->getObject('sql');
640 * @return object Ethna_Plugin プラグインオブジェクト
642 function &getPlugin()
644 return $this->class_factory->getObject('plugin');
651 * @return object Ethna_UrlHandler URLハンドラオブジェクト
653 function &getUrlHandler()
655 return $this->class_factory->getObject('url_handler');
662 * @return array マネージャ一覧
665 function getManagerList()
667 return $this->manager;
674 * @return string 実行中のアクション名
676 function getCurrentActionName()
678 return $this->action_name;
685 * @return string 実行中のXMLRPCメソッド名
687 function getXmlrpcMethodName()
689 return $this->xmlrpc_method_name;
696 * @return array 使用言語,システムエンコーディング名,クライアントエンコーディング名
698 function getLanguage()
700 return array($this->language, $this->system_encoding, $this->client_encoding);
708 function getGateway()
710 return $this->gateway;
718 function setGateway($gateway)
720 $this->gateway = $gateway;
727 * @param string $class_name アプリケーションコントローラのクラス名
728 * @param mixed $action_name 指定のアクション名(省略可)
729 * @param mixed $fallback_action_name アクションが決定できなかった場合に実行されるアクション名(省略可)
732 function main($class_name, $action_name = "", $fallback_action_name = "")
734 $c =& new $class_name;
735 $c->trigger($action_name, $fallback_action_name);
739 * CLIアプリケーションのエントリポイント
742 * @param string $class_name アプリケーションコントローラのクラス名
743 * @param string $action_name 実行するアクション名
744 * @param bool $enable_filter フィルタチェインを有効にするかどうか
747 function main_CLI($class_name, $action_name, $enable_filter = true)
749 $c =& new $class_name(GATEWAY_CLI);
750 $c->action_cli[$action_name] = array();
751 $c->trigger($action_name, "", $enable_filter);
755 * XMLRPCアプリケーションのエントリポイント
760 function main_XMLRPC($class_name)
762 if (extension_loaded('xmlrpc') == false) {
763 die("xmlrpc extension is required to enable this gateway");
766 $c =& new $class_name(GATEWAY_XMLRPC);
767 $c->trigger("", "", false);
771 * SOAPアプリケーションのエントリポイント
774 * @param string $class_name アプリケーションコントローラのクラス名
775 * @param mixed $action_name 指定のアクション名(省略可)
776 * @param mixed $fallback_action_name アクションが決定できなかった場合に実行されるアクション名(省略可)
779 function main_SOAP($class_name, $action_name = "", $fallback_action_name = "")
781 $c =& new $class_name(GATEWAY_SOAP);
782 $c->trigger($action_name, $fallback_action_name);
789 * @param mixed $default_action_name 指定のアクション名
790 * @param mixed $fallback_action_name アクション名が決定できなかった場合に実行されるアクション名
791 * @param bool $enable_filter フィルタチェインを有効にするかどうか
792 * @return mixed 0:正常終了 Ethna_Error:エラー
794 function trigger($default_action_name = "", $fallback_action_name = "", $enable_filter = true)
797 if ($enable_filter) {
798 $this->_createFilterChain();
802 for ($i = 0; $i < count($this->filter_chain); $i++) {
803 $r = $this->filter_chain[$i]->preFilter();
804 if (Ethna::isError($r)) {
810 switch ($this->getGateway()) {
812 $this->_trigger_WWW($default_action_name, $fallback_action_name);
815 $this->_trigger_CLI($default_action_name);
818 $this->_trigger_XMLRPC();
821 $this->_trigger_SOAP();
826 for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
827 $r = $this->filter_chain[$i]->postFilter();
828 if (Ethna::isError($r)) {
835 * フレームワークの処理を実行する(WWW)
837 * 引数$default_action_nameに配列が指定された場合、その配列で指定された
838 * アクション以外は受け付けない(指定されていないアクションが指定された
839 * 場合、配列の先頭で指定されたアクションが実行される)
842 * @param mixed $default_action_name 指定のアクション名
843 * @param mixed $fallback_action_name アクション名が決定できなかった場合に実行されるアクション名
844 * @return mixed 0:正常終了 Ethna_Error:エラー
846 function _trigger_WWW($default_action_name = "", $fallback_action_name = "")
849 $action_name = $this->_getActionName($default_action_name, $fallback_action_name);
852 $this->_ethnaManagerEnabledCheck($action_name);
855 $action_obj =& $this->_getAction($action_name);
856 if (is_null($action_obj)) {
857 if ($fallback_action_name != "") {
858 $this->logger->log(LOG_DEBUG, 'undefined action [%s] -> try fallback action [%s]', $action_name, $fallback_action_name);
859 $action_obj =& $this->_getAction($fallback_action_name);
861 if (is_null($action_obj)) {
862 return Ethna::raiseError("undefined action [%s]", E_APP_UNDEFINED_ACTION, $action_name);
864 $action_name = $fallback_action_name;
869 for ($i = 0; $i < count($this->filter_chain); $i++) {
870 $r = $this->filter_chain[$i]->preActionFilter($action_name);
872 $this->logger->log(LOG_DEBUG, 'action [%s] -> [%s] by %s', $action_name, $r, get_class($this->filter_chain[$i]));
876 $this->action_name = $action_name;
879 $this->_setLanguage($this->language, $this->system_encoding, $this->client_encoding);
882 $backend =& $this->getBackend();
884 $form_name = $this->getActionFormName($action_name);
885 $this->action_form =& new $form_name($this);
886 $this->action_form->setFormVars();
889 $backend->setActionForm($this->action_form);
891 $session =& $this->getSession();
893 $forward_name = $backend->perform($action_name);
896 for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
897 $r = $this->filter_chain[$i]->postActionFilter($action_name, $forward_name);
899 $this->logger->log(LOG_DEBUG, 'forward [%s] -> [%s] by %s', $forward_name, $r, get_class($this->filter_chain[$i]));
904 // コントローラで遷移先を決定する(オプション)
905 $forward_name = $this->_sortForward($action_name, $forward_name);
907 if ($forward_name != null) {
908 $view_class_name = $this->getViewClassName($forward_name);
909 $this->view =& new $view_class_name($backend, $forward_name, $this->_getForwardPath($forward_name));
910 $this->view->preforward();
911 $this->view->forward();
918 * フレームワークの処理を実行する(CLI)
921 * @param mixed $default_action_name 指定のアクション名
922 * @return mixed 0:正常終了 Ethna_Error:エラー
924 function _trigger_CLI($default_action_name = "")
926 return $this->_trigger_WWW($default_action_name);
930 * フレームワークの処理を実行する(XMLRPC)
933 * @param mixed $action_name 指定のアクション名
934 * @return mixed 0:正常終了 Ethna_Error:エラー
936 function _trigger_XMLRPC($action_name = "")
938 // prepare xmlrpc server
939 $xmlrpc_gateway_method_name = "_Ethna_XmlrpcGateway";
940 $xmlrpc_server = xmlrpc_server_create();
943 $param = xmlrpc_decode_request(file_get_contents('php://input'), $method);
944 $this->xmlrpc_method_name = $method;
946 $request = xmlrpc_encode_request(
947 $xmlrpc_gateway_method_name,
950 'output_type' => 'xml',
951 'verbosity' => 'pretty',
952 'escaping' => array('markup'),
953 'version' => 'xmlrpc',
954 'encoding' => 'utf-8'
958 xmlrpc_server_register_method(
960 $xmlrpc_gateway_method_name,
961 $xmlrpc_gateway_method_name
965 $r = xmlrpc_server_call_method(
970 'output_type' => 'xml',
971 'verbosity' => 'pretty',
972 'escaping' => array('markup'),
973 'version' => 'xmlrpc',
974 'encoding' => 'utf-8'
978 header('Content-Length: ' . strlen($r));
979 header('Content-Type: text/xml; charset=UTF-8');
984 * _trigger_XMLRPCのコールバックメソッド
988 function trigger_XMLRPC($method, $param)
991 $action_obj =& $this->_getAction($method);
992 if (is_null($action_obj)) {
993 return Ethna::raiseError("undefined xmlrpc method [%s]", E_APP_UNDEFINED_ACTION, $method);
997 $backend =& $this->getBackend();
999 $form_name = $this->getActionFormName($method);
1000 $this->action_form =& new $form_name($this);
1001 $def = $this->action_form->getDef();
1003 foreach ($def as $key => $value) {
1004 if (isset($param[$n]) == false) {
1005 $this->action_form->set($key, null);
1007 $this->action_form->set($key, $param[$n]);
1013 $backend->setActionForm($this->action_form);
1015 $session =& $this->getSession();
1016 $session->restore();
1017 $r = $backend->perform($method);
1023 * SOAPフレームワークの処理を実行する
1027 function _trigger_SOAP()
1030 $gg =& new Ethna_SOAP_GatewayGenerator();
1031 $script = $gg->generate();
1035 $server =& new SoapServer(null, array('uri' => $this->config->get('url')));
1036 $server->setClass($gg->getClassName());
1043 * エラー発生時の追加処理を行いたい場合はこのメソッドをオーバーライドする
1044 * (アラートメール送信等−デフォルトではログ出力時にアラートメール
1045 * が送信されるが、エラー発生時に別にアラートメールをここで送信
1049 * @param object Ethna_Error エラーオブジェクト
1051 function handleError(&$error)
1054 list ($log_level, $dummy) = $this->logger->errorLevelToLogLevel($error->getLevel());
1055 $message = $error->getMessage();
1056 $this->logger->log($log_level, sprintf("%s [ERROR CODE(%d)]", $message, $error->getCode()));
1063 * @param int $code エラーコード
1064 * @return string エラーメッセージ
1066 function getErrorMessage($code)
1068 $message_list =& $GLOBALS['_Ethna_error_message_list'];
1069 for ($i = count($message_list)-1; $i >= 0; $i--) {
1070 if (array_key_exists($code, $message_list[$i])) {
1071 return $message_list[$i][$code];
1081 * @param mixed $default_action_name 指定のアクション名
1082 * @return string 実行するアクション名
1084 function _getActionName($default_action_name, $fallback_action_name)
1086 // フォームから要求されたアクション名を取得する
1087 $form_action_name = $this->_getActionName_Form();
1088 $form_action_name = preg_replace('/[^a-z0-9\-_]+/i', '', $form_action_name);
1089 $this->logger->log(LOG_DEBUG, 'form_action_name[%s]', $form_action_name);
1091 // Ethnaマネージャへのフォームからのリクエストは拒否
1092 if ($form_action_name == "__ethna_info__" ||
1093 $form_action_name == "__ethna_unittest__") {
1094 $form_action_name = "";
1097 // フォームからの指定が無い場合はエントリポイントに指定されたデフォルト値を利用する
1098 if ($form_action_name == "" && count($default_action_name) > 0) {
1099 $tmp = is_array($default_action_name) ? $default_action_name[0] : $default_action_name;
1100 if ($tmp{strlen($tmp)-1} == '*') {
1101 $tmp = substr($tmp, 0, -1);
1103 $this->logger->log(LOG_DEBUG, '-> default_action_name[%s]', $tmp);
1104 $action_name = $tmp;
1106 $action_name = $form_action_name;
1109 // エントリポイントに配列が指定されている場合は指定以外のアクション名は拒否する
1110 if (is_array($default_action_name)) {
1111 if ($this->_isAcceptableActionName($action_name, $default_action_name) == false) {
1112 // 指定以外のアクション名で合った場合は$fallback_action_name(or デフォルト)
1113 $tmp = $fallback_action_name != "" ? $fallback_action_name : $default_action_name[0];
1114 if ($tmp{strlen($tmp)-1} == '*') {
1115 $tmp = substr($tmp, 0, -1);
1117 $this->logger->log(LOG_DEBUG, '-> fallback_action_name[%s]', $tmp);
1118 $action_name = $tmp;
1122 $this->logger->log(LOG_DEBUG, '<<< action_name[%s] >>>', $action_name);
1124 return $action_name;
1128 * フォームにより要求されたアクション名を返す
1130 * アプリケーションの性質に応じてこのメソッドをオーバーライドして下さい。
1131 * デフォルトでは"action_"で始まるフォーム値の"action_"の部分を除いたもの
1132 * ("action_sample"なら"sample")がアクション名として扱われます
1135 * @return string フォームにより要求されたアクション名
1137 function _getActionName_Form()
1139 if (isset($_SERVER['REQUEST_METHOD']) == false) {
1143 $url_handler =& $this->getUrlHandler();
1144 if ($_SERVER['REQUEST_METHOD'] == "GET") {
1146 } else if ($_SERVER['REQUEST_METHOD'] == "POST") {
1150 if (empty($_SERVER['URL_HANDLER']) == false) {
1151 $tmp_vars['__url_handler__'] = $_SERVER['URL_HANDLER'];
1152 $tmp_vars['__url_info__'] = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : null;
1153 $tmp_vars = $url_handler->requestToAction($tmp_vars);
1155 if ($_SERVER['REQUEST_METHOD'] == "GET") {
1156 $_GET = array_merge($_GET, $tmp_vars);
1157 } else if ($_SERVER['REQUEST_METHOD'] == "POST") {
1158 $_POST = array_merge($_POST, $tmp_vars);
1160 $_REQUEST = array_merge($_REQUEST, $tmp_vars);
1163 if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0) {
1164 $http_vars =& $_POST;
1166 $http_vars =& $_GET;
1169 // フォーム値からリクエストされたアクション名を取得する
1170 $action_name = $sub_action_name = null;
1171 foreach ($http_vars as $name => $value) {
1172 if ($value == "" || strncmp($name, 'action_', 7) != 0) {
1176 $tmp = substr($name, 7);
1179 if (preg_match('/_x$/', $name) || preg_match('/_y$/', $name)) {
1180 $tmp = substr($tmp, 0, strlen($tmp)-2);
1183 // value="dummy"となっているものは優先度を下げる
1184 if ($value == "dummy") {
1185 $sub_action_name = $tmp;
1187 $action_name = $tmp;
1190 if ($action_name == null) {
1191 $action_name = $sub_action_name;
1194 return $action_name;
1198 * アクション名を指定するクエリ/HTMLを生成する
1201 * @param string $action action to request
1202 * @param string $type hidden, url...
1203 * @todo consider gateway
1205 function getActionRequest($action, $type = "hidden")
1208 if ($type == "hidden") {
1209 $s = sprintf('<input type="hidden" name="action_%s" value="true">', htmlspecialchars($action, ENT_QUOTES));
1210 } else if ($type == "url") {
1211 $s = sprintf('action_%s=true', urlencode($action));
1217 * フォームにより要求されたアクション名に対応する定義を返す
1220 * @param string $action_name アクション名
1221 * @return array アクション定義
1223 function &_getAction($action_name, $gateway = null)
1226 $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
1229 $action =& $this->action;
1232 $action =& $this->action_cli;
1234 case GATEWAY_XMLRPC:
1235 $action =& $this->action_xmlrpc;
1239 $action_obj = array();
1240 if (isset($action[$action_name])) {
1241 $action_obj = $action[$action_name];
1242 if (isset($action_obj['inspect']) && $action_obj['inspect']) {
1246 $this->logger->log(LOG_DEBUG, "action [%s] is not defined -> try default", $action_name);
1249 // アクションスクリプトのインクルード
1250 $this->_includeActionScript($action_obj, $action_name);
1253 if (isset($action_obj['class_name']) == false) {
1254 $action_obj['class_name'] = $this->getDefaultActionClass($action_name);
1257 if (isset($action_obj['form_name']) == false) {
1258 $action_obj['form_name'] = $this->getDefaultFormClass($action_name);
1259 } else if (class_exists($action_obj['form_name']) == false) {
1260 // 明示指定されたフォームクラスが定義されていない場合は警告
1261 $this->logger->log(LOG_WARNING, 'stated form class is not defined [%s]', $action_obj['form_name']);
1265 if (class_exists($action_obj['class_name']) == false) {
1266 $this->logger->log(LOG_NOTICE, 'action class is not defined [%s]', $action_obj['class_name']);
1267 $_ret_object = null;
1268 return $_ret_object;
1270 if (class_exists($action_obj['form_name']) == false) {
1272 $class_name = $this->class_factory->getObjectName('form');
1273 $this->logger->log(LOG_DEBUG, 'form class is not defined [%s] -> falling back to default [%s]', $action_obj['form_name'], $class_name);
1274 $action_obj['form_name'] = $class_name;
1277 $action_obj['inspect'] = true;
1278 $action[$action_name] = $action_obj;
1279 return $action[$action_name];
1283 * アクション名とアクションクラスからの戻り値に基づいて遷移先を決定する
1286 * @param string $action_name アクション名
1287 * @param string $retval アクションクラスからの戻り値
1288 * @return string 遷移先
1290 function _sortForward($action_name, $retval)
1300 function _createFilterChain()
1302 $this->filter_chain = array();
1303 foreach ($this->filter as $filter) {
1304 //バージョン0.2.0以前のフィルタ群から探す
1305 $file = sprintf("%s/%s.%s", $this->getDirectory('filter'), $filter,$this->getExt('php'));
1306 if (file_exists($file)) {
1308 if (class_exists($filter)) {
1309 $this->filter_chain[] =& new $filter($this);
1311 } else { //プラグインから探す.
1312 $filter_plugin =& $this->plugin->getPlugin('Filter', $filter);
1313 if (Ethna::isError($filter_plugin)) {
1317 $this->filter_chain[] =& $filter_plugin;
1323 * アクション名が実行許可されているものかどうかを返す
1326 * @param string $action_name リクエストされたアクション名
1327 * @param array $default_action_name 許可されているアクション名
1328 * @return bool true:許可 false:不許可
1330 function _isAcceptableActionName($action_name, $default_action_name)
1332 foreach (to_array($default_action_name) as $name) {
1333 if ($action_name == $name) {
1335 } else if ($name{strlen($name)-1} == '*') {
1336 if (strncmp($action_name, substr($name, 0, -1), strlen($name)-1) == 0) {
1345 * 指定されたアクションのフォームクラス名を返す(オブジェクトの生成は行わない)
1348 * @param string $action_name アクション名
1349 * @return string アクションのフォームクラス名
1351 function getActionFormName($action_name)
1353 $action_obj =& $this->_getAction($action_name);
1354 if (is_null($action_obj)) {
1358 return $action_obj['form_name'];
1362 * アクションに対応するフォームクラス名が省略された場合のデフォルトクラス名を返す
1364 * デフォルトでは[プロジェクトID]_Form_[アクション名]となるので好み応じてオーバライドする
1367 * @param string $action_name アクション名
1368 * @return string アクションフォーム名
1370 function getDefaultFormClass($action_name, $gateway = null)
1372 $gateway_prefix = $this->_getGatewayPrefix($gateway);
1374 $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
1375 $r = sprintf("%s_%sForm_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
1376 $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
1382 * getDefaultFormClass()で取得したクラス名からアクション名を取得する
1384 * getDefaultFormClass()をオーバーライドした場合、こちらも合わせてオーバーライド
1388 * @param string $class_name フォームクラス名
1389 * @return string アクション名
1391 function actionFormToName($class_name)
1393 $prefix = sprintf("%s_Form_", $this->getAppId());
1394 if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
1398 $target = $match[1];
1400 $action_name = substr(preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $target), 1);
1402 return $action_name;
1406 * アクションに対応するフォームパス名が省略された場合のデフォルトパス名を返す
1408 * デフォルトでは_getDefaultActionPath()と同じ結果を返す(1ファイルに
1409 * アクションクラスとフォームクラスが記述される)ので、好みに応じて
1413 * @param string $action_name アクション名
1414 * @return string form classが定義されるスクリプトのパス名
1416 function getDefaultFormPath($action_name)
1418 return $this->getDefaultActionPath($action_name);
1422 * 指定されたアクションのクラス名を返す(オブジェクトの生成は行わない)
1425 * @param string $action_name アクションの名称
1426 * @return string アクションのクラス名
1428 function getActionClassName($action_name)
1430 $action_obj =& $this->_getAction($action_name);
1431 if ($action_obj == null) {
1435 return $action_obj['class_name'];
1439 * アクションに対応するアクションクラス名が省略された場合のデフォルトクラス名を返す
1441 * デフォルトでは[プロジェクトID]_Action_[アクション名]となるので好み応じてオーバライドする
1444 * @param string $action_name アクション名
1445 * @return string アクションクラス名
1447 function getDefaultActionClass($action_name, $gateway = null)
1449 $gateway_prefix = $this->_getGatewayPrefix($gateway);
1451 $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
1452 $r = sprintf("%s_%sAction_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
1453 $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
1459 * getDefaultActionClass()で取得したクラス名からアクション名を取得する
1461 * getDefaultActionClass()をオーバーライドした場合、こちらも合わせてオーバーライド
1465 * @param string $class_name アクションクラス名
1466 * @return string アクション名
1468 function actionClassToName($class_name)
1470 $prefix = sprintf("%s_Action_", $this->getAppId());
1471 if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
1475 $target = $match[1];
1477 $action_name = substr(preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $target), 1);
1479 return $action_name;
1483 * アクションに対応するアクションパス名が省略された場合のデフォルトパス名を返す
1485 * デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
1488 * @param string $action_name アクション名
1489 * @return string アクションクラスが定義されるスクリプトのパス名
1491 function getDefaultActionPath($action_name)
1493 $r = preg_replace('/_(.)/e', "'/' . strtoupper('\$1')", ucfirst($action_name)) . '.' . $this->getExt('php');
1494 $this->logger->log(LOG_DEBUG, "default action path [%s]", $r);
1500 * 指定された遷移名に対応するビュークラス名を返す(オブジェクトの生成は行わない)
1503 * @param string $forward_name 遷移先の名称
1504 * @return string view classのクラス名
1506 function getViewClassName($forward_name)
1508 if ($forward_name == null) {
1512 if (isset($this->forward[$forward_name])) {
1513 $forward_obj = $this->forward[$forward_name];
1515 $forward_obj = array();
1518 if (isset($forward_obj['view_name'])) {
1519 $class_name = $forward_obj['view_name'];
1520 if (class_exists($class_name)) {
1528 $this->_includeViewScript($forward_obj, $forward_name);
1530 if (is_null($class_name) == false && class_exists($class_name)) {
1532 } else if (is_null($class_name) == false) {
1533 $this->logger->log(LOG_WARNING, 'stated view class is not defined [%s] -> try default', $class_name);
1536 $class_name = $this->getDefaultViewClass($forward_name);
1537 if (class_exists($class_name)) {
1540 $class_name = $this->class_factory->getObjectName('view');
1541 $this->logger->log(LOG_DEBUG, 'view class is not defined for [%s] -> use default [%s]', $forward_name, $class_name);
1547 * 遷移名に対応するビュークラス名が省略された場合のデフォルトクラス名を返す
1549 * デフォルトでは[プロジェクトID]_View_[遷移名]となるので好み応じてオーバライドする
1552 * @param string $forward_name forward名
1553 * @return string view classクラス名
1555 function getDefaultViewClass($forward_name, $gateway = null)
1557 $gateway_prefix = $this->_getGatewayPrefix($gateway);
1559 $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($forward_name));
1560 $r = sprintf("%s_%sView_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
1561 $this->logger->log(LOG_DEBUG, "default view class [%s]", $r);
1567 * 遷移名に対応するビューパス名が省略された場合のデフォルトパス名を返す
1569 * デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
1572 * @param string $forward_name forward名
1573 * @return string view classが定義されるスクリプトのパス名
1575 function getDefaultViewPath($forward_name)
1577 $r = preg_replace('/_(.)/e', "'/' . strtoupper('\$1')", ucfirst($forward_name)) . '.' . $this->getExt('php');
1578 $this->logger->log(LOG_DEBUG, "default view path [%s]", $r);
1584 * 遷移名に対応するテンプレートパス名が省略された場合のデフォルトパス名を返す
1586 * デフォルトでは"foo_bar"というforward名が"foo/bar" + テンプレート拡張子となる
1590 * @param string $forward_name forward名
1591 * @return string forwardパス名
1593 function getDefaultForwardPath($forward_name)
1595 return str_replace('_', '/', $forward_name) . '.' . $this->ext['tpl'];
1599 * テンプレートパス名から遷移名を取得する
1601 * getDefaultForwardPath()をオーバーライドした場合、こちらも合わせてオーバーライド
1605 * @param string $forward_path テンプレートパス名
1606 * @return string 遷移名
1608 function forwardPathToName($forward_path)
1610 $forward_path = preg_replace('/^\/+/', '', $forward_path);
1611 $forward_path = preg_replace(sprintf('/\.%s$/', $this->getExt('tpl')), '', $forward_path);
1613 return str_replace('/', '_', $forward_path);
1617 * 遷移名からテンプレートファイルのパス名を取得する
1620 * @param string $forward_name forward名
1621 * @return string テンプレートファイルのパス名
1623 function _getForwardPath($forward_name)
1625 $forward_obj = null;
1627 if (isset($this->forward[$forward_name]) == false) {
1629 $this->forward[$forward_name] = array();
1631 $forward_obj =& $this->forward[$forward_name];
1632 if (isset($forward_obj['forward_path']) == false) {
1634 $forward_obj['forward_path'] = $this->getDefaultForwardPath($forward_name);
1637 return $forward_obj['forward_path'];
1641 * レンダラを取得する(getTemplateEngine()はそのうち廃止されgetRenderer()に統合される予定)
1644 * @return object Ethna_Renderer レンダラオブジェクト
1646 function &getRenderer()
1648 $_ret_object =& $this->getTemplateEngine();
1649 return $_ret_object;
1656 * @return object Ethna_Renderer レンダラオブジェクト
1659 function &getTemplateEngine()
1661 if (is_object($this->renderer)) {
1662 return $this->renderer;
1665 $this->renderer =& $this->class_factory->getObject('renderer');
1668 if (strtolower(get_class($this->renderer)) == "ethna_renderer_smarty") {
1669 // user defined modifiers
1670 foreach ($this->smarty_modifier_plugin as $modifier) {
1671 $name = str_replace('smarty_modifier_', '', $modifier);
1672 $this->renderer->setPlugin($name,'modifier', $modifier);
1675 // user defined functions
1676 foreach ($this->smarty_function_plugin as $function) {
1677 if (!is_array($function)) {
1678 $name = str_replace('smarty_function_', '', $function);
1679 $this->renderer->setPlugin($name, 'function', $function);
1681 $this->renderer->setPlugin($function[1], 'function', $function);
1685 // user defined blocks
1686 foreach ($this->smarty_block_plugin as $block) {
1687 if (!is_array($block)) {
1688 $name = str_replace('smarty_block_', '', $block);
1689 $this->renderer->setPlugin($name,'block', $block);
1691 $this->renderer->setPlugin($block[1],'block', $block);
1695 // user defined prefilters
1696 foreach ($this->smarty_prefilter_plugin as $prefilter) {
1697 if (!is_array($prefilter)) {
1698 $name = str_replace('smarty_prefilter_', '', $prefilter);
1699 $this->renderer->setPlugin($name,'prefilter', $prefilter);
1701 $this->renderer->setPlugin($prefilter[1],'prefilter', $prefilter);
1705 // user defined postfilters
1706 foreach ($this->smarty_postfilter_plugin as $postfilter) {
1707 if (!is_array($postfilter)) {
1708 $name = str_replace('smarty_postfilter_', '', $postfilter);
1709 $this->renderer->setPlugin($name,'postfilter', $postfilter);
1711 $this->renderer->setPlugin($postfilter[1],'postfilter', $postfilter);
1715 // user defined outputfilters
1716 foreach ($this->smarty_outputfilter_plugin as $outputfilter) {
1717 if (!is_array($outputfilter)) {
1718 $name = str_replace('smarty_outputfilter_', '', $outputfilter);
1719 $this->renderer->setPlugin($name,'outputfilter', $outputfilter);
1721 $this->renderer->setPlugin($outputfilter[1],'outputfilter', $outputfilter);
1726 //テンプレートエンジンのデフォルトの設定
1727 $this->_setDefaultTemplateEngine($this->renderer);
1730 return $this->renderer;
1734 * テンプレートエンジンのデフォルト状態を設定する
1737 * @param object Ethna_Renderer レンダラオブジェクト
1740 function _setDefaultTemplateEngine(&$renderer)
1747 * 将来への拡張のためのみに存在しています。現在は特にオーバーライドの必要はありません。
1750 * @param string $language 言語定義(LANG_JA, LANG_EN...)
1751 * @param string $system_encoding システムエンコーディング名
1752 * @param string $client_encoding クライアントエンコーディング
1754 function _setLanguage($language, $system_encoding = null, $client_encoding = null)
1756 $this->language = $language;
1757 $this->system_encoding = $system_encoding;
1758 $this->client_encoding = $client_encoding;
1760 $i18n =& $this->getI18N();
1761 $i18n->setLanguage($language, $system_encoding, $client_encoding);
1765 * デフォルト状態での使用言語を取得する
1768 * @return array 使用言語,システムエンコーディング名,クライアントエンコーディング名
1770 function _getDefaultLanguage()
1772 return array(LANG_JA, null, null);
1776 * デフォルト状態でのゲートウェイを取得する
1779 * @return int ゲートウェイ定義(GATEWAY_WWW, GATEWAY_CLI...)
1781 function _getDefaultGateway($gateway)
1783 if (is_null($GLOBALS['_Ethna_gateway']) == false) {
1784 return $GLOBALS['_Ethna_gateway'];
1790 * ゲートウェイに対応したクラス名のプレフィクスを取得する
1793 * @param string $gateway ゲートウェイ
1794 * @return string ゲートウェイクラスプレフィクス
1796 function _getGatewayPrefix($gateway = null)
1798 $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
1806 case GATEWAY_XMLRPC:
1821 * @param string $name マネージャキー
1822 * @return string マネージャクラス名
1824 function getManagerClassName($name)
1826 return sprintf('%s_%sManager', $this->getAppId(), ucfirst($name));
1830 * アプリケーションオブジェクトクラス名を取得する
1833 * @param string $name アプリケーションオブジェクトキー
1834 * @return string マネージャクラス名
1836 function getObjectClassName($name)
1838 $name = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name));
1839 return sprintf('%s_%s', $this->getAppId(), $name);
1843 * アクションスクリプトをインクルードする
1845 * ただし、インクルードしたファイルにクラスが正しく定義されているかどうかは保証しない
1848 * @param array $action_obj アクション定義
1849 * @param string $action_name アクション名
1851 function _includeActionScript($action_obj, $action_name)
1853 $class_path = $form_path = null;
1855 $action_dir = $this->getActiondir();
1858 if (isset($action_obj['class_path'])) {
1860 $tmp_path = $action_obj['class_path'];
1861 if (Ethna_Util::isAbsolute($tmp_path) == false) {
1862 $tmp_path = $action_dir . $tmp_path;
1865 if (file_exists($tmp_path) == false) {
1866 $this->logger->log(LOG_WARNING, 'class_path file not found [%s] -> try default', $tmp_path);
1868 include_once $tmp_path;
1869 $class_path = $tmp_path;
1874 if (is_null($class_path)) {
1875 $class_path = $this->getDefaultActionPath($action_name);
1876 if (file_exists($action_dir . $class_path)) {
1877 include_once $action_dir . $class_path;
1879 $this->logger->log(LOG_DEBUG, 'default action file not found [%s] -> try all files', $class_path);
1885 if (is_null($class_path)) {
1886 $this->_includeDirectory($this->getActiondir());
1891 if (isset($action_obj['form_path'])) {
1893 $tmp_path = $action_obj['form_path'];
1894 if (Ethna_Util::isAbsolute($tmp_path) == false) {
1895 $tmp_path = $action_dir . $tmp_path;
1898 if ($tmp_path == $class_path) {
1901 if (file_exists($tmp_path) == false) {
1902 $this->logger->log(LOG_WARNING, 'form_path file not found [%s] -> try default', $tmp_path);
1904 include_once $tmp_path;
1905 $form_path = $tmp_path;
1910 if (is_null($form_path)) {
1911 $form_path = $this->getDefaultFormPath($action_name);
1912 if ($form_path == $class_path) {
1915 if (file_exists($action_dir . $form_path)) {
1916 include_once $action_dir . $form_path;
1918 $this->logger->log(LOG_DEBUG, 'default form file not found [%s] -> maybe falling back to default form class', $form_path);
1926 * ただし、インクルードしたファイルにクラスが正しく定義されているかどうかは保証しない
1929 * @param array $forward_obj 遷移定義
1930 * @param string $forward_name 遷移名
1932 function _includeViewScript($forward_obj, $forward_name)
1934 $view_dir = $this->getViewdir();
1937 if (isset($forward_obj['view_path'])) {
1939 $tmp_path = $forward_obj['view_path'];
1940 if (Ethna_Util::isAbsolute($tmp_path) == false) {
1941 $tmp_path = $view_dir . $tmp_path;
1944 if (file_exists($tmp_path) == false) {
1945 $this->logger->log(LOG_WARNING, 'view_path file not found [%s] -> try default', $tmp_path);
1947 include_once $tmp_path;
1953 $view_path = $this->getDefaultViewPath($forward_name);
1954 if (file_exists($view_dir . $view_path)) {
1955 include_once $view_dir . $view_path;
1958 $this->logger->log(LOG_DEBUG, 'default view file not found [%s]', $view_path);
1964 * ディレクトリ以下の全てのスクリプトをインクルードする
1968 function _includeDirectory($dir)
1970 $ext = "." . $this->ext['php'];
1971 $ext_len = strlen($ext);
1973 if (is_dir($dir) == false) {
1977 $dh = opendir($dir);
1979 while (($file = readdir($dh)) !== false) {
1980 if ($file != '.' && $file != '..' && is_dir("$dir/$file")) {
1981 $this->_includeDirectory("$dir/$file");
1983 if (substr($file, -$ext_len, $ext_len) != $ext) {
1986 include_once $dir . '/' . $file;
1993 * 設定ファイルのDSN定義から使用するデータを再構築する(スレーブアクセス分岐等)
1995 * DSNの定義方法(デフォルト:設定ファイル)を変えたい場合はここをオーバーライドする
1998 * @return array DSN定義(array('DBキー1' => 'dsn1', 'DBキー2' => 'dsn2', ...))
2000 function _prepareDSN()
2004 foreach ($this->db as $key => $value) {
2005 $config_key = "dsn";
2007 $config_key .= "_$key";
2009 $dsn = $this->config->get($config_key);
2010 if (is_array($dsn)) {
2011 // 種別1つにつき複数DSNが定義されている場合はアクセス分岐
2012 $dsn = $this->_selectDSN($key, $dsn);
2022 * スレーブサーバへの振分け処理(デフォルト:ランダム)を変更したい場合はこのメソッドをオーバーライドする
2025 * @param string $type DB種別
2026 * @param array $dsn_list DSN一覧
2027 * @return string 選択されたDSN
2029 function _selectDSN($type, $dsn_list)
2031 if (is_array($dsn_list) == false) {
2036 list($usec, $sec) = explode(' ', microtime());
2037 mt_srand($sec + ((float) $usec * 100000));
2038 $n = mt_rand(0, count($dsn_list)-1);
2040 return $dsn_list[$n];
2046 * 不要な場合は空のメソッドとしてオーバーライドしてもよい
2050 function _activateEthnaManager()
2052 if ($this->config->get('debug') == false) {
2056 require_once ETHNA_BASE . '/class/Ethna_InfoManager.php';
2058 // see if we have simpletest
2059 if (file_exists_ex('simpletest/unit_tester.php', true)) {
2060 require_once ETHNA_BASE . '/class/Ethna_UnitTestManager.php';
2064 $this->action['__ethna_info__'] = array(
2065 'form_name' => 'Ethna_Form_Info',
2066 'form_path' => sprintf('%s/class/Action/Ethna_Action_Info.php', ETHNA_BASE),
2067 'class_name' => 'Ethna_Action_Info',
2068 'class_path' => sprintf('%s/class/Action/Ethna_Action_Info.php', ETHNA_BASE),
2072 $this->forward['__ethna_info__'] = array(
2073 'forward_path' => sprintf('%s/tpl/info.tpl', ETHNA_BASE),
2074 'view_name' => 'Ethna_View_Info',
2075 'view_path' => sprintf('%s/class/View/Ethna_View_Info.php', ETHNA_BASE),
2080 $this->action['__ethna_unittest__'] = array(
2081 'form_name' => 'Ethna_Form_UnitTest',
2082 'form_path' => sprintf('%s/class/Action/Ethna_Action_UnitTest.php', ETHNA_BASE),
2083 'class_name' => 'Ethna_Action_UnitTest',
2084 'class_path' => sprintf('%s/class/Action/Ethna_Action_UnitTest.php', ETHNA_BASE),
2088 $this->forward['__ethna_unittest__'] = array(
2089 'forward_path' => sprintf('%s/tpl/unittest.tpl', ETHNA_BASE),
2090 'view_name' => 'Ethna_View_UnitTest',
2091 'view_path' => sprintf('%s/class/View/Ethna_View_UnitTest.php', ETHNA_BASE),
2097 * Ethnaマネージャが実行可能かをチェックする
2099 * Ethnaマネージャを実行するよう指示されているにも関わらず、
2100 * debug が trueでない場合は実行を停止する。
2104 function _ethnaManagerEnabledCheck($action_name)
2106 if ($this->config->get('debug') == false
2107 && ($action_name == '__ethna_info__' || $action_name == '__ethna_unittest__')) {
2108 $this->ethnaManagerCheckErrorMsg($action_name);
2114 * Ethnaマネージャが実行不能な場合のエラーメッセージを
2115 * 表示する。運用上の都合でこのメッセージを出力したくない
2116 * 場合は、このメソッドをオーバーライドせよ
2120 function ethnaManagerCheckErrorMsg($action_name)
2122 $appid = strtolower($this->getAppId());
2123 $run_action = ($action_name == '__ethna_info__')
2124 ? ' show Application Info List '
2125 : ' run Unit Test ';
2126 echo "Ethna cannot {$run_action} under your application setting.<br>";
2127 echo "HINT: You must set {$appid}/etc/{$appid}-ini.php debug setting 'true'.<br>";
2129 echo "In {$appid}-ini.php, please set as follows :<br><br>";
2130 echo "\$config = array ( 'debug' => true, );";
2137 * @return bool CLI実行中フラグ
2142 return $this->gateway == GATEWAY_CLI ? true : false;
2149 * @param bool CLI実行中フラグ
2152 function setCLI($cli)
2154 $this->gateway = $cli ? GATEWAY_CLI : $this->_getDefaultGateway();
2160 * XMLRPCゲートウェイのスタブクラス
2164 function _Ethna_XmlrpcGateway($method_stub, $param)
2166 $ctl =& Ethna_Controller::getInstance();
2167 $method = $ctl->getXmlrpcMethodName();
2168 $r = $ctl->trigger_XMLRPC($method, $param);
2169 if (Ethna::isError($r)) {
2171 'faultCode' => $r->getCode(),
2172 'faultString' => $r->getMessage(),