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 フィルタ設定 */
100 /** @var string 使用ロケール設定 */
103 /** @var string システム側エンコーディング */
104 var $system_encoding;
106 /** @var string クライアント側エンコーディング */
107 /** ブラウザからのエンコーディングを指す */
108 var $client_encoding;
110 /** @var string 現在実行中のアクション名 */
113 /** @var string 現在実行中のXMLRPCメソッド名 */
114 var $xmlrpc_method_name;
116 /** @var array forward定義 */
117 var $forward = array();
119 /** @var array デフォルトのforward定義 */
120 var $forward_default = array(
121 '404' => array( 'view_name' => 'Ethna_View_404',),
122 '500' => array( 'view_name' => 'Ethna_View_500',),
123 'json' => array( 'view_name' => 'Ethna_View_Json',),
124 'redirect' => array( 'view_name' => 'Ethna_View_Redirect',),
127 /** @var array action定義 */
128 var $action = array();
130 /** @var array action(CLI)定義 */
131 var $action_cli = array();
133 /** @var array action(XMLRPC)定義 */
134 var $action_xmlrpc = array();
136 /** @var array アプリケーションマネージャ定義 */
137 var $manager = array();
139 /** @var object レンダラー */
140 var $renderer = null;
142 /** @var array フィルターチェイン(Ethna_Filterオブジェクトの配列) */
143 var $filter_chain = array();
145 /** @var object Ethna_ClassFactory クラスファクトリオブジェクト */
146 var $class_factory = null;
148 /** @var object Ethna_ActionForm フォームオブジェクト */
149 var $action_form = null;
151 /** @var object Ethna_View ビューオブジェクト */
154 /** @var object Ethna_Config 設定オブジェクト */
157 /** @var object Ethna_Logger ログオブジェクト */
160 /** @var object Ethna_Plugin プラグインオブジェクト */
163 /** @var string リクエストのゲートウェイ(www/cli/rest/xmlrpc/soap...) */
164 var $gateway = GATEWAY_WWW;
170 * Ethna_Controllerクラスのコンストラクタ
174 function Ethna_Controller($gateway = GATEWAY_WWW)
176 $GLOBALS['_Ethna_controller'] =& $this;
177 if ($this->base === "") {
178 // EthnaコマンドなどでBASEが定義されていない場合がある
179 if (defined('BASE')) {
184 $this->gateway = $gateway;
187 foreach ($this->class_default as $key => $val) {
188 if (isset($this->class[$key]) == false) {
189 $this->class[$key] = $val;
194 foreach ($this->directory_default as $key => $val) {
195 if (isset($this->directory[$key]) == false) {
196 $this->directory[$key] = $val;
201 $class_factory = $this->class['class'];
202 $this->class_factory =& new $class_factory($this, $this->class);
205 Ethna::setErrorCallback(array(&$this, 'handleError'));
207 // ディレクトリ名の設定(相対パス->絶対パス)
208 foreach ($this->directory as $key => $value) {
209 if ($key == 'plugins') {
210 // Smartyプラグインディレクトリは配列で指定する
212 foreach (to_array($value) as $elt) {
213 if (Ethna_Util::isAbsolute($elt) == false) {
214 $tmp[] = $this->base . (empty($this->base) ? '' : '/') . $elt;
217 $this->directory[$key] = $tmp;
219 if (Ethna_Util::isAbsolute($value) == false) {
220 $this->directory[$key] = $this->base . (empty($this->base) ? '' : '/') . $value;
227 $this->forward = $this->forward + $this->forward_default;
230 // フレームワークとしての内部エンコーディングはクライアント
231 // エンコーディング(=ブラウザからのエンコーディング)
233 // @see Ethna_Controller#_getDefaultLanguage
234 list($this->locale, $this->system_encoding, $this->client_encoding) = $this->_getDefaultLanguage();
236 mb_internal_encoding($this->client_encoding);
237 mb_regex_encoding($this->client_encoding);
239 $this->config =& $this->getConfig();
240 $this->dsn = $this->_prepareDSN();
241 $this->url = $this->config->get('url');
244 $this->plugin =& $this->getPlugin();
246 //// assert (experimental)
247 //if ($this->config->get('debug') === false) {
248 // ini_set('assert.active', 0);
252 $this->logger =& $this->getLogger();
253 $this->plugin->setLogger($this->logger);
254 $this->logger->begin();
257 $this->_activateEthnaManager();
261 * アプリケーション実行後の後始末を行います。
267 // 必要に応じてオーバライドして下さい。
268 $this->logger->end();
272 * (現在アクティブな)コントローラのインスタンスを返す
275 * @return object Ethna_Controller コントローラのインスタンス
278 function &getInstance()
280 if (isset($GLOBALS['_Ethna_controller'])) {
281 return $GLOBALS['_Ethna_controller'];
292 * @return string アプリケーションID
296 return ucfirst(strtolower($this->appid));
303 * @param string $id アプリケーションID
304 * @return mixed true:OK Ethna_Error:NG
307 function &checkAppId($id)
310 if (strcasecmp($id, 'ethna') === 0
311 || strcasecmp($id, 'app') === 0) {
312 return Ethna::raiseError("Application Id [$id] is reserved\n");
315 // アプリケーションIDはクラス名のprefixともなるため、
317 // @see http://www.php.net/manual/en/language.variables.php
318 if (preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $id) === 0) {
319 $msg = (preg_match('/^[0-9]$/', $id[0]))
320 ? "Application ID must NOT start with Number.\n"
321 : "Only Numeric(0-9) and Alphabetical(A-Z) is allowed for Application Id\n";
322 return Ethna::raiseError($msg);
331 * @param string $action_name アクション名
332 * @return mixed true:OK Ethna_Error:NG
335 function &checkActionName($action_name)
338 if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
339 $action_name) === 0) {
340 return Ethna::raiseError("invalid action name [$action_name]");
349 * @param string $view_name ビュー名
350 * @return mixed true:OK Ethna_Error:NG
353 function &checkViewName($view_name)
356 if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
358 return Ethna::raiseError("invalid view name [$view_name]");
367 * @param string $db_key DBキー
370 function getDSN($db_key = "")
372 if (isset($this->dsn[$db_key]) == false) {
375 return $this->dsn[$db_key];
382 * @param string $db_key DBキー
383 * @return bool true:persistent false:non-persistent(あるいは設定無し)
385 function getDSN_persistent($db_key = "")
387 $key = sprintf("dsn%s_persistent", $db_key == "" ? "" : "_$db_key");
389 $dsn_persistent = $this->config->get($key);
390 if (is_null($dsn_persistent)) {
393 return $dsn_persistent;
400 * @param string $db_key DBキー("", "r", "rw", "default", "blog_r"...)
401 * @return string $db_keyに対応するDB種別定義(設定が無い場合はnull)
403 function getDBType($db_key = null)
405 if (is_null($db_key)) {
410 if (isset($this->db[$db_key]) == false) {
413 return $this->db[$db_key];
420 * @return string アプリケーションベースURL
428 * アプリケーションベースディレクトリを返す
431 * @return string アプリケーションベースディレクトリ
433 function getBasedir()
439 * クライアントタイプ/言語からテンプレートディレクトリ名を決定する
440 * デフォルトでは [appid]/template/ja_JP/ (ja_JPはロケール名)
441 * ロケール名は _getDefaultLanguage で決定される。
444 * @return string テンプレートディレクトリ
445 * @see Ethna_Controller#_getDefaultLanguage
447 function getTemplatedir()
449 $template = $this->getDirectory('template');
452 // _getDerfaultLanguageメソッドでロケールが指定されていた場合は、
453 // テンプレートディレクトリにも自動的にそれを付加する。
454 if (!empty($this->locale)) {
455 $template .= '/' . $this->locale;
465 * @return string アクションディレクトリ
467 function getActiondir($gateway = null)
470 $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
479 $key = 'action_xmlrpc';
483 return (empty($this->directory[$key]) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory[$key] . "/"));
490 * @return string ビューディレクトリ
492 function getViewdir()
494 return (empty($this->directory['view']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['view'] . "/"));
498 * (action,view以外の)テストケースを置くディレクトリ名を決定する
501 * @return string テストケースを置くディレクトリ
503 function getTestdir()
505 return (empty($this->directory['test']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['test'] . "/"));
509 * アプリケーションディレクトリ設定を返す
512 * @param string $key ディレクトリタイプ("tmp", "template"...)
513 * @return string $keyに対応したアプリケーションディレクトリ(設定が無い場合はnull)
515 function getDirectory($key)
517 if (isset($this->directory[$key]) == false) {
520 return $this->directory[$key];
527 * @param string $key 拡張子タイプ("php", "tpl"...)
528 * @return string $keyに対応した拡張子(設定が無い場合はnull)
530 function getExt($key)
532 if (isset($this->ext[$key]) == false) {
535 return $this->ext[$key];
539 * クラスファクトリオブジェクトのアクセサ(R)
542 * @return object Ethna_ClassFactory クラスファクトリオブジェクト
544 function &getClassFactory()
546 return $this->class_factory;
550 * アクションエラーオブジェクトのアクセサ
553 * @return object Ethna_ActionError アクションエラーオブジェクト
555 function &getActionError()
557 return $this->class_factory->getObject('error');
561 * アクションフォームオブジェクトのアクセサ
564 * @return object Ethna_ActionForm アクションフォームオブジェクト
566 function &getActionForm()
568 // 明示的にクラスファクトリを利用していない
569 return $this->action_form;
576 * @return object Ethna_View ビューオブジェクト
580 // 明示的にクラスファクトリを利用していない
588 * @return object Ethna_Backend backendオブジェクト
590 function &getBackend()
592 return $this->class_factory->getObject('backend');
599 * @return object Ethna_Config 設定オブジェクト
601 function &getConfig()
603 return $this->class_factory->getObject('config');
610 * @return object Ethna_I18N i18nオブジェクト
614 return $this->class_factory->getObject('i18n');
621 * @return object Ethna_Logger ログオブジェクト
623 function &getLogger()
625 return $this->class_factory->getObject('logger');
632 * @return object Ethna_Session セッションオブジェクト
634 function &getSession()
636 return $this->class_factory->getObject('session');
643 * @return object Ethna_AppSQL SQLオブジェクト
647 return $this->class_factory->getObject('sql');
654 * @return object Ethna_Plugin プラグインオブジェクト
656 function &getPlugin()
658 return $this->class_factory->getObject('plugin');
665 * @return object Ethna_UrlHandler URLハンドラオブジェクト
667 function &getUrlHandler()
669 return $this->class_factory->getObject('url_handler');
676 * @return array マネージャ一覧
679 function getManagerList()
681 return $this->manager;
688 * @return string 実行中のアクション名
690 function getCurrentActionName()
692 return $this->action_name;
699 * @return string 実行中のXMLRPCメソッド名
701 function getXmlrpcMethodName()
703 return $this->xmlrpc_method_name;
710 * @return array ロケール名(e.x ja_JP, en_US 等),
712 * クライアントエンコーディング名 の配列
713 * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
714 * @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html
716 function getLanguage()
718 return array($this->locale, $this->system_encoding, $this->client_encoding);
725 * @return string ロケール名(e.x ja_JP, en_US 等),
726 * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
730 return $this->locale;
737 * @param $locale ロケール名(e.x ja_JP, en_US 等),
738 * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
740 function setLocale($locale)
742 $this->locale = $locale;
743 $i18n =& $this->getI18N();
744 $i18n->setLanguage($this->locale, $this->system_encoding, $this->client_encoding);
748 * クライアントエンコーディング名へのアクセサ(R)
751 * @return string $client_encoding クライアントエンコーディング名
753 function getClientEncoding()
755 return $this->client_encoding;
759 * クライアントエンコーディング名へのアクセサ(W)
762 * @param string $client_encoding クライアントエンコーディング名
764 function setClientEncoding($client_encoding)
766 $this->client_encoding = $client_encoding;
767 $i18n =& $this->getI18N();
768 $i18n->setLanguage($this->locale, $this->system_encoding, $this->client_encoding);
776 function getGateway()
778 return $this->gateway;
786 function setGateway($gateway)
788 $this->gateway = $gateway;
795 * @param string $class_name アプリケーションコントローラのクラス名
796 * @param mixed $action_name 指定のアクション名(省略可)
797 * @param mixed $fallback_action_name アクションが決定できなかった場合に実行されるアクション名(省略可)
800 function main($class_name, $action_name = "", $fallback_action_name = "")
802 $c =& new $class_name;
803 $c->trigger($action_name, $fallback_action_name);
808 * CLIアプリケーションのエントリポイント
811 * @param string $class_name アプリケーションコントローラのクラス名
812 * @param string $action_name 実行するアクション名
813 * @param bool $enable_filter フィルタチェインを有効にするかどうか
816 function main_CLI($class_name, $action_name, $enable_filter = true)
818 $c =& new $class_name(GATEWAY_CLI);
819 $c->action_cli[$action_name] = array();
820 $c->trigger($action_name, "", $enable_filter);
825 * XMLRPCアプリケーションのエントリポイント
830 function main_XMLRPC($class_name)
832 if (extension_loaded('xmlrpc') == false) {
833 die("xmlrpc extension is required to enable this gateway");
836 $c =& new $class_name(GATEWAY_XMLRPC);
837 $c->trigger("", "", false);
842 * SOAPアプリケーションのエントリポイント
845 * @param string $class_name アプリケーションコントローラのクラス名
846 * @param mixed $action_name 指定のアクション名(省略可)
847 * @param mixed $fallback_action_name アクションが決定できなかった場合に実行されるアクション名(省略可)
850 function main_SOAP($class_name, $action_name = "", $fallback_action_name = "")
852 $c =& new $class_name(GATEWAY_SOAP);
853 $c->trigger($action_name, $fallback_action_name);
861 * @param mixed $default_action_name 指定のアクション名
862 * @param mixed $fallback_action_name アクション名が決定できなかった場合に実行されるアクション名
863 * @param bool $enable_filter フィルタチェインを有効にするかどうか
864 * @return mixed 0:正常終了 Ethna_Error:エラー
866 function trigger($default_action_name = "", $fallback_action_name = "", $enable_filter = true)
869 if ($enable_filter) {
870 $this->_createFilterChain();
874 for ($i = 0; $i < count($this->filter_chain); $i++) {
875 $r = $this->filter_chain[$i]->preFilter();
876 if (Ethna::isError($r)) {
882 switch ($this->getGateway()) {
884 $this->_trigger_WWW($default_action_name, $fallback_action_name);
887 $this->_trigger_CLI($default_action_name);
890 $this->_trigger_XMLRPC();
893 $this->_trigger_SOAP();
898 for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
899 $r = $this->filter_chain[$i]->postFilter();
900 if (Ethna::isError($r)) {
907 * フレームワークの処理を実行する(WWW)
909 * 引数$default_action_nameに配列が指定された場合、その配列で指定された
910 * アクション以外は受け付けない(指定されていないアクションが指定された
911 * 場合、配列の先頭で指定されたアクションが実行される)
914 * @param mixed $default_action_name 指定のアクション名
915 * @param mixed $fallback_action_name アクション名が決定できなかった場合に実行されるアクション名
916 * @return mixed 0:正常終了 Ethna_Error:エラー
918 function _trigger_WWW($default_action_name = "", $fallback_action_name = "")
921 $action_name = $this->_getActionName($default_action_name, $fallback_action_name);
924 $this->_ethnaManagerEnabledCheck($action_name);
927 $action_obj =& $this->_getAction($action_name);
928 if (is_null($action_obj)) {
929 if ($fallback_action_name != "") {
930 $this->logger->log(LOG_DEBUG, 'undefined action [%s] -> try fallback action [%s]', $action_name, $fallback_action_name);
931 $action_obj =& $this->_getAction($fallback_action_name);
933 if (is_null($action_obj)) {
934 return Ethna::raiseError("undefined action [%s]", E_APP_UNDEFINED_ACTION, $action_name);
936 $action_name = $fallback_action_name;
941 for ($i = 0; $i < count($this->filter_chain); $i++) {
942 $r = $this->filter_chain[$i]->preActionFilter($action_name);
944 $this->logger->log(LOG_DEBUG, 'action [%s] -> [%s] by %s', $action_name, $r, get_class($this->filter_chain[$i]));
948 $this->action_name = $action_name;
951 $backend =& $this->getBackend();
952 $session =& $this->getSession();
956 $this->_setLanguage($this->locale, $this->system_encoding, $this->client_encoding);
960 $form_name = $this->getActionFormName($action_name);
961 $this->action_form =& new $form_name($this);
962 $this->action_form->setFormDef_PreHelper();
963 $this->action_form->setFormVars();
964 $backend->setActionForm($this->action_form);
967 $forward_name = $backend->perform($action_name);
970 for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
971 $r = $this->filter_chain[$i]->postActionFilter($action_name, $forward_name);
973 $this->logger->log(LOG_DEBUG, 'forward [%s] -> [%s] by %s', $forward_name, $r, get_class($this->filter_chain[$i]));
978 // コントローラで遷移先を決定する(オプション)
979 $forward_name_params = $this->_sortForward($action_name, $forward_name);
982 $preforward_params = array();
983 if (is_array($forward_name_params)) {
984 $forward_name = array_shift($forward_name_params);
985 $preforward_params = $forward_name_params;
988 $forward_name = $forward_name_params;
991 if ($forward_name != null) {
992 $view_class_name = $this->getViewClassName($forward_name);
993 $this->view =& new $view_class_name($backend, $forward_name, $this->_getForwardPath($forward_name));
994 call_user_func_array(array($this->view, 'preforward'), $preforward_params);
995 $this->view->forward();
1002 * フレームワークの処理を実行する(CLI)
1005 * @param mixed $default_action_name 指定のアクション名
1006 * @return mixed 0:正常終了 Ethna_Error:エラー
1008 function _trigger_CLI($default_action_name = "")
1010 return $this->_trigger_WWW($default_action_name);
1014 * フレームワークの処理を実行する(XMLRPC)
1017 * @param mixed $action_name 指定のアクション名
1018 * @return mixed 0:正常終了 Ethna_Error:エラー
1020 function _trigger_XMLRPC($action_name = "")
1022 // prepare xmlrpc server
1023 $xmlrpc_gateway_method_name = "_Ethna_XmlrpcGateway";
1024 $xmlrpc_server = xmlrpc_server_create();
1027 $param = xmlrpc_decode_request(file_get_contents('php://input'), $method);
1028 $this->xmlrpc_method_name = $method;
1030 $request = xmlrpc_encode_request(
1031 $xmlrpc_gateway_method_name,
1034 'output_type' => 'xml',
1035 'verbosity' => 'pretty',
1036 'escaping' => array('markup'),
1037 'version' => 'xmlrpc',
1038 'encoding' => 'utf-8'
1042 xmlrpc_server_register_method(
1044 $xmlrpc_gateway_method_name,
1045 $xmlrpc_gateway_method_name
1049 $r = xmlrpc_server_call_method(
1054 'output_type' => 'xml',
1055 'verbosity' => 'pretty',
1056 'escaping' => array('markup'),
1057 'version' => 'xmlrpc',
1058 'encoding' => 'utf-8'
1062 header('Content-Length: ' . strlen($r));
1063 header('Content-Type: text/xml; charset=UTF-8');
1068 * _trigger_XMLRPCのコールバックメソッド
1072 function trigger_XMLRPC($method, $param)
1075 $action_obj =& $this->_getAction($method);
1076 if (is_null($action_obj)) {
1077 return Ethna::raiseError("undefined xmlrpc method [%s]", E_APP_UNDEFINED_ACTION, $method);
1081 $backend =& $this->getBackend();
1083 $form_name = $this->getActionFormName($method);
1084 $this->action_form =& new $form_name($this);
1085 $def = $this->action_form->getDef();
1087 foreach ($def as $key => $value) {
1088 if (isset($param[$n]) == false) {
1089 $this->action_form->set($key, null);
1091 $this->action_form->set($key, $param[$n]);
1097 $backend->setActionForm($this->action_form);
1099 $session =& $this->getSession();
1100 $session->restore();
1101 $r = $backend->perform($method);
1107 * SOAPフレームワークの処理を実行する
1111 function _trigger_SOAP()
1114 $gg =& new Ethna_SOAP_GatewayGenerator();
1115 $script = $gg->generate();
1119 $server =& new SoapServer(null, array('uri' => $this->config->get('url')));
1120 $server->setClass($gg->getClassName());
1127 * エラー発生時の追加処理を行いたい場合はこのメソッドをオーバーライドする
1128 * (アラートメール送信等−デフォルトではログ出力時にアラートメール
1129 * が送信されるが、エラー発生時に別にアラートメールをここで送信
1133 * @param object Ethna_Error エラーオブジェクト
1135 function handleError(&$error)
1138 list ($log_level, $dummy) = $this->logger->errorLevelToLogLevel($error->getLevel());
1139 $message = $error->getMessage();
1140 $this->logger->log($log_level, sprintf("%s [ERROR CODE(%d)]", $message, $error->getCode()));
1147 * @param int $code エラーコード
1148 * @return string エラーメッセージ
1150 function getErrorMessage($code)
1152 $message_list =& $GLOBALS['_Ethna_error_message_list'];
1153 for ($i = count($message_list)-1; $i >= 0; $i--) {
1154 if (array_key_exists($code, $message_list[$i])) {
1155 return $message_list[$i][$code];
1165 * @param mixed $default_action_name 指定のアクション名
1166 * @return string 実行するアクション名
1168 function _getActionName($default_action_name, $fallback_action_name)
1170 // フォームから要求されたアクション名を取得する
1171 $form_action_name = $this->_getActionName_Form();
1172 $form_action_name = preg_replace('/[^a-z0-9\-_]+/i', '', $form_action_name);
1173 $this->logger->log(LOG_DEBUG, 'form_action_name[%s]', $form_action_name);
1175 // Ethnaマネージャへのフォームからのリクエストは拒否
1176 if ($form_action_name == "__ethna_info__" ||
1177 $form_action_name == "__ethna_unittest__") {
1178 $form_action_name = "";
1181 // フォームからの指定が無い場合はエントリポイントに指定されたデフォルト値を利用する
1182 if ($form_action_name == "" && count($default_action_name) > 0) {
1183 $tmp = is_array($default_action_name) ? $default_action_name[0] : $default_action_name;
1184 if ($tmp{strlen($tmp)-1} == '*') {
1185 $tmp = substr($tmp, 0, -1);
1187 $this->logger->log(LOG_DEBUG, '-> default_action_name[%s]', $tmp);
1188 $action_name = $tmp;
1190 $action_name = $form_action_name;
1193 // エントリポイントに配列が指定されている場合は指定以外のアクション名は拒否する
1194 if (is_array($default_action_name)) {
1195 if ($this->_isAcceptableActionName($action_name, $default_action_name) == false) {
1196 // 指定以外のアクション名で合った場合は$fallback_action_name(or デフォルト)
1197 $tmp = $fallback_action_name != "" ? $fallback_action_name : $default_action_name[0];
1198 if ($tmp{strlen($tmp)-1} == '*') {
1199 $tmp = substr($tmp, 0, -1);
1201 $this->logger->log(LOG_DEBUG, '-> fallback_action_name[%s]', $tmp);
1202 $action_name = $tmp;
1206 $this->logger->log(LOG_DEBUG, '<<< action_name[%s] >>>', $action_name);
1208 return $action_name;
1212 * フォームにより要求されたアクション名を返す
1214 * アプリケーションの性質に応じてこのメソッドをオーバーライドして下さい。
1215 * デフォルトでは"action_"で始まるフォーム値の"action_"の部分を除いたもの
1216 * ("action_sample"なら"sample")がアクション名として扱われます
1219 * @return string フォームにより要求されたアクション名
1221 function _getActionName_Form()
1223 if (isset($_SERVER['REQUEST_METHOD']) == false) {
1227 $url_handler =& $this->getUrlHandler();
1228 if ($_SERVER['REQUEST_METHOD'] == "GET") {
1230 } else if ($_SERVER['REQUEST_METHOD'] == "POST") {
1234 if (empty($_SERVER['URL_HANDLER']) == false) {
1235 $tmp_vars['__url_handler__'] = $_SERVER['URL_HANDLER'];
1236 $tmp_vars['__url_info__'] = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : null;
1237 $tmp_vars = $url_handler->requestToAction($tmp_vars);
1239 if ($_SERVER['REQUEST_METHOD'] == "GET") {
1240 $_GET = array_merge($_GET, $tmp_vars);
1241 } else if ($_SERVER['REQUEST_METHOD'] == "POST") {
1242 $_POST = array_merge($_POST, $tmp_vars);
1244 $_REQUEST = array_merge($_REQUEST, $tmp_vars);
1247 if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0) {
1248 $http_vars =& $_POST;
1250 $http_vars =& $_GET;
1253 // フォーム値からリクエストされたアクション名を取得する
1254 $action_name = $sub_action_name = null;
1255 foreach ($http_vars as $name => $value) {
1256 if ($value == "" || strncmp($name, 'action_', 7) != 0) {
1260 $tmp = substr($name, 7);
1263 if (preg_match('/_x$/', $name) || preg_match('/_y$/', $name)) {
1264 $tmp = substr($tmp, 0, strlen($tmp)-2);
1267 // value="dummy"となっているものは優先度を下げる
1268 if ($value == "dummy") {
1269 $sub_action_name = $tmp;
1271 $action_name = $tmp;
1274 if ($action_name == null) {
1275 $action_name = $sub_action_name;
1278 return $action_name;
1282 * アクション名を指定するクエリ/HTMLを生成する
1285 * @param string $action action to request
1286 * @param string $type hidden, url...
1287 * @todo consider gateway
1289 function getActionRequest($action, $type = "hidden")
1292 if ($type == "hidden") {
1293 $s = sprintf('<input type="hidden" name="action_%s" value="true" />', htmlspecialchars($action, ENT_QUOTES));
1294 } else if ($type == "url") {
1295 $s = sprintf('action_%s=true', urlencode($action));
1301 * フォームにより要求されたアクション名に対応する定義を返す
1304 * @param string $action_name アクション名
1305 * @return array アクション定義
1307 function &_getAction($action_name, $gateway = null)
1310 $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
1313 $action =& $this->action;
1316 $action =& $this->action_cli;
1318 case GATEWAY_XMLRPC:
1319 $action =& $this->action_xmlrpc;
1323 $action_obj = array();
1324 if (isset($action[$action_name])) {
1325 $action_obj = $action[$action_name];
1326 if (isset($action_obj['inspect']) && $action_obj['inspect']) {
1330 $this->logger->log(LOG_DEBUG, "action [%s] is not defined -> try default", $action_name);
1333 // アクションスクリプトのインクルード
1334 $this->_includeActionScript($action_obj, $action_name);
1337 if (isset($action_obj['class_name']) == false) {
1338 $action_obj['class_name'] = $this->getDefaultActionClass($action_name);
1341 if (isset($action_obj['form_name']) == false) {
1342 $action_obj['form_name'] = $this->getDefaultFormClass($action_name);
1343 } else if (class_exists($action_obj['form_name']) == false) {
1344 // 明示指定されたフォームクラスが定義されていない場合は警告
1345 $this->logger->log(LOG_WARNING, 'stated form class is not defined [%s]', $action_obj['form_name']);
1349 if (class_exists($action_obj['class_name']) == false) {
1350 $this->logger->log(LOG_NOTICE, 'action class is not defined [%s]', $action_obj['class_name']);
1351 $_ret_object = null;
1352 return $_ret_object;
1354 if (class_exists($action_obj['form_name']) == false) {
1356 $class_name = $this->class_factory->getObjectName('form');
1357 $this->logger->log(LOG_DEBUG, 'form class is not defined [%s] -> falling back to default [%s]', $action_obj['form_name'], $class_name);
1358 $action_obj['form_name'] = $class_name;
1361 $action_obj['inspect'] = true;
1362 $action[$action_name] = $action_obj;
1363 return $action[$action_name];
1367 * アクション名とアクションクラスからの戻り値に基づいて遷移先を決定する
1370 * @param string $action_name アクション名
1371 * @param string $retval アクションクラスからの戻り値
1372 * @return string 遷移先
1374 function _sortForward($action_name, $retval)
1384 function _createFilterChain()
1386 $this->filter_chain = array();
1387 foreach ($this->filter as $filter) {
1388 $filter_plugin =& $this->plugin->getPlugin('Filter', $filter);
1389 if (Ethna::isError($filter_plugin)) {
1393 $this->filter_chain[] =& $filter_plugin;
1398 * アクション名が実行許可されているものかどうかを返す
1401 * @param string $action_name リクエストされたアクション名
1402 * @param array $default_action_name 許可されているアクション名
1403 * @return bool true:許可 false:不許可
1405 function _isAcceptableActionName($action_name, $default_action_name)
1407 foreach (to_array($default_action_name) as $name) {
1408 if ($action_name == $name) {
1410 } else if ($name{strlen($name)-1} == '*') {
1411 if (strncmp($action_name, substr($name, 0, -1), strlen($name)-1) == 0) {
1420 * 指定されたアクションのフォームクラス名を返す(オブジェクトの生成は行わない)
1423 * @param string $action_name アクション名
1424 * @return string アクションのフォームクラス名
1426 function getActionFormName($action_name)
1428 $action_obj =& $this->_getAction($action_name);
1429 if (is_null($action_obj)) {
1433 return $action_obj['form_name'];
1437 * アクションに対応するフォームクラス名が省略された場合のデフォルトクラス名を返す
1439 * デフォルトでは[プロジェクトID]_Form_[アクション名]となるので好み応じてオーバライドする
1442 * @param string $action_name アクション名
1443 * @return string アクションフォーム名
1445 function getDefaultFormClass($action_name, $gateway = null)
1447 $gateway_prefix = $this->_getGatewayPrefix($gateway);
1449 $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
1450 $r = sprintf("%s_%sForm_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
1451 $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
1457 * getDefaultFormClass()で取得したクラス名からアクション名を取得する
1459 * getDefaultFormClass()をオーバーライドした場合、こちらも合わせてオーバーライド
1463 * @param string $class_name フォームクラス名
1464 * @return string アクション名
1466 function actionFormToName($class_name)
1468 $prefix = sprintf("%s_Form_", $this->getAppId());
1469 if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
1473 $target = $match[1];
1475 $action_name = substr(preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $target), 1);
1477 return $action_name;
1481 * アクションに対応するフォームパス名が省略された場合のデフォルトパス名を返す
1483 * デフォルトでは_getDefaultActionPath()と同じ結果を返す(1ファイルに
1484 * アクションクラスとフォームクラスが記述される)ので、好みに応じて
1488 * @param string $action_name アクション名
1489 * @return string form classが定義されるスクリプトのパス名
1491 function getDefaultFormPath($action_name)
1493 return $this->getDefaultActionPath($action_name);
1497 * 指定されたアクションのクラス名を返す(オブジェクトの生成は行わない)
1500 * @param string $action_name アクションの名称
1501 * @return string アクションのクラス名
1503 function getActionClassName($action_name)
1505 $action_obj =& $this->_getAction($action_name);
1506 if ($action_obj == null) {
1510 return $action_obj['class_name'];
1514 * アクションに対応するアクションクラス名が省略された場合のデフォルトクラス名を返す
1516 * デフォルトでは[プロジェクトID]_Action_[アクション名]となるので好み応じてオーバライドする
1519 * @param string $action_name アクション名
1520 * @return string アクションクラス名
1522 function getDefaultActionClass($action_name, $gateway = null)
1524 $gateway_prefix = $this->_getGatewayPrefix($gateway);
1526 $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
1527 $r = sprintf("%s_%sAction_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
1528 $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
1534 * getDefaultActionClass()で取得したクラス名からアクション名を取得する
1536 * getDefaultActionClass()をオーバーライドした場合、こちらも合わせてオーバーライド
1540 * @param string $class_name アクションクラス名
1541 * @return string アクション名
1543 function actionClassToName($class_name)
1545 $prefix = sprintf("%s_Action_", $this->getAppId());
1546 if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
1550 $target = $match[1];
1552 $action_name = substr(preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $target), 1);
1554 return $action_name;
1558 * アクションに対応するアクションパス名が省略された場合のデフォルトパス名を返す
1560 * デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
1563 * @param string $action_name アクション名
1564 * @return string アクションクラスが定義されるスクリプトのパス名
1566 function getDefaultActionPath($action_name)
1568 $r = preg_replace('/_(.)/e', "'/' . strtoupper('\$1')", ucfirst($action_name)) . '.' . $this->getExt('php');
1569 $this->logger->log(LOG_DEBUG, "default action path [%s]", $r);
1575 * 指定された遷移名に対応するビュークラス名を返す(オブジェクトの生成は行わない)
1578 * @param string $forward_name 遷移先の名称
1579 * @return string view classのクラス名
1581 function getViewClassName($forward_name)
1583 if ($forward_name == null) {
1587 if (isset($this->forward[$forward_name])) {
1588 $forward_obj = $this->forward[$forward_name];
1590 $forward_obj = array();
1593 if (isset($forward_obj['view_name'])) {
1594 $class_name = $forward_obj['view_name'];
1595 if (class_exists($class_name)) {
1603 $this->_includeViewScript($forward_obj, $forward_name);
1605 if (is_null($class_name) == false && class_exists($class_name)) {
1607 } else if (is_null($class_name) == false) {
1608 $this->logger->log(LOG_WARNING, 'stated view class is not defined [%s] -> try default', $class_name);
1611 $class_name = $this->getDefaultViewClass($forward_name);
1612 if (class_exists($class_name)) {
1615 $class_name = $this->class_factory->getObjectName('view');
1616 $this->logger->log(LOG_DEBUG, 'view class is not defined for [%s] -> use default [%s]', $forward_name, $class_name);
1622 * 遷移名に対応するビュークラス名が省略された場合のデフォルトクラス名を返す
1624 * デフォルトでは[プロジェクトID]_View_[遷移名]となるので好み応じてオーバライドする
1627 * @param string $forward_name forward名
1628 * @return string view classクラス名
1630 function getDefaultViewClass($forward_name, $gateway = null)
1632 $gateway_prefix = $this->_getGatewayPrefix($gateway);
1634 $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($forward_name));
1635 $r = sprintf("%s_%sView_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
1636 $this->logger->log(LOG_DEBUG, "default view class [%s]", $r);
1642 * 遷移名に対応するビューパス名が省略された場合のデフォルトパス名を返す
1644 * デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
1647 * @param string $forward_name forward名
1648 * @return string view classが定義されるスクリプトのパス名
1650 function getDefaultViewPath($forward_name)
1652 $r = preg_replace('/_(.)/e', "'/' . strtoupper('\$1')", ucfirst($forward_name)) . '.' . $this->getExt('php');
1653 $this->logger->log(LOG_DEBUG, "default view path [%s]", $r);
1659 * 遷移名に対応するテンプレートパス名が省略された場合のデフォルトパス名を返す
1661 * デフォルトでは"foo_bar"というforward名が"foo/bar" + テンプレート拡張子となる
1665 * @param string $forward_name forward名
1666 * @return string forwardパス名
1668 function getDefaultForwardPath($forward_name)
1670 return str_replace('_', '/', $forward_name) . '.' . $this->ext['tpl'];
1674 * テンプレートパス名から遷移名を取得する
1676 * getDefaultForwardPath()をオーバーライドした場合、こちらも合わせてオーバーライド
1680 * @param string $forward_path テンプレートパス名
1681 * @return string 遷移名
1683 function forwardPathToName($forward_path)
1685 $forward_path = preg_replace('/^\/+/', '', $forward_path);
1686 $forward_path = preg_replace(sprintf('/\.%s$/', $this->getExt('tpl')), '', $forward_path);
1688 return str_replace('/', '_', $forward_path);
1692 * 遷移名からテンプレートファイルのパス名を取得する
1695 * @param string $forward_name forward名
1696 * @return string テンプレートファイルのパス名
1698 function _getForwardPath($forward_name)
1700 $forward_obj = null;
1702 if (isset($this->forward[$forward_name]) == false) {
1704 $this->forward[$forward_name] = array();
1706 $forward_obj =& $this->forward[$forward_name];
1707 if (isset($forward_obj['forward_path']) == false) {
1709 $forward_obj['forward_path'] = $this->getDefaultForwardPath($forward_name);
1712 return $forward_obj['forward_path'];
1716 * レンダラを取得する(getTemplateEngine()はそのうち廃止されgetRenderer()に統合される予定)
1719 * @return object Ethna_Renderer レンダラオブジェクト
1721 function &getRenderer()
1723 $_ret_object =& $this->getTemplateEngine();
1724 return $_ret_object;
1731 * @return object Ethna_Renderer レンダラオブジェクト
1734 function &getTemplateEngine()
1736 if (is_object($this->renderer)) {
1737 return $this->renderer;
1740 $this->renderer =& $this->class_factory->getObject('renderer');
1742 //テンプレートエンジンのデフォルトの設定
1743 $this->_setDefaultTemplateEngine($this->renderer);
1746 return $this->renderer;
1750 * テンプレートエンジンのデフォルト状態を設定する
1753 * @param object Ethna_Renderer レンダラオブジェクト
1756 function _setDefaultTemplateEngine(&$renderer)
1762 * 条件によって使用言語、ロケールを切り替えたい場合は、
1766 * @param string $locale ロケール名(ja_JP, en_US等)
1767 * (ll_cc の形式。ll = 言語コード cc = 国コード)
1768 * @param string $system_encoding システムエンコーディング名
1769 * @param string $client_encoding クライアントエンコーディング(テンプレートのエンコーディングと考えれば良い)
1770 * @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html
1771 * @see Ethna_Controller#_getDefaultLanguage
1773 function _setLanguage($locale, $system_encoding = null, $client_encoding = null)
1775 $this->locale = $locale;
1776 $this->system_encoding = $system_encoding;
1777 $this->client_encoding = $client_encoding;
1779 // $this->locale, $this->client_encoding を書き換えた場合は
1780 // 必ず Ethna_I18N クラスの setLanguageメソッドも呼ぶこと!
1781 // さもないとカタログその他が再ロードされない!
1782 $i18n =& $this->getI18N();
1783 $i18n->setLanguage($locale, $system_encoding, $client_encoding);
1787 * デフォルト状態での使用言語を取得する
1788 * 外部に出力されるEthnaのエラーメッセージ等のエンコーディングを
1789 * 切り替えたい場合は、このメソッドをオーバーライドする。
1792 * @return array ロケール名(e.x ja_JP, en_US 等),
1795 * (= テンプレートのエンコーディングと考えてよい) の配列
1796 * (ロケール名は ll_cc の形式。ll = 言語コード cc = 国コード)
1798 * WARNING!! : クライアントエンコーディング名が、フレームワークの内部エンコーデ
1799 * ィングとして設定されます。つまり、クライアントエンコーディングで
1800 * ブラウザからの入力は入ってくるものと想定しています!
1802 function _getDefaultLanguage()
1804 return array('ja_JP', 'UTF-8', 'UTF-8');
1808 * デフォルト状態でのゲートウェイを取得する
1811 * @return int ゲートウェイ定義(GATEWAY_WWW, GATEWAY_CLI...)
1813 function _getDefaultGateway($gateway)
1815 if (is_null($GLOBALS['_Ethna_gateway']) == false) {
1816 return $GLOBALS['_Ethna_gateway'];
1822 * ゲートウェイに対応したクラス名のプレフィクスを取得する
1825 * @param string $gateway ゲートウェイ
1826 * @return string ゲートウェイクラスプレフィクス
1828 function _getGatewayPrefix($gateway = null)
1830 $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
1838 case GATEWAY_XMLRPC:
1853 * @param string $name マネージャキー
1854 * @return string マネージャクラス名
1856 function getManagerClassName($name)
1858 // アプリケーションIDと、渡された名前のはじめを大文字にして、
1860 $manager_id = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name));
1861 return sprintf('%s_%sManager', $this->getAppId(), ucfirst($manager_id));
1865 * アプリケーションオブジェクトクラス名を取得する
1868 * @param string $name アプリケーションオブジェクトキー
1869 * @return string マネージャクラス名
1871 function getObjectClassName($name)
1873 // 引数のはじめの一文字目と、アンダーバー直後の
1874 // 1文字を必ず大文字にする。アンダーバーは削除される。
1875 $name = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name));
1877 // $name に foo_bar を渡し、AppID が Hogeの場合
1878 // [Appid]_FooBar が返される
1879 return sprintf('%s_%s', $this->getAppId(), $name);
1883 * アクションスクリプトをインクルードする
1885 * ただし、インクルードしたファイルにクラスが正しく定義されているかどうかは保証しない
1888 * @param array $action_obj アクション定義
1889 * @param string $action_name アクション名
1891 function _includeActionScript($action_obj, $action_name)
1893 $class_path = $form_path = null;
1895 $action_dir = $this->getActiondir();
1898 if (isset($action_obj['class_path'])) {
1900 $tmp_path = $action_obj['class_path'];
1901 if (Ethna_Util::isAbsolute($tmp_path) == false) {
1902 $tmp_path = $action_dir . $tmp_path;
1905 if (file_exists($tmp_path) == false) {
1906 $this->logger->log(LOG_WARNING, 'class_path file not found [%s] -> try default', $tmp_path);
1908 include_once $tmp_path;
1909 $class_path = $tmp_path;
1914 if (is_null($class_path)) {
1915 $class_path = $this->getDefaultActionPath($action_name);
1916 if (file_exists($action_dir . $class_path)) {
1917 include_once $action_dir . $class_path;
1919 $this->logger->log(LOG_DEBUG, 'default action file not found [%s] -> try all files', $class_path);
1925 if (isset($action_obj['form_path'])) {
1927 $tmp_path = $action_obj['form_path'];
1928 if (Ethna_Util::isAbsolute($tmp_path) == false) {
1929 $tmp_path = $action_dir . $tmp_path;
1932 if ($tmp_path == $class_path) {
1935 if (file_exists($tmp_path) == false) {
1936 $this->logger->log(LOG_WARNING, 'form_path file not found [%s] -> try default', $tmp_path);
1938 include_once $tmp_path;
1939 $form_path = $tmp_path;
1944 if (is_null($form_path)) {
1945 $form_path = $this->getDefaultFormPath($action_name);
1946 if ($form_path == $class_path) {
1949 if (file_exists($action_dir . $form_path)) {
1950 include_once $action_dir . $form_path;
1952 $this->logger->log(LOG_DEBUG, 'default form file not found [%s] -> maybe falling back to default form class', $form_path);
1960 * ただし、インクルードしたファイルにクラスが正しく定義されているかどうかは保証しない
1963 * @param array $forward_obj 遷移定義
1964 * @param string $forward_name 遷移名
1966 function _includeViewScript($forward_obj, $forward_name)
1968 $view_dir = $this->getViewdir();
1971 if (isset($forward_obj['view_path'])) {
1973 $tmp_path = $forward_obj['view_path'];
1974 if (Ethna_Util::isAbsolute($tmp_path) == false) {
1975 $tmp_path = $view_dir . $tmp_path;
1978 if (file_exists($tmp_path) == false) {
1979 $this->logger->log(LOG_WARNING, 'view_path file not found [%s] -> try default', $tmp_path);
1981 include_once $tmp_path;
1987 $view_path = $this->getDefaultViewPath($forward_name);
1988 if (file_exists($view_dir . $view_path)) {
1989 include_once $view_dir . $view_path;
1992 $this->logger->log(LOG_DEBUG, 'default view file not found [%s]', $view_path);
1998 * ディレクトリ以下の全てのスクリプトをインクルードする
2002 function _includeDirectory($dir)
2004 $ext = "." . $this->ext['php'];
2005 $ext_len = strlen($ext);
2007 if (is_dir($dir) == false) {
2011 $dh = opendir($dir);
2013 while (($file = readdir($dh)) !== false) {
2014 if ($file != '.' && $file != '..' && is_dir("$dir/$file")) {
2015 $this->_includeDirectory("$dir/$file");
2017 if (substr($file, -$ext_len, $ext_len) != $ext) {
2020 include_once $dir . '/' . $file;
2027 * 設定ファイルのDSN定義から使用するデータを再構築する(スレーブアクセス分岐等)
2029 * DSNの定義方法(デフォルト:設定ファイル)を変えたい場合はここをオーバーライドする
2032 * @return array DSN定義(array('DBキー1' => 'dsn1', 'DBキー2' => 'dsn2', ...))
2034 function _prepareDSN()
2038 foreach ($this->db as $key => $value) {
2039 $config_key = "dsn";
2041 $config_key .= "_$key";
2043 $dsn = $this->config->get($config_key);
2044 if (is_array($dsn)) {
2045 // 種別1つにつき複数DSNが定義されている場合はアクセス分岐
2046 $dsn = $this->_selectDSN($key, $dsn);
2056 * スレーブサーバへの振分け処理(デフォルト:ランダム)を変更したい場合はこのメソッドをオーバーライドする
2059 * @param string $type DB種別
2060 * @param array $dsn_list DSN一覧
2061 * @return string 選択されたDSN
2063 function _selectDSN($type, $dsn_list)
2065 if (is_array($dsn_list) == false) {
2070 list($usec, $sec) = explode(' ', microtime());
2071 mt_srand($sec + ((float) $usec * 100000));
2072 $n = mt_rand(0, count($dsn_list)-1);
2074 return $dsn_list[$n];
2080 * 不要な場合は空のメソッドとしてオーバーライドしてもよい
2084 function _activateEthnaManager()
2086 if ($this->config->get('debug') == false) {
2090 require_once ETHNA_BASE . '/class/Ethna_InfoManager.php';
2092 // see if we have simpletest
2093 if (file_exists_ex('simpletest/unit_tester.php', true)) {
2094 require_once ETHNA_BASE . '/class/Ethna_UnitTestManager.php';
2098 $this->action['__ethna_info__'] = array(
2099 'form_name' => 'Ethna_Form_Info',
2100 'form_path' => sprintf('%s/class/Action/Ethna_Action_Info.php', ETHNA_BASE),
2101 'class_name' => 'Ethna_Action_Info',
2102 'class_path' => sprintf('%s/class/Action/Ethna_Action_Info.php', ETHNA_BASE),
2106 $this->forward['__ethna_info__'] = array(
2107 'forward_path' => sprintf('%s/tpl/info.tpl', ETHNA_BASE),
2108 'view_name' => 'Ethna_View_Info',
2109 'view_path' => sprintf('%s/class/View/Ethna_View_Info.php', ETHNA_BASE),
2114 $this->action['__ethna_unittest__'] = array(
2115 'form_name' => 'Ethna_Form_UnitTest',
2116 'form_path' => sprintf('%s/class/Action/Ethna_Action_UnitTest.php', ETHNA_BASE),
2117 'class_name' => 'Ethna_Action_UnitTest',
2118 'class_path' => sprintf('%s/class/Action/Ethna_Action_UnitTest.php', ETHNA_BASE),
2122 $this->forward['__ethna_unittest__'] = array(
2123 'forward_path' => sprintf('%s/tpl/unittest.tpl', ETHNA_BASE),
2124 'view_name' => 'Ethna_View_UnitTest',
2125 'view_path' => sprintf('%s/class/View/Ethna_View_UnitTest.php', ETHNA_BASE),
2131 * Ethnaマネージャが実行可能かをチェックする
2133 * Ethnaマネージャを実行するよう指示されているにも関わらず、
2134 * debug が trueでない場合は実行を停止する。
2138 function _ethnaManagerEnabledCheck($action_name)
2140 if ($this->config->get('debug') == false
2141 && ($action_name == '__ethna_info__' || $action_name == '__ethna_unittest__')) {
2142 $this->ethnaManagerCheckErrorMsg($action_name);
2148 * Ethnaマネージャが実行不能な場合のエラーメッセージを
2149 * 表示する。運用上の都合でこのメッセージを出力したくない
2150 * 場合は、このメソッドをオーバーライドせよ
2154 function ethnaManagerCheckErrorMsg($action_name)
2156 $appid = strtolower($this->getAppId());
2157 $run_action = ($action_name == '__ethna_info__')
2158 ? ' show Application Info List '
2159 : ' run Unit Test ';
2160 echo "Ethna cannot {$run_action} under your application setting.<br>";
2161 echo "HINT: You must set {$appid}/etc/{$appid}-ini.php debug setting 'true'.<br>";
2163 echo "In {$appid}-ini.php, please set as follows :<br><br>";
2164 echo "\$config = array ( 'debug' => true, );";
2171 * @return bool CLI実行中フラグ
2176 return $this->gateway == GATEWAY_CLI ? true : false;
2183 * @param bool CLI実行中フラグ
2186 function setCLI($cli)
2188 $this->gateway = $cli ? GATEWAY_CLI : $this->_getDefaultGateway();
2194 * XMLRPCゲートウェイのスタブクラス
2198 function _Ethna_XmlrpcGateway($method_stub, $param)
2200 $ctl =& Ethna_Controller::getInstance();
2201 $method = $ctl->getXmlrpcMethodName();
2202 $r = $ctl->trigger_XMLRPC($method, $param);
2203 if (Ethna::isError($r)) {
2205 'faultCode' => $r->getCode(),
2206 'faultString' => $r->getMessage(),