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 */
29 protected $appid = 'ETHNA';
31 /** @var string アプリケーションベースディレクトリ */
34 /** @protected string アプリケーションベースURL */
37 /** @protected string アプリケーションDSN(Data Source Name) */
40 /** @protected array アプリケーションディレクトリ */
41 protected $directory = array();
43 /** @protected array アプリケーションディレクトリ(デフォルト) */
44 protected $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 /** @protected array DBアクセス定義 */
65 protected $db = array(
69 /** @protected array 拡張子設定 */
70 protected $ext = array(
75 /** @protected array クラス設定 */
76 public $class = array();
78 /** @protected array クラス設定(デフォルト) */
79 public $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 /** @protected array フィルタ設定 */
97 protected $filter = array(
100 /** @protected string 使用ロケール設定 */
103 /** @protected string システム側エンコーディング */
104 protected $system_encoding;
106 /** @protected string クライアント側エンコーディング */
107 /** ブラウザからのエンコーディングを指す */
108 protected $client_encoding;
110 /** @protected string 現在実行中のアクション名 */
111 protected $action_name;
113 /** @protected string 現在実行中のXMLRPCメソッド名 */
114 protected $xmlrpc_method_name;
116 /** @protected array forward定義 */
117 protected $forward = array();
119 /** @protected array デフォルトのforward定義 */
120 protected $forward_default = array(
121 '403' => array( 'view_name' => 'Ethna_View_403',),
122 '404' => array( 'view_name' => 'Ethna_View_404',),
123 '500' => array( 'view_name' => 'Ethna_View_500',),
124 'json' => array( 'view_name' => 'Ethna_View_Json',),
125 'redirect' => array( 'view_name' => 'Ethna_View_Redirect',),
128 /** @protected array action定義 */
129 protected $action = array();
131 /** @protected array action(CLI)定義 */
132 protected $action_cli = array();
134 /** @protected array action(XMLRPC)定義 */
135 protected $action_xmlrpc = array();
137 /** @protected array アプリケーションマネージャ定義 */
138 protected $manager = array();
140 /** @protected object レンダラー */
141 protected $renderer = null;
143 /** @protected array フィルターチェイン(Ethna_Filterオブジェクトの配列) */
144 protected $filter_chain = array();
146 /** @protected object Ethna_ClassFactory クラスファクトリオブジェクト */
147 protected $class_factory = null;
149 /** @protected object Ethna_ActionForm フォームオブジェクト */
150 protected $action_form = null;
152 /** @protected object Ethna_View ビューオブジェクト */
153 protected $view = null;
155 /** @protected object Ethna_Config 設定オブジェクト */
156 protected $config = null;
158 /** @protected object Ethna_Logger ログオブジェクト */
159 protected $logger = null;
161 /** @protected object Ethna_Plugin プラグインオブジェクト */
162 protected $plugin = null;
164 /** @protected string リクエストのゲートウェイ(www/cli/rest/xmlrpc/soap...) */
165 protected $gateway = GATEWAY_WWW;
171 * Ethna_Controllerクラスのコンストラクタ
175 public function __construct($gateway = GATEWAY_WWW)
177 $GLOBALS['_Ethna_controller'] = $this;
178 if ($this->base === "") {
179 // EthnaコマンドなどでBASEが定義されていない場合がある
180 if (defined('BASE')) {
185 $this->gateway = $gateway;
188 foreach ($this->class_default as $key => $val) {
189 if (isset($this->class[$key]) == false) {
190 $this->class[$key] = $val;
195 foreach ($this->directory_default as $key => $val) {
196 if (isset($this->directory[$key]) == false) {
197 $this->directory[$key] = $val;
202 $class_factory = $this->class['class'];
203 $this->class_factory = new $class_factory($this, $this->class);
206 Ethna::setErrorCallback(array($this, 'handleError'));
208 // ディレクトリ名の設定(相対パス->絶対パス)
209 foreach ($this->directory as $key => $value) {
210 if ($key == 'plugins') {
211 // Smartyプラグインディレクトリは配列で指定する
213 foreach (to_array($value) as $elt) {
214 if (Ethna_Util::isAbsolute($elt) == false) {
215 $tmp[] = $this->base . (empty($this->base) ? '' : '/') . $elt;
218 $this->directory[$key] = $tmp;
220 if (Ethna_Util::isAbsolute($value) == false) {
221 $this->directory[$key] = $this->base . (empty($this->base) ? '' : '/') . $value;
228 $this->forward = $this->forward + $this->forward_default;
231 // フレームワークとしての内部エンコーディングはクライアント
232 // エンコーディング(=ブラウザからのエンコーディング)
234 // @see Ethna_Controller#_getDefaultLanguage
235 list($this->locale, $this->system_encoding, $this->client_encoding) = $this->_getDefaultLanguage();
237 mb_internal_encoding($this->client_encoding);
238 mb_regex_encoding($this->client_encoding);
240 $this->config = $this->getConfig();
241 $this->dsn = $this->_prepareDSN();
242 $this->url = $this->config->get('url');
245 $this->plugin = $this->getPlugin();
247 // include Ethna_Plugin_Abstract for all plugins
248 $this->plugin->includePlugin('Abstract');
250 //// assert (experimental)
251 //if ($this->config->get('debug') === false) {
252 // ini_set('assert.active', 0);
256 $this->logger = $this->getLogger();
257 $this->plugin->setLogger($this->logger);
258 $this->logger->begin();
261 $this->_activateEthnaManager();
265 * アプリケーション実行後の後始末を行います。
269 protected function end()
271 // 必要に応じてオーバライドして下さい。
272 $this->logger->end();
276 * (現在アクティブな)コントローラのインスタンスを返す
279 * @return object Ethna_Controller コントローラのインスタンス
282 public static function getInstance()
284 if (isset($GLOBALS['_Ethna_controller'])) {
285 return $GLOBALS['_Ethna_controller'];
296 * @return string アプリケーションID
298 public function getAppId()
300 return ucfirst(strtolower($this->appid));
307 * @param string $id アプリケーションID
308 * @return mixed true:OK Ethna_Error:NG
311 public static function checkAppId($id)
314 if (strcasecmp($id, 'ethna') === 0
315 || strcasecmp($id, 'app') === 0) {
316 return Ethna::raiseError("Application Id [$id] is reserved\n");
319 // アプリケーションIDはクラス名のprefixともなるため、
321 // @see http://www.php.net/manual/en/language.variables.php
322 if (preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $id) === 0) {
323 $msg = (preg_match('/^[0-9]$/', $id[0]))
324 ? "Application ID must NOT start with Number.\n"
325 : "Only Numeric(0-9) and Alphabetical(A-Z) is allowed for Application Id\n";
326 return Ethna::raiseError($msg);
335 * @param string $action_name アクション名
336 * @return mixed true:OK Ethna_Error:NG
339 public static function checkActionName($action_name)
342 if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
343 $action_name) === 0) {
344 return Ethna::raiseError("invalid action name [$action_name]");
353 * @param string $view_name ビュー名
354 * @return mixed true:OK Ethna_Error:NG
357 public static function checkViewName($view_name)
360 if (preg_match('/^[a-zA-Z\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/',
362 return Ethna::raiseError("invalid view name [$view_name]");
371 * @param string $db_key DBキー
374 public function getDSN($db_key = "")
376 if (isset($this->dsn[$db_key]) == false) {
379 return $this->dsn[$db_key];
386 * @param string $db_key DBキー
387 * @return bool true:persistent false:non-persistent(あるいは設定無し)
389 public function getDSN_persistent($db_key = "")
391 $key = sprintf("dsn%s_persistent", $db_key == "" ? "" : "_$db_key");
393 $dsn_persistent = $this->config->get($key);
394 if (is_null($dsn_persistent)) {
397 return $dsn_persistent;
404 * @param string $db_key DBキー("", "r", "rw", "default", "blog_r"...)
405 * @return string $db_keyに対応するDB種別定義(設定が無い場合はnull)
407 public function getDBType($db_key = null)
409 if (is_null($db_key)) {
414 if (isset($this->db[$db_key]) == false) {
417 return $this->db[$db_key];
424 * @return string アプリケーションベースURL
426 public function getURL()
432 * アプリケーションベースディレクトリを返す
435 * @return string アプリケーションベースディレクトリ
437 public function getBasedir()
443 * クライアントタイプ/言語からテンプレートディレクトリ名を決定する
444 * デフォルトでは [appid]/template/ja_JP/ (ja_JPはロケール名)
445 * ロケール名は _getDefaultLanguage で決定される。
448 * @return string テンプレートディレクトリ
449 * @see Ethna_Controller#_getDefaultLanguage
451 public function getTemplatedir()
453 $template = $this->getDirectory('template');
456 // _getDerfaultLanguageメソッドでロケールが指定されていた場合は、
457 // テンプレートディレクトリにも自動的にそれを付加する。
458 if (!empty($this->locale)) {
459 $template .= '/' . $this->locale;
469 * @return string アクションディレクトリ
471 public function getActiondir($gateway = null)
474 $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
483 $key = 'action_xmlrpc';
487 return (empty($this->directory[$key]) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory[$key] . "/"));
494 * @return string ビューディレクトリ
496 public function getViewdir()
498 return (empty($this->directory['view']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['view'] . "/"));
502 * (action,view以外の)テストケースを置くディレクトリ名を決定する
505 * @return string テストケースを置くディレクトリ
507 public function getTestdir()
509 return (empty($this->directory['test']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['test'] . "/"));
513 * アプリケーションディレクトリ設定を返す
516 * @param string $key ディレクトリタイプ("tmp", "template"...)
517 * @return string $keyに対応したアプリケーションディレクトリ(設定が無い場合はnull)
519 public function getDirectory($key)
521 if (isset($this->directory[$key]) == false) {
524 return $this->directory[$key];
527 * アプリケーションディレクトリ設定を返す
530 * @param string $key type
531 * @return string $key directory
533 public function setDirectory($key, $value)
535 $this->directory[$key] = $value;
543 * @param string $key 拡張子タイプ("php", "tpl"...)
544 * @return string $keyに対応した拡張子(設定が無い場合はnull)
546 public function getExt($key)
548 if (isset($this->ext[$key]) == false) {
551 return $this->ext[$key];
555 * クラスファクトリオブジェクトのアクセサ(R)
558 * @return object Ethna_ClassFactory クラスファクトリオブジェクト
560 public function getClassFactory()
562 return $this->class_factory;
566 * アクションエラーオブジェクトのアクセサ
569 * @return object Ethna_ActionError アクションエラーオブジェクト
571 public function getActionError()
573 return $this->class_factory->getObject('error');
577 * Accessor for ActionForm
580 * @return object Ethna_ActionForm アクションフォームオブジェクト
582 public function getActionForm()
584 // 明示的にクラスファクトリを利用していない
585 return $this->action_form;
589 * Setter for ActionForm
590 * if the ::$action_form class is not null, then cannot set the view
593 * @return object Ethna_ActionForm アクションフォームオブジェクト
595 public function setActionForm($af)
597 if ($this->action_form !== null) {
600 $this->action_form = $af;
606 * Accessor for ViewClass
609 * @return object Ethna_View ビューオブジェクト
611 public function getView()
613 // 明示的にクラスファクトリを利用していない
618 * Setter for ViewClass
619 * if the ::$view class is not null, then cannot set the view
622 * @param $view object Ethna_ViewClass
625 public function setView($view)
627 if ($this->view !== null) {
638 * @return object Ethna_Backend backendオブジェクト
640 public function getBackend()
642 return $this->class_factory->getObject('backend');
649 * @return object Ethna_Config 設定オブジェクト
651 public function getConfig()
653 return $this->class_factory->getObject('config');
660 * @return object Ethna_I18N i18nオブジェクト
662 public function getI18N()
664 return $this->class_factory->getObject('i18n');
671 * @return object Ethna_Logger ログオブジェクト
673 public function getLogger()
675 return $this->class_factory->getObject('logger');
682 * @return object Ethna_Session セッションオブジェクト
684 public function getSession()
686 return $this->class_factory->getObject('session');
693 * @return object Ethna_AppSQL SQLオブジェクト
695 public function getSQL()
697 return $this->class_factory->getObject('sql');
704 * @return object Ethna_Plugin プラグインオブジェクト
706 public function getPlugin()
708 return $this->class_factory->getObject('plugin');
715 * @return object Ethna_UrlHandler URLハンドラオブジェクト
717 public function getUrlHandler()
719 return $this->class_factory->getObject('url_handler');
726 * @return array マネージャ一覧
729 public function getManagerList()
731 return $this->manager;
738 * @return string 実行中のアクション名
740 public function getCurrentActionName()
742 return $this->action_name;
749 * @return string 実行中のXMLRPCメソッド名
751 public function getXmlrpcMethodName()
753 return $this->xmlrpc_method_name;
760 * @return array ロケール名(e.x ja_JP, en_US 等),
762 * クライアントエンコーディング名 の配列
763 * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
764 * @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html
766 public function getLanguage()
768 return array($this->locale, $this->system_encoding, $this->client_encoding);
775 * @return string ロケール名(e.x ja_JP, en_US 等),
776 * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
778 public function getLocale()
780 return $this->locale;
787 * @param $locale ロケール名(e.x ja_JP, en_US 等),
788 * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード)
790 public function setLocale($locale)
792 $this->locale = $locale;
793 $i18n = $this->getI18N();
794 $i18n->setLanguage($this->locale, $this->system_encoding, $this->client_encoding);
798 * クライアントエンコーディング名へのアクセサ(R)
801 * @return string $client_encoding クライアントエンコーディング名
803 public function getClientEncoding()
805 return $this->client_encoding;
809 * クライアントエンコーディング名へのアクセサ(W)
812 * @param string $client_encoding クライアントエンコーディング名
814 public function setClientEncoding($client_encoding)
816 $this->client_encoding = $client_encoding;
817 $i18n = $this->getI18N();
818 $i18n->setLanguage($this->locale, $this->system_encoding, $this->client_encoding);
826 public function getGateway()
828 return $this->gateway;
836 public function setGateway($gateway)
838 $this->gateway = $gateway;
845 * @param string $class_name アプリケーションコントローラのクラス名
846 * @param mixed $action_name 指定のアクション名(省略可)
847 * @param mixed $fallback_action_name アクションが決定できなかった場合に実行されるアクション名(省略可)
850 public static function main($class_name, $action_name = "", $fallback_action_name = "")
852 $c = new $class_name;
853 $c->trigger($action_name, $fallback_action_name);
858 * CLIアプリケーションのエントリポイント
861 * @param string $class_name アプリケーションコントローラのクラス名
862 * @param string $action_name 実行するアクション名
863 * @param bool $enable_filter フィルタチェインを有効にするかどうか
866 public static function main_CLI($class_name, $action_name, $enable_filter = true)
868 $c = new $class_name(GATEWAY_CLI);
869 $c->action_cli[$action_name] = array();
870 $c->trigger($action_name, "", $enable_filter);
875 * XMLRPCアプリケーションのエントリポイント
880 public static function main_XMLRPC($class_name)
882 if (extension_loaded('xmlrpc') == false) {
883 die("xmlrpc extension is required to enable this gateway");
886 $c = new $class_name(GATEWAY_XMLRPC);
887 $c->trigger("", "", false);
892 * SOAPアプリケーションのエントリポイント
895 * @param string $class_name アプリケーションコントローラのクラス名
896 * @param mixed $action_name 指定のアクション名(省略可)
897 * @param mixed $fallback_action_name アクションが決定できなかった場合に実行されるアクション名(省略可)
900 public static function main_SOAP($class_name, $action_name = "", $fallback_action_name = "")
902 $c = new $class_name(GATEWAY_SOAP);
903 $c->trigger($action_name, $fallback_action_name);
911 * @param mixed $default_action_name 指定のアクション名
912 * @param mixed $fallback_action_name アクション名が決定できなかった場合に実行されるアクション名
913 * @param bool $enable_filter フィルタチェインを有効にするかどうか
914 * @return mixed 0:正常終了 Ethna_Error:エラー
916 public function trigger($default_action_name = "", $fallback_action_name = "", $enable_filter = true)
919 if ($enable_filter) {
920 $this->_createFilterChain();
924 for ($i = 0; $i < count($this->filter_chain); $i++) {
925 $r = $this->filter_chain[$i]->preFilter();
926 if (Ethna::isError($r)) {
932 switch ($this->getGateway()) {
934 $this->_trigger_WWW($default_action_name, $fallback_action_name);
937 $this->_trigger_CLI($default_action_name);
940 $this->_trigger_XMLRPC();
943 $this->_trigger_SOAP();
948 for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
949 $r = $this->filter_chain[$i]->postFilter();
950 if (Ethna::isError($r)) {
957 * フレームワークの処理を実行する(WWW)
959 * 引数$default_action_nameに配列が指定された場合、その配列で指定された
960 * アクション以外は受け付けない(指定されていないアクションが指定された
961 * 場合、配列の先頭で指定されたアクションが実行される)
964 * @param mixed $default_action_name 指定のアクション名
965 * @param mixed $fallback_action_name アクション名が決定できなかった場合に実行されるアクション名
966 * @return mixed 0:正常終了 Ethna_Error:エラー
968 private function _trigger_WWW($default_action_name = "", $fallback_action_name = "")
971 $action_name = $this->_getActionName($default_action_name, $fallback_action_name);
974 $this->_ethnaManagerEnabledCheck($action_name);
977 $action_obj = $this->_getAction($action_name);
978 if (is_null($action_obj)) {
979 if ($fallback_action_name != "") {
980 $this->logger->log(LOG_DEBUG, 'undefined action [%s] -> try fallback action [%s]', $action_name, $fallback_action_name);
981 $action_obj = $this->_getAction($fallback_action_name);
983 if (is_null($action_obj)) {
984 return Ethna::raiseError("undefined action [%s]", E_APP_UNDEFINED_ACTION, $action_name);
986 $action_name = $fallback_action_name;
991 for ($i = 0; $i < count($this->filter_chain); $i++) {
992 $r = $this->filter_chain[$i]->preActionFilter($action_name);
994 $this->logger->log(LOG_DEBUG, 'action [%s] -> [%s] by %s', $action_name, $r, get_class($this->filter_chain[$i]));
998 $this->action_name = $action_name;
1001 $backend = $this->getBackend();
1002 $session = $this->getSession();
1003 $session->restore();
1006 $this->_setLanguage($this->locale, $this->system_encoding, $this->client_encoding);
1010 $form_name = $this->getActionFormName($action_name);
1011 $this->action_form = new $form_name($this);
1012 $this->action_form->setFormDef_PreHelper();
1013 $this->action_form->setFormVars();
1014 $backend->setActionForm($this->action_form);
1017 $forward_name = $backend->perform($action_name);
1020 for ($i = count($this->filter_chain) - 1; $i >= 0; $i--) {
1021 $r = $this->filter_chain[$i]->postActionFilter($action_name, $forward_name);
1023 $this->logger->log(LOG_DEBUG, 'forward [%s] -> [%s] by %s', $forward_name, $r, get_class($this->filter_chain[$i]));
1028 // コントローラで遷移先を決定する(オプション)
1029 $forward_name_params = $this->_sortForward($action_name, $forward_name);
1032 $preforward_params = array();
1033 if (is_array($forward_name_params)) {
1034 $forward_name = array_shift($forward_name_params);
1035 $preforward_params = $forward_name_params;
1038 $forward_name = $forward_name_params;
1041 if ($forward_name != null) {
1042 $view_class_name = $this->getViewClassName($forward_name);
1043 $this->view = new $view_class_name($backend, $forward_name, $this->_getForwardPath($forward_name));
1044 call_user_func_array(array($this->view, 'preforward'), $preforward_params);
1045 $this->view->forward();
1052 * フレームワークの処理を実行する(CLI)
1055 * @param mixed $default_action_name 指定のアクション名
1056 * @return mixed 0:正常終了 Ethna_Error:エラー
1058 private function _trigger_CLI($default_action_name = "")
1060 return $this->_trigger_WWW($default_action_name);
1064 * フレームワークの処理を実行する(XMLRPC)
1067 * @param mixed $action_name 指定のアクション名
1068 * @return mixed 0:正常終了 Ethna_Error:エラー
1070 private function _trigger_XMLRPC($action_name = "")
1072 // prepare xmlrpc server
1073 $xmlrpc_gateway_method_name = "_Ethna_XmlrpcGateway";
1074 $xmlrpc_server = xmlrpc_server_create();
1077 $param = xmlrpc_decode_request(file_get_contents('php://input'), $method);
1078 $this->xmlrpc_method_name = $method;
1080 $request = xmlrpc_encode_request(
1081 $xmlrpc_gateway_method_name,
1084 'output_type' => 'xml',
1085 'verbosity' => 'pretty',
1086 'escaping' => array('markup'),
1087 'version' => 'xmlrpc',
1088 'encoding' => 'utf-8'
1092 xmlrpc_server_register_method(
1094 $xmlrpc_gateway_method_name,
1095 $xmlrpc_gateway_method_name
1099 $r = xmlrpc_server_call_method(
1104 'output_type' => 'xml',
1105 'verbosity' => 'pretty',
1106 'escaping' => array('markup'),
1107 'version' => 'xmlrpc',
1108 'encoding' => 'utf-8'
1112 header('Content-Length: ' . strlen($r));
1113 header('Content-Type: text/xml; charset=UTF-8');
1118 * _trigger_XMLRPCのコールバックメソッド
1122 private function trigger_XMLRPC($method, $param)
1125 $action_obj = $this->_getAction($method);
1126 if (is_null($action_obj)) {
1127 return Ethna::raiseError("undefined xmlrpc method [%s]", E_APP_UNDEFINED_ACTION, $method);
1131 $backend = $this->getBackend();
1133 $form_name = $this->getActionFormName($method);
1134 $this->action_form = new $form_name($this);
1135 $def = $this->action_form->getDef();
1137 foreach ($def as $key => $value) {
1138 if (isset($param[$n]) == false) {
1139 $this->action_form->set($key, null);
1141 $this->action_form->set($key, $param[$n]);
1147 $backend->setActionForm($this->action_form);
1149 $session = $this->getSession();
1150 $session->restore();
1151 $r = $backend->perform($method);
1157 * SOAPフレームワークの処理を実行する
1161 private function _trigger_SOAP()
1164 $gg = new Ethna_SOAP_GatewayGenerator();
1165 $script = $gg->generate();
1169 $server = new SoapServer(null, array('uri' => $this->config->get('url')));
1170 $server->setClass($gg->getClassName());
1177 * エラー発生時の追加処理を行いたい場合はこのメソッドをオーバーライドする
1178 * (アラートメール送信等−デフォルトではログ出力時にアラートメール
1179 * が送信されるが、エラー発生時に別にアラートメールをここで送信
1183 * @param object Ethna_Error エラーオブジェクト
1185 public function handleError(&$error)
1188 list ($log_level, $dummy) = $this->logger->errorLevelToLogLevel($error->getLevel());
1189 $message = $error->getMessage();
1190 $this->logger->log($log_level, sprintf("%s [ERROR CODE(%d)]", $message, $error->getCode()));
1197 * @param int $code エラーコード
1198 * @return string エラーメッセージ
1200 public function getErrorMessage($code)
1202 $message_list = $GLOBALS['_Ethna_error_message_list'];
1203 for ($i = count($message_list)-1; $i >= 0; $i--) {
1204 if (array_key_exists($code, $message_list[$i])) {
1205 return $message_list[$i][$code];
1215 * @param mixed $default_action_name 指定のアクション名
1216 * @return string 実行するアクション名
1218 private function _getActionName($default_action_name, $fallback_action_name)
1220 // フォームから要求されたアクション名を取得する
1221 $form_action_name = $this->_getActionName_Form();
1222 $form_action_name = preg_replace('/[^a-z0-9\-_]+/i', '', $form_action_name);
1223 $this->logger->log(LOG_DEBUG, 'form_action_name[%s]', $form_action_name);
1225 // Ethnaマネージャへのフォームからのリクエストは拒否
1226 if ($form_action_name == "__ethna_info__" ||
1227 $form_action_name == "__ethna_unittest__") {
1228 $form_action_name = "";
1231 // フォームからの指定が無い場合はエントリポイントに指定されたデフォルト値を利用する
1232 if ($form_action_name == "" && count($default_action_name) > 0) {
1233 $tmp = is_array($default_action_name) ? $default_action_name[0] : $default_action_name;
1234 if ($tmp{strlen($tmp)-1} == '*') {
1235 $tmp = substr($tmp, 0, -1);
1237 $this->logger->log(LOG_DEBUG, '-> default_action_name[%s]', $tmp);
1238 $action_name = $tmp;
1240 $action_name = $form_action_name;
1243 // エントリポイントに配列が指定されている場合は指定以外のアクション名は拒否する
1244 if (is_array($default_action_name)) {
1245 if ($this->_isAcceptableActionName($action_name, $default_action_name) == false) {
1246 // 指定以外のアクション名で合った場合は$fallback_action_name(or デフォルト)
1247 $tmp = $fallback_action_name != "" ? $fallback_action_name : $default_action_name[0];
1248 if ($tmp{strlen($tmp)-1} == '*') {
1249 $tmp = substr($tmp, 0, -1);
1251 $this->logger->log(LOG_DEBUG, '-> fallback_action_name[%s]', $tmp);
1252 $action_name = $tmp;
1256 $this->logger->log(LOG_DEBUG, '<<< action_name[%s] >>>', $action_name);
1258 return $action_name;
1262 * フォームにより要求されたアクション名を返す
1264 * アプリケーションの性質に応じてこのメソッドをオーバーライドして下さい。
1265 * デフォルトでは"action_"で始まるフォーム値の"action_"の部分を除いたもの
1266 * ("action_sample"なら"sample")がアクション名として扱われます
1269 * @return string フォームにより要求されたアクション名
1271 protected function _getActionName_Form()
1273 if (isset($_SERVER['REQUEST_METHOD']) == false) {
1277 $url_handler = $this->getUrlHandler();
1278 if ($_SERVER['REQUEST_METHOD'] == "GET") {
1280 } else if ($_SERVER['REQUEST_METHOD'] == "POST") {
1284 if (empty($_SERVER['URL_HANDLER']) == false) {
1285 $tmp_vars['__url_handler__'] = $_SERVER['URL_HANDLER'];
1286 $tmp_vars['__url_info__'] = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : null;
1287 $tmp_vars = $url_handler->requestToAction($tmp_vars);
1289 if ($_SERVER['REQUEST_METHOD'] == "GET") {
1290 $_GET = array_merge($_GET, $tmp_vars);
1291 } else if ($_SERVER['REQUEST_METHOD'] == "POST") {
1292 $_POST = array_merge($_POST, $tmp_vars);
1294 $_REQUEST = array_merge($_REQUEST, $tmp_vars);
1297 if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0) {
1298 $http_vars = $_POST;
1303 // フォーム値からリクエストされたアクション名を取得する
1304 $action_name = $sub_action_name = null;
1305 foreach ($http_vars as $name => $value) {
1306 if ($value == "" || strncmp($name, 'action_', 7) != 0) {
1310 $tmp = substr($name, 7);
1313 if (preg_match('/_x$/', $name) || preg_match('/_y$/', $name)) {
1314 $tmp = substr($tmp, 0, strlen($tmp)-2);
1317 // value="dummy"となっているものは優先度を下げる
1318 if ($value == "dummy") {
1319 $sub_action_name = $tmp;
1321 $action_name = $tmp;
1324 if ($action_name == null) {
1325 $action_name = $sub_action_name;
1328 return $action_name;
1332 * アクション名を指定するクエリ/HTMLを生成する
1335 * @param string $action action to request
1336 * @param string $type hidden, url...
1337 * @todo consider gateway
1339 public function getActionRequest($action, $type = "hidden")
1342 if ($type == "hidden") {
1343 $s = sprintf('<input type="hidden" name="action_%s" value="true" />', htmlspecialchars($action, ENT_QUOTES));
1344 } else if ($type == "url") {
1345 $s = sprintf('action_%s=true', urlencode($action));
1351 * フォームにより要求されたアクション名に対応する定義を返す
1354 * @param string $action_name アクション名
1355 * @return array アクション定義
1357 public function _getAction($action_name, $gateway = null)
1360 $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
1363 $action = $this->action;
1366 $action = $this->action_cli;
1368 case GATEWAY_XMLRPC:
1369 $action = $this->action_xmlrpc;
1373 $action_obj = array();
1374 if (isset($action[$action_name])) {
1375 $action_obj = $action[$action_name];
1376 if (isset($action_obj['inspect']) && $action_obj['inspect']) {
1380 $this->logger->log(LOG_DEBUG, "action [%s] is not defined -> try default", $action_name);
1383 // アクションスクリプトのインクルード
1384 $this->_includeActionScript($action_obj, $action_name);
1387 if (isset($action_obj['class_name']) == false) {
1388 $action_obj['class_name'] = $this->getDefaultActionClass($action_name);
1391 if (isset($action_obj['form_name']) == false) {
1392 $action_obj['form_name'] = $this->getDefaultFormClass($action_name);
1393 } else if (class_exists($action_obj['form_name']) == false) {
1394 // 明示指定されたフォームクラスが定義されていない場合は警告
1395 $this->logger->log(LOG_WARNING, 'stated form class is not defined [%s]', $action_obj['form_name']);
1399 if (class_exists($action_obj['class_name']) == false) {
1400 $this->logger->log(LOG_NOTICE, 'action class is not defined [%s]', $action_obj['class_name']);
1401 $_ret_object = null;
1402 return $_ret_object;
1404 if (class_exists($action_obj['form_name']) == false) {
1406 $class_name = $this->class_factory->getObjectName('form');
1407 $this->logger->log(LOG_DEBUG, 'form class is not defined [%s] -> falling back to default [%s]', $action_obj['form_name'], $class_name);
1408 $action_obj['form_name'] = $class_name;
1411 $action_obj['inspect'] = true;
1412 $action[$action_name] = $action_obj;
1413 return $action[$action_name];
1417 * アクション名とアクションクラスからの戻り値に基づいて遷移先を決定する
1420 * @param string $action_name アクション名
1421 * @param string $retval アクションクラスからの戻り値
1422 * @return string 遷移先
1424 protected function _sortForward($action_name, $retval)
1434 protected function _createFilterChain()
1436 $this->filter_chain = array();
1437 foreach ($this->filter as $filter) {
1438 $filter_plugin = $this->plugin->getPlugin('Filter', $filter);
1439 if (Ethna::isError($filter_plugin)) {
1443 $this->filter_chain[] = $filter_plugin;
1448 * アクション名が実行許可されているものかどうかを返す
1451 * @param string $action_name リクエストされたアクション名
1452 * @param array $default_action_name 許可されているアクション名
1453 * @return bool true:許可 false:不許可
1455 private function _isAcceptableActionName($action_name, $default_action_name)
1457 foreach (to_array($default_action_name) as $name) {
1458 if ($action_name == $name) {
1460 } else if ($name{strlen($name)-1} == '*') {
1461 if (strncmp($action_name, substr($name, 0, -1), strlen($name)-1) == 0) {
1470 * 指定されたアクションのフォームクラス名を返す(オブジェクトの生成は行わない)
1473 * @param string $action_name アクション名
1474 * @return string アクションのフォームクラス名
1476 public function getActionFormName($action_name)
1478 $action_obj = $this->_getAction($action_name);
1479 if (is_null($action_obj)) {
1483 return $action_obj['form_name'];
1487 * アクションに対応するフォームクラス名が省略された場合のデフォルトクラス名を返す
1489 * デフォルトでは[プロジェクトID]_Form_[アクション名]となるので好み応じてオーバライドする
1492 * @param string $action_name アクション名
1493 * @return string アクションフォーム名
1495 public function getDefaultFormClass($action_name, $gateway = null)
1497 $gateway_prefix = $this->_getGatewayPrefix($gateway);
1499 $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
1500 $r = sprintf("%s_%sForm_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
1501 $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
1507 * getDefaultFormClass()で取得したクラス名からアクション名を取得する
1509 * getDefaultFormClass()をオーバーライドした場合、こちらも合わせてオーバーライド
1513 * @param string $class_name フォームクラス名
1514 * @return string アクション名
1516 public function actionFormToName($class_name)
1518 $prefix = sprintf("%s_Form_", $this->getAppId());
1519 if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
1523 $target = $match[1];
1525 $action_name = substr(preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $target), 1);
1527 return $action_name;
1531 * アクションに対応するフォームパス名が省略された場合のデフォルトパス名を返す
1533 * デフォルトでは_getDefaultActionPath()と同じ結果を返す(1ファイルに
1534 * アクションクラスとフォームクラスが記述される)ので、好みに応じて
1538 * @param string $action_name アクション名
1539 * @return string form classが定義されるスクリプトのパス名
1541 public function getDefaultFormPath($action_name)
1543 return $this->getDefaultActionPath($action_name);
1547 * 指定されたアクションのクラス名を返す(オブジェクトの生成は行わない)
1550 * @param string $action_name アクションの名称
1551 * @return string アクションのクラス名
1553 public function getActionClassName($action_name)
1555 $action_obj = $this->_getAction($action_name);
1556 if ($action_obj == null) {
1560 return $action_obj['class_name'];
1564 * アクションに対応するアクションクラス名が省略された場合のデフォルトクラス名を返す
1566 * デフォルトでは[プロジェクトID]_Action_[アクション名]となるので好み応じてオーバライドする
1569 * @param string $action_name アクション名
1570 * @return string アクションクラス名
1572 public function getDefaultActionClass($action_name, $gateway = null)
1574 $gateway_prefix = $this->_getGatewayPrefix($gateway);
1576 $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
1577 $r = sprintf("%s_%sAction_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
1578 $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
1584 * getDefaultActionClass()で取得したクラス名からアクション名を取得する
1586 * getDefaultActionClass()をオーバーライドした場合、こちらも合わせてオーバーライド
1590 * @param string $class_name アクションクラス名
1591 * @return string アクション名
1593 public function actionClassToName($class_name)
1595 $prefix = sprintf("%s_Action_", $this->getAppId());
1596 if (preg_match("/$prefix(.*)/", $class_name, $match) == 0) {
1600 $target = $match[1];
1602 $action_name = substr(preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $target), 1);
1604 return $action_name;
1608 * アクションに対応するアクションパス名が省略された場合のデフォルトパス名を返す
1610 * デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
1613 * @param string $action_name アクション名
1614 * @return string アクションクラスが定義されるスクリプトのパス名
1616 public function getDefaultActionPath($action_name)
1618 $r = preg_replace('/_(.)/e', "'/' . strtoupper('\$1')", ucfirst($action_name)) . '.' . $this->getExt('php');
1619 $this->logger->log(LOG_DEBUG, "default action path [%s]", $r);
1625 * 指定された遷移名に対応するビュークラス名を返す(オブジェクトの生成は行わない)
1628 * @param string $forward_name 遷移先の名称
1629 * @return string view classのクラス名
1631 public function getViewClassName($forward_name)
1633 if ($forward_name == null) {
1637 if (isset($this->forward[$forward_name])) {
1638 $forward_obj = $this->forward[$forward_name];
1640 $forward_obj = array();
1643 if (isset($forward_obj['view_name'])) {
1644 $class_name = $forward_obj['view_name'];
1645 if (class_exists($class_name)) {
1653 $this->_includeViewScript($forward_obj, $forward_name);
1655 if (is_null($class_name) == false && class_exists($class_name)) {
1657 } else if (is_null($class_name) == false) {
1658 $this->logger->log(LOG_WARNING, 'stated view class is not defined [%s] -> try default', $class_name);
1661 $class_name = $this->getDefaultViewClass($forward_name);
1662 if (class_exists($class_name)) {
1665 $class_name = $this->class_factory->getObjectName('view');
1666 $this->logger->log(LOG_DEBUG, 'view class is not defined for [%s] -> use default [%s]', $forward_name, $class_name);
1672 * 遷移名に対応するビュークラス名が省略された場合のデフォルトクラス名を返す
1674 * デフォルトでは[プロジェクトID]_View_[遷移名]となるので好み応じてオーバライドする
1677 * @param string $forward_name forward名
1678 * @return string view classクラス名
1680 public function getDefaultViewClass($forward_name, $gateway = null)
1682 $gateway_prefix = $this->_getGatewayPrefix($gateway);
1684 $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($forward_name));
1685 $r = sprintf("%s_%sView_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
1686 $this->logger->log(LOG_DEBUG, "default view class [%s]", $r);
1692 * 遷移名に対応するビューパス名が省略された場合のデフォルトパス名を返す
1694 * デフォルトでは"foo_bar" -> "/Foo/Bar.php"となるので好み応じてオーバーライドする
1697 * @param string $forward_name forward名
1698 * @return string view classが定義されるスクリプトのパス名
1700 public function getDefaultViewPath($forward_name)
1702 $r = preg_replace('/_(.)/e', "'/' . strtoupper('\$1')", ucfirst($forward_name)) . '.' . $this->getExt('php');
1703 $this->logger->log(LOG_DEBUG, "default view path [%s]", $r);
1709 * 遷移名に対応するテンプレートパス名が省略された場合のデフォルトパス名を返す
1711 * デフォルトでは"foo_bar"というforward名が"foo/bar" + テンプレート拡張子となる
1715 * @param string $forward_name forward名
1716 * @return string forwardパス名
1718 public function getDefaultForwardPath($forward_name)
1720 return str_replace('_', '/', $forward_name) . '.' . $this->ext['tpl'];
1724 * テンプレートパス名から遷移名を取得する
1726 * getDefaultForwardPath()をオーバーライドした場合、こちらも合わせてオーバーライド
1730 * @param string $forward_path テンプレートパス名
1731 * @return string 遷移名
1733 public function forwardPathToName($forward_path)
1735 $forward_path = preg_replace('/^\/+/', '', $forward_path);
1736 $forward_path = preg_replace(sprintf('/\.%s$/', $this->getExt('tpl')), '', $forward_path);
1738 return str_replace('/', '_', $forward_path);
1742 * 遷移名からテンプレートファイルのパス名を取得する
1745 * @param string $forward_name forward名
1746 * @return string テンプレートファイルのパス名
1748 public function _getForwardPath($forward_name)
1750 $forward_obj = null;
1752 if (isset($this->forward[$forward_name]) == false) {
1754 $this->forward[$forward_name] = array();
1756 $forward_obj = $this->forward[$forward_name];
1757 if (isset($forward_obj['forward_path']) == false) {
1759 $forward_obj['forward_path'] = $this->getDefaultForwardPath($forward_name);
1762 return $forward_obj['forward_path'];
1766 * レンダラを取得する(getTemplateEngine()はそのうち廃止されgetRenderer()に統合される予定)
1769 * @return object Ethna_Renderer レンダラオブジェクト
1771 public function getRenderer()
1773 // if action is __ethna_info__, the renderer must be Smarty2
1774 if ($this->action_name == '__ethna_info__') {
1775 require_once ETHNA_BASE . '/class/Renderer/Smarty.php';
1776 return new Ethna_Renderer_Smarty($this);
1778 $_ret_object = $this->getTemplateEngine();
1779 return $_ret_object;
1786 * @return object Ethna_Renderer レンダラオブジェクト
1789 public function getTemplateEngine()
1791 if (is_object($this->renderer)) {
1792 return $this->renderer;
1795 $this->renderer = $this->class_factory->getObject('renderer');
1797 //テンプレートエンジンのデフォルトの設定
1798 $this->_setDefaultTemplateEngine($this->renderer);
1801 return $this->renderer;
1805 * テンプレートエンジンのデフォルト状態を設定する
1808 * @param object Ethna_Renderer レンダラオブジェクト
1811 protected function _setDefaultTemplateEngine($renderer)
1817 * 条件によって使用言語、ロケールを切り替えたい場合は、
1821 * @param string $locale ロケール名(ja_JP, en_US等)
1822 * (ll_cc の形式。ll = 言語コード cc = 国コード)
1823 * @param string $system_encoding システムエンコーディング名
1824 * @param string $client_encoding クライアントエンコーディング(テンプレートのエンコーディングと考えれば良い)
1825 * @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html
1826 * @see Ethna_Controller#_getDefaultLanguage
1828 protected function _setLanguage($locale, $system_encoding = null, $client_encoding = null)
1830 $this->locale = $locale;
1831 $this->system_encoding = $system_encoding;
1832 $this->client_encoding = $client_encoding;
1834 // $this->locale, $this->client_encoding を書き換えた場合は
1835 // 必ず Ethna_I18N クラスの setLanguageメソッドも呼ぶこと!
1836 // さもないとカタログその他が再ロードされない!
1837 $i18n = $this->getI18N();
1838 $i18n->setLanguage($locale, $system_encoding, $client_encoding);
1842 * デフォルト状態での使用言語を取得する
1843 * 外部に出力されるEthnaのエラーメッセージ等のエンコーディングを
1844 * 切り替えたい場合は、このメソッドをオーバーライドする。
1847 * @return array ロケール名(e.x ja_JP, en_US 等),
1850 * (= テンプレートのエンコーディングと考えてよい) の配列
1851 * (ロケール名は ll_cc の形式。ll = 言語コード cc = 国コード)
1853 * WARNING!! : クライアントエンコーディング名が、フレームワークの内部エンコーデ
1854 * ィングとして設定されます。つまり、クライアントエンコーディングで
1855 * ブラウザからの入力は入ってくるものと想定しています!
1857 protected function _getDefaultLanguage()
1859 return array('ja_JP', 'UTF-8', 'UTF-8');
1863 * デフォルト状態でのゲートウェイを取得する
1866 * @return int ゲートウェイ定義(GATEWAY_WWW, GATEWAY_CLI...)
1868 protected function _getDefaultGateway($gateway)
1870 if (is_null($GLOBALS['_Ethna_gateway']) == false) {
1871 return $GLOBALS['_Ethna_gateway'];
1877 * ゲートウェイに対応したクラス名のプレフィクスを取得する
1880 * @param string $gateway ゲートウェイ
1881 * @return string ゲートウェイクラスプレフィクス
1883 protected function _getGatewayPrefix($gateway = null)
1885 $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
1893 case GATEWAY_XMLRPC:
1908 * @param string $name マネージャキー
1909 * @return string マネージャクラス名
1911 public function getManagerClassName($name)
1913 // アプリケーションIDと、渡された名前のはじめを大文字にして、
1915 $manager_id = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name));
1916 return sprintf('%s_%sManager', $this->getAppId(), ucfirst($manager_id));
1920 * アプリケーションオブジェクトクラス名を取得する
1923 * @param string $name アプリケーションオブジェクトキー
1924 * @return string マネージャクラス名
1926 public function getObjectClassName($name)
1928 // 引数のはじめの一文字目と、アンダーバー直後の
1929 // 1文字を必ず大文字にする。アンダーバーは削除される。
1930 $name = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name));
1932 // $name に foo_bar を渡し、AppID が Hogeの場合
1933 // [Appid]_FooBar が返される
1934 return sprintf('%s_%s', $this->getAppId(), $name);
1938 * アクションスクリプトをインクルードする
1940 * ただし、インクルードしたファイルにクラスが正しく定義されているかどうかは保証しない
1943 * @param array $action_obj アクション定義
1944 * @param string $action_name アクション名
1946 protected function _includeActionScript($action_obj, $action_name)
1948 $class_path = $form_path = null;
1950 $action_dir = $this->getActiondir();
1953 if (isset($action_obj['class_path'])) {
1955 $tmp_path = $action_obj['class_path'];
1956 if (Ethna_Util::isAbsolute($tmp_path) == false) {
1957 $tmp_path = $action_dir . $tmp_path;
1960 if (file_exists($tmp_path) == false) {
1961 $this->logger->log(LOG_WARNING, 'class_path file not found [%s] -> try default', $tmp_path);
1963 include_once $tmp_path;
1964 $class_path = $tmp_path;
1969 if (is_null($class_path)) {
1970 $class_path = $this->getDefaultActionPath($action_name);
1971 if (file_exists($action_dir . $class_path)) {
1972 include_once $action_dir . $class_path;
1974 $this->logger->log(LOG_DEBUG, 'default action file not found [%s] -> try all files', $class_path);
1980 if (isset($action_obj['form_path'])) {
1982 $tmp_path = $action_obj['form_path'];
1983 if (Ethna_Util::isAbsolute($tmp_path) == false) {
1984 $tmp_path = $action_dir . $tmp_path;
1987 if ($tmp_path == $class_path) {
1990 if (file_exists($tmp_path) == false) {
1991 $this->logger->log(LOG_WARNING, 'form_path file not found [%s] -> try default', $tmp_path);
1993 include_once $tmp_path;
1994 $form_path = $tmp_path;
1999 if (is_null($form_path)) {
2000 $form_path = $this->getDefaultFormPath($action_name);
2001 if ($form_path == $class_path) {
2004 if (file_exists($action_dir . $form_path)) {
2005 include_once $action_dir . $form_path;
2007 $this->logger->log(LOG_DEBUG, 'default form file not found [%s] -> maybe falling back to default form class', $form_path);
2015 * ただし、インクルードしたファイルにクラスが正しく定義されているかどうかは保証しない
2018 * @param array $forward_obj 遷移定義
2019 * @param string $forward_name 遷移名
2021 protected function _includeViewScript($forward_obj, $forward_name)
2023 $view_dir = $this->getViewdir();
2026 if (isset($forward_obj['view_path'])) {
2028 $tmp_path = $forward_obj['view_path'];
2029 if (Ethna_Util::isAbsolute($tmp_path) == false) {
2030 $tmp_path = $view_dir . $tmp_path;
2033 if (file_exists($tmp_path) == false) {
2034 $this->logger->log(LOG_WARNING, 'view_path file not found [%s] -> try default', $tmp_path);
2036 include_once $tmp_path;
2042 $view_path = $this->getDefaultViewPath($forward_name);
2043 if (file_exists($view_dir . $view_path)) {
2044 include_once $view_dir . $view_path;
2047 $this->logger->log(LOG_DEBUG, 'default view file not found [%s]', $view_path);
2053 * ディレクトリ以下の全てのスクリプトをインクルードする
2057 protected function _includeDirectory($dir)
2059 $ext = "." . $this->ext['php'];
2060 $ext_len = strlen($ext);
2062 if (is_dir($dir) == false) {
2066 $dh = opendir($dir);
2068 while (($file = readdir($dh)) !== false) {
2069 if ($file != '.' && $file != '..' && is_dir("$dir/$file")) {
2070 $this->_includeDirectory("$dir/$file");
2072 if (substr($file, -$ext_len, $ext_len) != $ext) {
2075 include_once $dir . '/' . $file;
2082 * 設定ファイルのDSN定義から使用するデータを再構築する(スレーブアクセス分岐等)
2084 * DSNの定義方法(デフォルト:設定ファイル)を変えたい場合はここをオーバーライドする
2087 * @return array DSN定義(array('DBキー1' => 'dsn1', 'DBキー2' => 'dsn2', ...))
2089 protected function _prepareDSN()
2093 foreach ($this->db as $key => $value) {
2094 $config_key = "dsn";
2096 $config_key .= "_$key";
2098 $dsn = $this->config->get($config_key);
2099 if (is_array($dsn)) {
2100 // 種別1つにつき複数DSNが定義されている場合はアクセス分岐
2101 $dsn = $this->_selectDSN($key, $dsn);
2111 * スレーブサーバへの振分け処理(デフォルト:ランダム)を変更したい場合はこのメソッドをオーバーライドする
2114 * @param string $type DB種別
2115 * @param array $dsn_list DSN一覧
2116 * @return string 選択されたDSN
2118 protected function _selectDSN($type, $dsn_list)
2120 if (is_array($dsn_list) == false) {
2125 list($usec, $sec) = explode(' ', microtime());
2126 mt_srand($sec + ((float) $usec * 100000));
2127 $n = mt_rand(0, count($dsn_list)-1);
2129 return $dsn_list[$n];
2135 * 不要な場合は空のメソッドとしてオーバーライドしてもよい
2139 protected function _activateEthnaManager()
2141 if ($this->config->get('debug') == false) {
2145 require_once ETHNA_BASE . '/class/InfoManager.php';
2147 // see if we have simpletest
2148 if (file_exists_ex('simpletest/unit_tester.php', true)) {
2149 require_once ETHNA_BASE . '/class/UnitTestManager.php';
2153 $this->action['__ethna_info__'] = array(
2154 'form_name' => 'Ethna_Form_Info',
2155 'form_path' => sprintf('%s/class/Action/Info.php', ETHNA_BASE),
2156 'class_name' => 'Ethna_Action_Info',
2157 'class_path' => sprintf('%s/class/Action/Info.php', ETHNA_BASE),
2161 $this->forward['__ethna_info__'] = array(
2162 'forward_path' => sprintf('%s/tpl/info.tpl', ETHNA_BASE),
2163 'view_name' => 'Ethna_View_Info',
2164 'view_path' => sprintf('%s/class/View/Info.php', ETHNA_BASE),
2169 $this->action['__ethna_unittest__'] = array(
2170 'form_name' => 'Ethna_Form_UnitTest',
2171 'form_path' => sprintf('%s/class/Action/UnitTest.php', ETHNA_BASE),
2172 'class_name' => 'Ethna_Action_UnitTest',
2173 'class_path' => sprintf('%s/class/Action/UnitTest.php', ETHNA_BASE),
2177 $this->forward['__ethna_unittest__'] = array(
2178 'forward_path' => sprintf('%s/tpl/unittest.tpl', ETHNA_BASE),
2179 'view_name' => 'Ethna_View_UnitTest',
2180 'view_path' => sprintf('%s/class/View/UnitTest.php', ETHNA_BASE),
2186 * Ethnaマネージャが実行可能かをチェックする
2188 * Ethnaマネージャを実行するよう指示されているにも関わらず、
2189 * debug が trueでない場合は実行を停止する。
2193 protected function _ethnaManagerEnabledCheck($action_name)
2195 if ($this->config->get('debug') == false
2196 && ($action_name == '__ethna_info__' || $action_name == '__ethna_unittest__'))
2198 $this->ethnaManagerCheckErrorMsg($action_name);
2204 * Ethnaマネージャが実行不能な場合のエラーメッセージを
2205 * 表示する。運用上の都合でこのメッセージを出力したくない
2206 * 場合は、このメソッドをオーバーライドせよ
2210 protected function ethnaManagerCheckErrorMsg($action_name)
2212 $appid = strtolower($this->getAppId());
2213 $run_action = ($action_name == '__ethna_info__')
2214 ? ' show Application Info List '
2215 : ' run Unit Test ';
2216 echo "Ethna cannot {$run_action} under your application setting.<br>";
2217 echo "HINT: You must set {$appid}/etc/{$appid}-ini.php debug setting 'true'.<br>";
2219 echo "In {$appid}-ini.php, please set as follows :<br><br>";
2220 echo "\$config = array ( 'debug' => true, );";
2227 * @return bool CLI実行中フラグ
2230 public function getCLI()
2232 return $this->gateway == GATEWAY_CLI ? true : false;
2239 * @param bool CLI実行中フラグ
2242 public function setCLI($cli)
2244 $this->gateway = $cli ? GATEWAY_CLI : $this->_getDefaultGateway();
2250 * XMLRPCゲートウェイのスタブクラス
2254 function _Ethna_XmlrpcGateway($method_stub, $param)
2256 $ctl = Ethna_Controller::getInstance();
2257 $method = $ctl->getXmlrpcMethodName();
2258 $r = $ctl->trigger_XMLRPC($method, $param);
2259 if (Ethna::isError($r)) {
2261 'faultCode' => $r->getCode(),
2262 'faultString' => $r->getMessage(),