From c38ef5f4c6623f1fb441823a4dafc12a313b7289 Mon Sep 17 00:00:00 2001 From: Yoshinari Takaoka Date: Fri, 16 Oct 2009 17:57:21 +0900 Subject: [PATCH] - merged changes from 2009-01-30 to 2009-04-29. --- CHANGES | 34 ++++ Ethna.php | 2 +- bin/ethna_handle.php | 24 ++- bin/ethna_run_test.php | 15 +- class/Ethna_ActionForm.php | 24 +++ class/Ethna_Config.php | 2 +- class/Ethna_Controller.php | 133 +++----------- class/Ethna_Getopt.php | 12 +- class/Ethna_ViewClass.php | 29 ++- .../Generator/Ethna_Plugin_Generator_Project.php | 2 - .../Generator/Ethna_Plugin_Generator_Template.php | 10 +- .../Handle/Ethna_Plugin_Handle_AddProject.php | 2 +- .../Handle/Ethna_Plugin_Handle_AddTemplate.php | 4 +- class/Plugin/Handle/Ethna_Plugin_Handle_Help.php | 87 +++++++++ class/Plugin/Smarty/block.form.php | 7 + class/Plugin/Smarty/function.form_input.php | 2 +- skel/app.controller.php | 98 ++-------- skel/locale/ja_JP/ethna_sysmsg.ini | 6 +- skel/skel.app_manager.php | 4 +- skel/www.index.php | 2 +- skel/www.info.php | 2 +- skel/www.unittest.php | 2 +- test/Ethna_Getopt_Test.php | 21 ++- test/Ethna_MockProject.php | 6 +- test/Ethna_ViewClass_Test.php | 2 - .../Ethna_Plugin_Handle_AddTemplate_Test.php | 93 ++++++++++ .../Handle/Ethna_Plugin_Handle_I18n_Test.php | 40 +++++ .../Handle/Ethna_Plugin_Handle_PearLocal_Test.php | 64 +++++++ test/TextDetailReporter.php | 2 +- test/skel/app.controller.php | 199 +++++++++++++++++++++ 30 files changed, 669 insertions(+), 261 deletions(-) create mode 100644 class/Plugin/Handle/Ethna_Plugin_Handle_Help.php create mode 100644 test/Plugin/Handle/Ethna_Plugin_Handle_AddTemplate_Test.php create mode 100644 test/Plugin/Handle/Ethna_Plugin_Handle_PearLocal_Test.php create mode 100644 test/skel/app.controller.php diff --git a/CHANGES b/CHANGES index ee92828..3f39932 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,38 @@ * 変更点一覧 +** 2.5.0 + +*** features + +- フォーム定義に関する変更 +-- フォーム定義を動的に変更するためのAPIをさらに追加 +-- Ethna_ActionForm#setFormDef_ViewHelper +- APPID_Controller.php のスケルトンに継承を想定したメソッドを追加 +-- skel/app.controller.php _setDefaultTemplateEngin +- add-project 時の www 以下に出来るエントリポイントから APPID_Controller へのパスを相対パスに変更 +- ethna コマンドの挙動変更 +-- ethna help コマンドを追加 +- 指定 Action が存在しない場合い、app/action 以下を全て include する仕様を変更 +- add-project -b オプションの挙動変更 +- controller での smarty_xx_plugin の機能を削除 + +*** bug fix + +- Ethna_Controller#getTemplatedir を無視してテンプレートディレクトリを決定していたバグを修正(thanks: hiko) +-- getTemplatedirメソッドをオーバライドしても強制的にロケールが付加されていた +-- https://sourceforge.jp/ticket/browse.php?group_id=1343&tid=15570 +- "ethna pear-local list -a" の実行結果がエラーになってしまうバグを修正 +-- https://sourceforge.jp/ticket/browse.php?group_id=1343&tid=15760 +- safe-mode が ON の際に、CacheManager_Localfile がディレクトリを生成できないので、tmp ディレクトリ直下にキャッシュファイルを作成するようにした +-- skel/skel.app_manager.php も修正 +- APPID-ini.php が存在しない場合,またはURLが設定にない場合,デフォルトURLが HTTP_HOST で設定されていたが,末尾に / がなかったので修正 +- フォームヘルパで自動的に出力されるhiddenタグの閉じ忘れを修正(thanks: id:syachi5150) +- ethna add-app-manager コマンドで生成されるファイル名およびクラス名が間違っていたバグを修正(thanks: id:syachi5150) +-- https://sourceforge.jp/ticket/browse.php?group_id=1343&tid=16137 +- Validatorが出力するメッセージからフォーム名の後ろのスペースを削るように修正。(thanks: id:syachi5150) +-- https://sourceforge.jp/ticket/browse.php?group_id=1343&tid=16336 + + ** 2.5.0-preview4 *** bug fix @@ -7,6 +40,7 @@ - フォーム定義が配列で、Ethna_ActionForm#getHiddenVars の値を Ethna_ActionForm#setAppNE した場合、クロスサイトスクリプティング脆弱性が存在するバグを修正 (thanks: shuitic) -- http://sourceforge.jp/ticket/browse.php?group_id=1343&tid=17332 + ** 2.5.0-preview3 *** features diff --git a/Ethna.php b/Ethna.php index 102d9d5..1121337 100644 --- a/Ethna.php +++ b/Ethna.php @@ -45,7 +45,7 @@ if (!defined('DIRECTORY_SEPARATOR')) { } /** バージョン定義 */ -define('ETHNA_VERSION', '2.5.0-preview4'); +define('ETHNA_VERSION', '2.5.0'); /** * ダミーのエラーモード diff --git a/bin/ethna_handle.php b/bin/ethna_handle.php index 3483de0..cc9907c 100644 --- a/bin/ethna_handle.php +++ b/bin/ethna_handle.php @@ -35,7 +35,7 @@ $eh =& new Ethna_Handle(); list($my_arg_list, $arg_list) = _Ethna_HandleGateway_SeparateArgList($arg_list); $r = $opt->getopt($my_arg_list, "v", array("version")); if (Ethna::isError($r)) { - usage($eh); + _Ethna_HandleGateway_ShowUsage(); exit(1); } @@ -48,16 +48,17 @@ foreach ($r[0] as $opt) { } if (count($arg_list) == 0) { - usage($eh); + _Ethna_HandleGateway_ShowUsage(); exit(1); } $id = array_shift($arg_list); $handler =& $eh->getHandler($id); +$handler->eh =& $eh; if (Ethna::isError($handler)) { printf("no such command: %s\n\n", $id); - usage($eh); + _Ethna_HandleGateway_ShowUsage(); exit(1); } @@ -73,18 +74,15 @@ if (Ethna::isError($r)) { } /** - * usage + * show usage */ -function usage(&$eh) +function _Ethna_HandleGateway_ShowUsage() { - $handler_list = $eh->getHandlerList(); - printf("usage: ethna [option] [command] [args...]\n\n"); - printf("available options are as follows:\n\n"); - printf(" -v, --version show version and exit\n"); - printf("\navailable commands are as follows:\n\n"); - foreach ($handler_list as $handler) { - printf(" %s -> %s\n", $handler->getId(), $handler->getDescription()); - } + $message = <<backend も初期化済みのため、DBやセッション * の値に基づいてフォーム定義を変更することができます。 * @@ -1254,6 +1258,26 @@ class Ethna_ActionForm } /** + * フォーム定義変更用、ユーザ定義ヘルパメソッド + * + * フォームヘルパを使うときに、フォーム定義を動的に + * 変更したい場合に、このメソッドをオーバーライドします。 + * + * 以下の定義をテンプレートで行った場合に呼び出されます。 + * + * {form ethna_action=...} (ethna_action がない場合は呼び出されません) + * {form_input action=...} (action がない場合は呼び出されません) + * + * @access public + */ + function setFormDef_ViewHelper() + { + // TODO: デフォルト実装は Ethna_ActionClass#prepare 前に + // 呼び出されるものと同じ。異なる場合にオーバライドする + $this->setFormDef_PreHelper(); + } + + /** * ヘルパオブジェクト(アプリケーションオブジェクト) * 経由でのフォーム値定義を設定する * diff --git a/class/Ethna_Config.php b/class/Ethna_Config.php index a3dbef6..c6e7af8 100644 --- a/class/Ethna_Config.php +++ b/class/Ethna_Config.php @@ -117,7 +117,7 @@ class Ethna_Config // デフォルト値設定 if (isset($_SERVER['HTTP_HOST']) && isset($config['url']) == false) { - $config['url'] = sprintf("http://%s", $_SERVER['HTTP_HOST']); + $config['url'] = sprintf("http://%s/", $_SERVER['HTTP_HOST']); } if (isset($config['dsn']) == false) { $config['dsn'] = ""; diff --git a/class/Ethna_Controller.php b/class/Ethna_Controller.php index a7db244..5d591c4 100644 --- a/class/Ethna_Controller.php +++ b/class/Ethna_Controller.php @@ -134,25 +134,6 @@ class Ethna_Controller /** @var object レンダラー */ var $renderer = null; - /** @var array smarty modifier定義 */ - var $smarty_modifier_plugin = array(); - - /** @var array smarty function定義 */ - var $smarty_function_plugin = array(); - - /** @var array smarty block定義 */ - var $smarty_block_plugin = array(); - - /** @var array smarty prefilter定義 */ - var $smarty_prefilter_plugin = array(); - - /** @var array smarty postfilter定義 */ - var $smarty_postfilter_plugin = array(); - - /** @var array smarty outputfilter定義 */ - var $smarty_outputfilter_plugin = array(); - - /** @var array フィルターチェイン(Ethna_Filterオブジェクトの配列) */ var $filter_chain = array(); @@ -268,14 +249,14 @@ class Ethna_Controller } /** - * アプリケーション実行後の後始末を行います。 + * アプリケーション実行後の後始末を行います。 * - * @access protected + * @access protected */ function end() { // 必要に応じてオーバライドして下さい。 - $this->logger->end(); + $this->logger->end(); } /** @@ -459,7 +440,9 @@ class Ethna_Controller $template = $this->getDirectory('template'); // 言語別ディレクトリ - if (file_exists($template . '/' . $this->locale)) { + // _getDerfaultLanguageメソッドでロケールが指定されていた場合は、 + // テンプレートディレクトリにも自動的にそれを付加する。 + if (!empty($this->locale)) { $template .= '/' . $this->locale; } @@ -719,7 +702,7 @@ class Ethna_Controller * システムエンコーディング名, * クライアントエンコーディング名 の配列 * (ロケール名は、ll_cc の形式。ll = 言語コード cc = 国コード) - * @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html + * @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html */ function getLanguage() { @@ -1035,7 +1018,7 @@ class Ethna_Controller 'version' => 'xmlrpc', 'encoding' => 'utf-8' ) - ); + ); xmlrpc_server_register_method( $xmlrpc_server, @@ -1286,9 +1269,9 @@ class Ethna_Controller */ function getActionRequest($action, $type = "hidden") { - $s = null; + $s = null; if ($type == "hidden") { - $s = sprintf('', htmlspecialchars($action, ENT_QUOTES)); + $s = sprintf('', htmlspecialchars($action, ENT_QUOTES)); } else if ($type == "url") { $s = sprintf('action_%s=true', urlencode($action)); } @@ -1667,7 +1650,7 @@ class Ethna_Controller { return str_replace('_', '/', $forward_name) . '.' . $this->ext['tpl']; } - + /** * テンプレートパス名から遷移名を取得する * @@ -1734,71 +1717,8 @@ class Ethna_Controller if (is_object($this->renderer)) { return $this->renderer; } - - $this->renderer =& $this->class_factory->getObject('renderer'); - - // {{{ for B.C. - if (strtolower(get_class($this->renderer)) == "ethna_renderer_smarty") { - // user defined modifiers - foreach ($this->smarty_modifier_plugin as $modifier) { - if (!is_array($modifier)) { - $name = str_replace('smarty_modifier_', '', $modifier); - $this->renderer->setPlugin($name,'modifier', $modifier); - } else { - $this->renderer->setPlugin($modifier[1], 'modifier', $modifier); - } - } - - // user defined functions - foreach ($this->smarty_function_plugin as $function) { - if (!is_array($function)) { - $name = str_replace('smarty_function_', '', $function); - $this->renderer->setPlugin($name, 'function', $function); - } else { - $this->renderer->setPlugin($function[1], 'function', $function); - } - } - // user defined blocks - foreach ($this->smarty_block_plugin as $block) { - if (!is_array($block)) { - $name = str_replace('smarty_block_', '', $block); - $this->renderer->setPlugin($name,'block', $block); - } else { - $this->renderer->setPlugin($block[1],'block', $block); - } - } - - // user defined prefilters - foreach ($this->smarty_prefilter_plugin as $prefilter) { - if (!is_array($prefilter)) { - $name = str_replace('smarty_prefilter_', '', $prefilter); - $this->renderer->setPlugin($name,'prefilter', $prefilter); - } else { - $this->renderer->setPlugin($prefilter[1],'prefilter', $prefilter); - } - } - - // user defined postfilters - foreach ($this->smarty_postfilter_plugin as $postfilter) { - if (!is_array($postfilter)) { - $name = str_replace('smarty_postfilter_', '', $postfilter); - $this->renderer->setPlugin($name,'postfilter', $postfilter); - } else { - $this->renderer->setPlugin($postfilter[1],'postfilter', $postfilter); - } - } - - // user defined outputfilters - foreach ($this->smarty_outputfilter_plugin as $outputfilter) { - if (!is_array($outputfilter)) { - $name = str_replace('smarty_outputfilter_', '', $outputfilter); - $this->renderer->setPlugin($name,'outputfilter', $outputfilter); - } else { - $this->renderer->setPlugin($outputfilter[1],'outputfilter', $outputfilter); - } - } - } + $this->renderer =& $this->class_factory->getObject('renderer'); //テンプレートエンジンのデフォルトの設定 $this->_setDefaultTemplateEngine($this->renderer); @@ -1828,7 +1748,7 @@ class Ethna_Controller * (ll_cc の形式。ll = 言語コード cc = 国コード) * @param string $system_encoding システムエンコーディング名 * @param string $client_encoding クライアントエンコーディング(テンプレートのエンコーディングと考えれば良い) - * @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html + * @see http://www.gnu.org/software/gettext/manual/html_node/Locale-Names.html * @see Ethna_Controller#_getDefaultLanguage */ function _setLanguage($locale, $system_encoding = null, $client_encoding = null) @@ -1917,8 +1837,9 @@ class Ethna_Controller function getManagerClassName($name) { // アプリケーションIDと、渡された名前のはじめを大文字にして、 - // 組み合わせたものが返される - return sprintf('%s_%sManager', $this->getAppId(), ucfirst($name)); + // 組み合わせたものが返される + $manager_id = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name)); + return sprintf('%s_%sManager', $this->getAppId(), ucfirst($manager_id)); } /** @@ -1933,7 +1854,7 @@ class Ethna_Controller // 引数のはじめの一文字目と、アンダーバー直後の // 1文字を必ず大文字にする。アンダーバーは削除される。 $name = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name)); - + // $name に foo_bar を渡し、AppID が Hogeの場合 // [Appid]_FooBar が返される return sprintf('%s_%s', $this->getAppId(), $name); @@ -1977,15 +1898,9 @@ class Ethna_Controller include_once $action_dir . $class_path; } else { $this->logger->log(LOG_DEBUG, 'default action file not found [%s] -> try all files', $class_path); - $class_path = null; + return; } } - - // 全ファイルインクルード - if (is_null($class_path)) { - $this->_includeDirectory($this->getActiondir()); - return; - } // form_path属性チェック if (isset($action_obj['form_path'])) { @@ -2118,7 +2033,7 @@ class Ethna_Controller /** * DSNのアクセス分岐を行う - * + * * スレーブサーバへの振分け処理(デフォルト:ランダム)を変更したい場合はこのメソッドをオーバーライドする * * @access protected @@ -2136,7 +2051,7 @@ class Ethna_Controller list($usec, $sec) = explode(' ', microtime()); mt_srand($sec + ((float) $usec * 100000)); $n = mt_rand(0, count($dsn_list)-1); - + return $dsn_list[$n]; } @@ -2154,7 +2069,7 @@ class Ethna_Controller } require_once ETHNA_BASE . '/class/Ethna_InfoManager.php'; - + // see if we have simpletest if (file_exists_ex('simpletest/unit_tester.php', true)) { require_once ETHNA_BASE . '/class/Ethna_UnitTestManager.php'; @@ -2174,8 +2089,8 @@ class Ethna_Controller 'view_name' => 'Ethna_View_Info', 'view_path' => sprintf('%s/class/View/Ethna_View_Info.php', ETHNA_BASE), ); - - + + // action設定 $this->action['__ethna_unittest__'] = array( 'form_name' => 'Ethna_Form_UnitTest', @@ -2228,7 +2143,7 @@ class Ethna_Controller echo "
"; echo "In {$appid}-ini.php, please set as follows :

"; echo "\$config = array ( 'debug' => true, );"; - } + } /** * CLI実行中フラグを取得する diff --git a/class/Ethna_Getopt.php b/class/Ethna_Getopt.php index e0b6033..3af565b 100644 --- a/class/Ethna_Getopt.php +++ b/class/Ethna_Getopt.php @@ -228,7 +228,17 @@ class Ethna_Getopt } } else { // オプションとして解釈されない - $nonparsed_arguments[] = $arg; + + // non-parsed なオプションに辿り着いた + // ら、それ以降の解釈を停止する + // つまり、それ以降は全て値として解釈する + // + // これは POSIX_CORRECT な実装であって + // GNU Getopt な実装ではないが、実際に + // Console_Getopt で行われている以上、 + // それに従った実装 + $nonparsed_arguments = array_slice($args, $pos); + break; } } diff --git a/class/Ethna_ViewClass.php b/class/Ethna_ViewClass.php index b6970f0..3aa4964 100644 --- a/class/Ethna_ViewClass.php +++ b/class/Ethna_ViewClass.php @@ -145,29 +145,40 @@ class Ethna_ViewClass * helperアクションフォームオブジェクトを設定する * * @param string $action アクション名 + * @param boolean $dynamic_helper 動的フォームヘルパを呼ぶか否か * @access public */ - function addActionFormHelper($action) + function addActionFormHelper($action, $dynamic_helper = false) { + // + // 既に追加されている場合は処理をしない + // if (isset($this->helper_action_form[$action]) && is_object($this->helper_action_form[$action])) { return; } + // 現在のアクションと等しければ、対応する + // アクションフォームを設定 $ctl =& Ethna_Controller::getInstance(); if ($action === $ctl->getCurrentActionName()) { $this->helper_action_form[$action] =& $this->af; - return; + } else { + // アクションが異なる場合 + $form_name = $ctl->getActionFormName($action); + if ($form_name === null) { + $this->logger->log(LOG_WARNING, + 'action form for the action [%s] not found.', $action); + return; + } + $this->helper_action_form[$action] =& new $form_name($ctl); } - $form_name = $ctl->getActionFormName($action); - if ($form_name === null) { - $this->logger->log(LOG_WARNING, - 'action form for the action [%s] not found.', $action); - return; + // 動的フォームを設定するためのヘルパメソッドを呼ぶ + if ($dynamic_helper) { + $af =& $this->helper_action_form[$action]; + $af->setFormDef_ViewHelper(); } - - $this->helper_action_form[$action] =& new $form_name($ctl); } // }}} diff --git a/class/Plugin/Generator/Ethna_Plugin_Generator_Project.php b/class/Plugin/Generator/Ethna_Plugin_Generator_Project.php index f0f02b8..4454469 100644 --- a/class/Plugin/Generator/Ethna_Plugin_Generator_Project.php +++ b/class/Plugin/Generator/Ethna_Plugin_Generator_Project.php @@ -71,8 +71,6 @@ class Ethna_Plugin_Generator_Project extends Ethna_Plugin_Generator return $r; } - $basedir = sprintf("%s/%s", $basedir, $id); - // ディレクトリ作成 if (is_dir($basedir) == false) { // confirm diff --git a/class/Plugin/Generator/Ethna_Plugin_Generator_Template.php b/class/Plugin/Generator/Ethna_Plugin_Generator_Template.php index 23d0dc2..0e80cf0 100644 --- a/class/Plugin/Generator/Ethna_Plugin_Generator_Template.php +++ b/class/Plugin/Generator/Ethna_Plugin_Generator_Template.php @@ -39,18 +39,10 @@ class Ethna_Plugin_Generator_Template extends Ethna_Plugin_Generator // ロケール名がディレクトリに含まれていない場合は、 // ディレクトリがないためなのでそれを補正 $tpl_dir = $this->ctl->getTemplatedir(); - if (!empty($locale) && strpos($tpl_dir, $locale) === false) { - $tpl_dir = $this->ctl->getDirectory('template'); - $tpl_dir .= "/$locale"; - } - if ($tpl_dir{strlen($tpl_dir)-1} != '/') { - $tpl_dir .= '/'; - } - $tpl_path = $this->ctl->getDefaultForwardPath($forward_name); // entity - $entity = $tpl_dir . $tpl_path; + $entity = $tpl_dir . '/' . $tpl_path; Ethna_Util::mkdir(dirname($entity), 0755); // skelton diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_AddProject.php b/class/Plugin/Handle/Ethna_Plugin_Handle_AddProject.php index c895f0b..ff975fd 100644 --- a/class/Plugin/Handle/Ethna_Plugin_Handle_AddProject.php +++ b/class/Plugin/Handle/Ethna_Plugin_Handle_AddProject.php @@ -46,7 +46,7 @@ class Ethna_Plugin_Handle_AddProject extends Ethna_Plugin_Handle if (isset($opt_list['basedir'])) { $basedir = realpath(end($opt_list['basedir'])); } else { - $basedir = getcwd(); + $basedir = sprintf("%s/%s", getcwd(), strtolower($app_id)); } // skeldir diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_AddTemplate.php b/class/Plugin/Handle/Ethna_Plugin_Handle_AddTemplate.php index 9b3fe4a..b8715f1 100644 --- a/class/Plugin/Handle/Ethna_Plugin_Handle_AddTemplate.php +++ b/class/Plugin/Handle/Ethna_Plugin_Handle_AddTemplate.php @@ -63,7 +63,7 @@ class Ethna_Plugin_Handle_AddTemplate extends Ethna_Plugin_Handle_AddView { return <<id} [-b|--basedir=dir] [-s|--skelfile=file] [-l|--locale] [-e|--encoding] [template] + {$this->id} [-b|--basedir=dir] [-s|--skelfile=file] [-l|--locale=locale] [-e|--encoding] [template] EOS; } @@ -74,7 +74,7 @@ EOS; function getUsage() { return <<id} [-b|--basedir=dir] [-s|--skelfile=file] [-l|--locale] [-e|--encoding] [template] +ethna {$this->id} [-b|--basedir=dir] [-s|--skelfile=file] [-l|--locale=locale] [-e|--encoding] [template] EOS; } } diff --git a/class/Plugin/Handle/Ethna_Plugin_Handle_Help.php b/class/Plugin/Handle/Ethna_Plugin_Handle_Help.php new file mode 100644 index 0000000..803f94e --- /dev/null +++ b/class/Plugin/Handle/Ethna_Plugin_Handle_Help.php @@ -0,0 +1,87 @@ + + * @license http://www.opensource.org/licenses/bsd-license.php The BSD License + * @package Ethna + * @version $Id: $ + */ + +// {{{ Ethna_Plugin_Handle_Help +/** + * add-action handler + * + * @author ICHII Takashi + * @access public + * @package Ethna + */ +class Ethna_Plugin_Handle_Help extends Ethna_Plugin_Handle +{ + /** + * show help + * + * @access public + */ + function perform() + { + $r =& $this->_getopt(); + if (Ethna::isError($r)) { + return $r; + } + list($opt_list, $arg_list) = $r; + + // action_name + $handle_name = array_shift($arg_list); + if (!strlen($handle_name)) { + $handler_list = $this->eh->getHandlerList(); + printf("usage: ethna [option] [command] [args...]\n\n"); + printf("available options are as follows:\n\n"); + printf(" -v, --version show version and exit\n"); + printf("\navailable commands are as follows:\n\n"); + foreach ($handler_list as $handler) { + printf(" %s\n", $handler->getId()); + } + return true; + } + + // getHandler + $handler =& $this->eh->getHandler($handle_name); + if (Ethna::isError($handler) || $handler === false) { + // command not found + return Ethna::raiseError('command not found.', 'usage'); + } + + echo $handler->getDescription(); + + return true; + + } + + /** + * get handler's description + * + * @access public + */ + function getDescription() + { + return <<id} [command_name] + +EOS; + } + + /** + * @access public + */ + function getUsage() + { + return <<id} [command_name] +EOS; + } +} +// }}} +?> diff --git a/class/Plugin/Smarty/block.form.php b/class/Plugin/Smarty/block.form.php index 316c6b7..b3ae1b4 100644 --- a/class/Plugin/Smarty/block.form.php +++ b/class/Plugin/Smarty/block.form.php @@ -32,6 +32,13 @@ function smarty_block_form($params, $content, &$smarty, &$repeat) = 'default'; } + // 動的フォームヘルパを呼ぶ + if (isset($params['ethna_action'])) { + $ethna_action = $params['ethna_action']; + $view =& $c->getView(); + $view->addActionFormHelper($ethna_action, true); + } + // ここで返す値は出力されない return ''; diff --git a/class/Plugin/Smarty/function.form_input.php b/class/Plugin/Smarty/function.form_input.php index 3e8a77e..6d62936 100644 --- a/class/Plugin/Smarty/function.form_input.php +++ b/class/Plugin/Smarty/function.form_input.php @@ -39,7 +39,7 @@ function smarty_function_form_input($params, &$smarty) $action = $block_params['ethna_action']; } if ($action !== null) { - $view->addActionFormHelper($action); + $view->addActionFormHelper($action, true); } // default diff --git a/skel/app.controller.php b/skel/app.controller.php index ebe6d5e..29ef5e1 100644 --- a/skel/app.controller.php +++ b/skel/app.controller.php @@ -13,7 +13,7 @@ define('BASE', dirname(dirname(__FILE__))); /** include_path setting (adding "/app" and "/lib" directory to include_path) */ $app = BASE . "/app"; $lib = BASE . "/lib"; -ini_set('include_path', implode(PATH_SEPARATOR, array($app, $lib)) . PATH_SEPARATOR . ini_get('include_path')); +set_include_path(implode(PATH_SEPARATOR, array($app, $lib)) . PATH_SEPARATOR . get_include_path()); /** including application library. */ @@ -65,7 +65,12 @@ class {$project_id}_Controller extends Ethna_Controller * * Example: * - * 'index' => array(), + * 'index' => array( + * 'form_name' => 'Sample_Form_SomeAction', + * 'form_path' => 'Some/Action.php', + * 'class_name' => 'Sample_Action_SomeAction', + * 'class_path' => 'Some/Action.php', + * ), */ ); @@ -178,84 +183,6 @@ class {$project_id}_Controller extends Ethna_Controller */ ); - /** - * @var array smarty modifier definition. - */ - var $smarty_modifier_plugin = array( - /* - * TODO: write user defined smarty modifier here. - * - * Example: - * - * 'smarty_modifier_foo_bar', - */ - ); - - /** - * @var array smarty function definition. - */ - var $smarty_function_plugin = array( - /* - * TODO: write user defined smarty function here. - * - * Example: - * - * 'smarty_function_foo_bar', - */ - ); - - /** - * @var array smarty block definition. - */ - var $smarty_block_plugin = array( - /* - * TODO: write user defined smarty block here. - * - * Example: - * - * 'smarty_block_foo_bar', - */ - ); - - /** - * @var array smarty prefilter definition. - */ - var $smarty_prefilter_plugin = array( - /* - * TODO: write user defined smarty prefilter here. - * - * Example: - * - * 'smarty_prefilter_foo_bar', - */ - ); - - /** - * @var array smarty postfilter definition. - */ - var $smarty_postfilter_plugin = array( - /* - * TODO: write user defined smarty postfilter here. - * - * Example: - * - * 'smarty_postfilter_foo_bar', - */ - ); - - /** - * @var array smarty outputfilter definition. - */ - var $smarty_outputfilter_plugin = array( - /* - * TODO: write user defined smarty outputfilter here. - * - * Example: - * - * 'smarty_outputfilter_foo_bar', - */ - ); - /**#@-*/ /** @@ -272,6 +199,17 @@ class {$project_id}_Controller extends Ethna_Controller { return array('{$locale}', 'UTF-8', '{$client_enc}'); } + + /** + * テンプレートエンジンのデフォルト状態を設定する + * + * @access protected + * @param object Ethna_Renderer レンダラオブジェクト + * @obsolete + */ + function _setDefaultTemplateEngine(&$renderer) + { + } } ?> diff --git a/skel/locale/ja_JP/ethna_sysmsg.ini b/skel/locale/ja_JP/ethna_sysmsg.ini index c8a806a..91a7fe2 100644 --- a/skel/locale/ja_JP/ethna_sysmsg.ini +++ b/skel/locale/ja_JP/ethna_sysmsg.ini @@ -20,8 +20,8 @@ "Please input {form} properly." = "{form}を正しく入力してください" "Please input {form}." = "{form}を入力して下さい" "Please select {form}." = "{form}を選択して下さい" -"{form} was not selected." = "{form} が選択されていません" -"no input to {form}." = "{form} が入力されていません" +"{form} was not selected." = "{form}が選択されていません" +"no input to {form}." = "{form}が入力されていません" "Required item of {form} was not selected." = "{form}の必要な項目が選択されていません" "Required item of {form} was not submitted." = "{form}の必要な項目が入力されていません" "Please input scalar value to {form}." = "{form}にはスカラー値を入力して下さい" @@ -50,7 +50,7 @@ "File was not uploaded." = "ファイルはアップロードされませんでした。" "Temporary folder was not found." = "テンポラリフォルダがありません。" "Could not write uploaded file to disk." = "ディスクへの書き込みに失敗しました。" -"invalid tmp_name." = "tmp_name が不正です。" +"invalid tmp_name." = "tmp_nameが不正です。" "Invalid file name." = "ファイル名が正しくありません" "Invalid file type." = "ファイルタイプが正しくありません。" "Uploaded file size must be less than %s." = "ファイルサイズは%s以下にしてください。" diff --git a/skel/skel.app_manager.php b/skel/skel.app_manager.php index 8e09b77..d4af361 100644 --- a/skel/skel.app_manager.php +++ b/skel/skel.app_manager.php @@ -8,13 +8,13 @@ */ /** - * {$app_manager}Manager + * {$app_manager} * * @author {$author} * @access public * @package {$project_id} */ -class {$app_manager}Manager extends Ethna_AppManager +class {$app_manager} extends Ethna_AppManager { } ?> diff --git a/skel/www.index.php b/skel/www.index.php index c968fd1..f5f69ab 100644 --- a/skel/www.index.php +++ b/skel/www.index.php @@ -1,5 +1,5 @@ diff --git a/skel/www.info.php b/skel/www.info.php index 57e5f1c..dcc668f 100644 --- a/skel/www.info.php +++ b/skel/www.info.php @@ -1,5 +1,5 @@ assertEqual('a', $parsed_arg[0][0]); $this->assertNULL($parsed_arg[0][1]); - $this->assertEqual('c', $parsed_arg[1][0]); - $this->assertEqual('d', $parsed_arg[1][1]); - $this->assertEqual('e', $parsed_arg[2][0]); - $this->assertNULL($parsed_arg[2][1]); $nonparsed_arg = array_shift($r); $this->assertEqual('b', $nonparsed_arg[0]); - $this->assertEqual('f', $nonparsed_arg[1]); + $this->assertEqual('-c', $nonparsed_arg[1]); + $this->assertEqual('d', $nonparsed_arg[2]); + $this->assertEqual('-e', $nonparsed_arg[3]); + $this->assertEqual('f', $nonparsed_arg[4]); } function test_shortopt_complex() @@ -196,7 +195,7 @@ class Ethna_Getopt_Test extends Ethna_UnitTestBase // complex option part 1. $args = array(); $shortopt = 'ab:c::'; - $args = array('-abc', '-cd'); + $args = array('-abcd', '-cd'); $r = $this->opt->getopt($args, $shortopt); $this->assertFalse(Ethna::isError($r)); @@ -205,7 +204,7 @@ class Ethna_Getopt_Test extends Ethna_UnitTestBase $this->assertNULL($parsed_arg[0][1]); $this->assertEqual('b', $parsed_arg[1][0]); - $this->assertEqual('c', $parsed_arg[1][1]); + $this->assertEqual('cd', $parsed_arg[1][1]); $this->assertEqual('c', $parsed_arg[2][0]); $this->assertEqual('d', $parsed_arg[2][1]); @@ -289,8 +288,8 @@ class Ethna_Getopt_Test extends Ethna_UnitTestBase $nonparsed_arg = array_shift($r); $this->assertEqual('hoge', $nonparsed_arg[0]); - // --foo option value is bar. hoge is nonparsed. - $args = array('--foo', 'bar', 'hoge'); + // --foo option value is bar. hoge, -fuga is nonparsed. + $args = array('--foo', 'bar', 'hoge', '-fuga'); $shortopt = NULL; $longopt = array("foo="); $r = $this->opt->getopt($args, $shortopt, $longopt); @@ -302,6 +301,7 @@ class Ethna_Getopt_Test extends Ethna_UnitTestBase $nonparsed_arg = array_shift($r); $this->assertEqual('hoge', $nonparsed_arg[0]); + $this->assertEqual('-fuga', $nonparsed_arg[1]); } function test_longopt_optional() @@ -417,12 +417,11 @@ class Ethna_Getopt_Test extends Ethna_UnitTestBase $this->assertEqual('bar', $parsed_arg[1][1]); $this->assertequal('--bar', $parsed_arg[2][0]); $this->assertEqual('moge', $parsed_arg[2][1]); - $this->assertequal('--hoge', $parsed_arg[3][0]); - $this->assertNULL($parsed_arg[3][1]); $nonparsed_arg = array_shift($r); $this->assertEqual('hoge', $nonparsed_arg[0]); + $this->assertEqual('--hoge', $nonparsed_arg[1]); } // }}} } diff --git a/test/Ethna_MockProject.php b/test/Ethna_MockProject.php index 593986c..2cd797f 100644 --- a/test/Ethna_MockProject.php +++ b/test/Ethna_MockProject.php @@ -65,7 +65,7 @@ class Ethna_MockProject $id = 'add-project'; $options = array( '-b', - $this->basedir, + $this->basedir . '/' . $this->project_name, '-s', $this->skel_dir, $this->project_name, @@ -104,8 +104,8 @@ class Ethna_MockProject } } if (!$in_basedir_opt) { - $options[] = '-b'; - $options[] = $this->proj_basedir; + $base_opt = array('-b', $this->proj_basedir); + $options = array_merge($base_opt, $options); } $eh =& new Ethna_Handle(); diff --git a/test/Ethna_ViewClass_Test.php b/test/Ethna_ViewClass_Test.php index 18a932d..df2b32c 100644 --- a/test/Ethna_ViewClass_Test.php +++ b/test/Ethna_ViewClass_Test.php @@ -6,8 +6,6 @@ * @author halt feits */ -//error_reporting(E_ALL); - /** * Ethna_ViewClassクラスのテストケース * diff --git a/test/Plugin/Handle/Ethna_Plugin_Handle_AddTemplate_Test.php b/test/Plugin/Handle/Ethna_Plugin_Handle_AddTemplate_Test.php new file mode 100644 index 0000000..e0eabd7 --- /dev/null +++ b/test/Plugin/Handle/Ethna_Plugin_Handle_AddTemplate_Test.php @@ -0,0 +1,93 @@ + + * @version $Id$ + */ + +require_once ETHNA_BASE . '/test/Ethna_MockProject.php'; + +//{{{ Ethna_Plugin_Handle_AddTemplate_Test +/** + * Test Case For Ethna_Plugin_Handle_AddTemplate_Test + * + * @access public + */ +class Ethna_Plugin_Handle_AddTemplate_Test extends Ethna_UnitTestBase +{ + var $proj; + + function setUp() + { + $this->proj = new Ethna_MockProject(); + $r = $this->proj->create(); + if (Ethna::isError($r)) { + $this->fail($r->getMessage()); + } + } + + function tearDown() + { + $this->proj->delete(); + } + + function test_template_dir_exists() + { + $ctl =& $this->proj->getController(); + + // default locale + $r = $this->proj->runCmd('add-template', array('test')); + $template_dir = $ctl->getTemplatedir(); + $this->assertTrue(file_exists($template_dir)); + + // new locale + $r = $this->proj->runCmd('add-template', array('-l', 'en_US', 'test')); + $template_dir = $ctl->getTemplatedir(); + $this->assertTrue(file_exists($template_dir)); + } + + function test_cmd_option() + { + // unrecognized option + $r = $this->proj->runCmd('add-template', array('-k')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('unrecognized option -k', $r->getMessage()); + + // skel requires an argument + $r = $this->proj->runCmd('add-template', array('-s')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('option -s requires an argument', $r->getMessage()); + + $r = $this->proj->runCmd('add-template', array('--skelfile')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('option --skelfile requires an argument', $r->getMessage()); + + // locale requires an argument + $r = $this->proj->runCmd('add-template', array('-l')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('option -l requires an argument', $r->getMessage()); + + $r = $this->proj->runCmd('add-template', array('--locale')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('option --locale requires an argument', $r->getMessage()); + + // template name isn't set + $r = $this->proj->runCmd('add-template', array()); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('template name isn\'t set.', $r->getMessage()); + + // invalid locale + $r = $this->proj->runCmd('add-template', array('-l', 'invalid::locale', 'test')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('You specified locale, but invalid : invalid::locale', $r->getMessage()); + + // normal command exexute + $r = $this->proj->runCmd('add-template', array('-l', 'ja_JP', 'test')); + $this->assertFalse(Ethna::isError($r)); + } +} +// }}} + +?> diff --git a/test/Plugin/Handle/Ethna_Plugin_Handle_I18n_Test.php b/test/Plugin/Handle/Ethna_Plugin_Handle_I18n_Test.php index 9179cf2..96d1bb8 100644 --- a/test/Plugin/Handle/Ethna_Plugin_Handle_I18n_Test.php +++ b/test/Plugin/Handle/Ethna_Plugin_Handle_I18n_Test.php @@ -124,6 +124,44 @@ class Ethna_Plugin_Handle_I18n_Test extends Ethna_UnitTestBase $this->assertTrue(isset($catalog['template i18n multiple modifier'])); } + function test_cmd_option() + { + // unrecognized option + $r = $this->proj->runCmd('i18n', array('-k')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('unrecognized option -k', $r->getMessage()); + + // --locale(requires an argument) + $r = $this->proj->runCmd('i18n', array('-l')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('option -l requires an argument', $r->getMessage()); + + $r = $this->proj->runCmd('i18n', array('-l', 'ko_KR')); + $this->assertFalse(Ethna::isError($r)); + + $r = $this->proj->runCmd('i18n', array('--locale')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('option --locale requires an argument', $r->getMessage()); + + // --gettext option only + $r = $this->proj->runCmd('i18n', array('-g')); + $this->assertFalse(Ethna::isError($r)); + + $r = $this->proj->runCmd('i18n', array('--gettext')); + $this->assertFalse(Ethna::isError($r)); + + // --gettext not allowed an argument + $r = $this->proj->runCmd('i18n', array('--gettext=foo')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual("option --gettext doesn't allow an argument", $r->getMessage()); + + // --locale and --gettext mixin + $r = $this->proj->runCmd('i18n', array('-g', '-l', 'ko_KR')); + $this->assertFalse(Ethna::isError($r)); + + $r = $this->proj->runCmd('i18n', array('--gettext', '--locale=ko_KR')); + $this->assertFalse(Ethna::isError($r)); + } function run_i18n_cmd() { @@ -133,6 +171,8 @@ class Ethna_Plugin_Handle_I18n_Test extends Ethna_UnitTestBase return; } } + + } // }}} diff --git a/test/Plugin/Handle/Ethna_Plugin_Handle_PearLocal_Test.php b/test/Plugin/Handle/Ethna_Plugin_Handle_PearLocal_Test.php new file mode 100644 index 0000000..29e682c --- /dev/null +++ b/test/Plugin/Handle/Ethna_Plugin_Handle_PearLocal_Test.php @@ -0,0 +1,64 @@ + + * @version $Id$ + */ + +require_once ETHNA_BASE . '/test/Ethna_MockProject.php'; + +//{{{ Ethna_Plugin_Handle_PearLocal_Test +/** + * Test Case For Ethna_Plugin_Handle_PearLocal_Test + * + * @access public + */ +class Ethna_Plugin_Handle_PearLocal_Test extends Ethna_UnitTestBase +{ + var $proj; + + function setUp() + { + $this->proj = new Ethna_MockProject(); + $r = $this->proj->create(); + if (Ethna::isError($r)) { + $this->fail($r->getMessage()); + } + } + + function tearDown() + { + $this->proj->delete(); + } + + function test_cmd_option() + { + // unrecognized option + $r = $this->proj->runCmd('pear-local', array('-k')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('unrecognized option -k', $r->getMessage()); + + // pear list -a(get no error) + // @see http://sourceforge.jp/ticket/browse.php?group_id=1343&tid=15760 + $r = $this->proj->runCmd('pear-local', array('list', '-a')); + $this->assertFalse(Ethna::isError($r)); + + // channel requires an argument + $r = $this->proj->runCmd('pear-local', array('-c')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('option -c requires an argument', $r->getMessage()); + + $r = $this->proj->runCmd('pear-local', array('--channel')); + $this->assertTrue(Ethna::isError($r)); + $this->assertEqual('option --channel requires an argument', $r->getMessage()); + + // normal command exexute(offline only) + $r = $this->proj->runCmd('pear-local', array('config-set', 'default_channel', 'pear.php.net')); + $this->assertFalse(Ethna::isError($r)); + } +} +// }}} + +?> diff --git a/test/TextDetailReporter.php b/test/TextDetailReporter.php index 627150b..089c46e 100644 --- a/test/TextDetailReporter.php +++ b/test/TextDetailReporter.php @@ -60,7 +60,7 @@ class TextDetailReporter extends SimpleReporter { */ function paintFail($message) { parent::paintFail($message); - print $this->getFailCount() . ") $message\n"; + print "\n\t" . $this->getFailCount() . ") $message\n"; $breadcrumb = $this->getTestList(); array_shift($breadcrumb); print "\tin " . implode("\n\tin ", array_reverse($breadcrumb)); diff --git a/test/skel/app.controller.php b/test/skel/app.controller.php new file mode 100644 index 0000000..0c8a0ba --- /dev/null +++ b/test/skel/app.controller.php @@ -0,0 +1,199 @@ + array( + * 'view_name' => '{$project_id}_View_Index', + * ), + */ + ); + + /** + * @var array action definition. + */ + var $action = array( + /* + * TODO: write action definition here. + * + * Example: + * + * 'index' => array(), + */ + ); + + /** + * @var array SOAP action definition. + */ + var $soap_action = array( + /* + * TODO: write action definition for SOAP application here. + * Example: + * + * 'sample' => array(), + */ + ); + + /** + * @var array application directory. + */ + var $directory = array( + 'action' => 'app/action', + 'action_cli' => 'app/action_cli', + 'action_xmlrpc' => 'app/action_xmlrpc', + 'app' => 'app', + 'plugin' => 'app/plugin', + 'bin' => 'bin', + 'etc' => 'etc', + 'filter' => 'app/filter', + 'locale' => 'locale', + 'log' => 'log', + 'plugins' => array('app/plugin/Smarty',), + 'template' => 'template', + 'template_c' => 'tmp', + 'tmp' => 'tmp', + 'view' => 'app/view', + 'www' => 'www', + 'test' => 'app/test', + ); + + /** + * @var array database access definition. + */ + var $db = array( + '' => DB_TYPE_RW, + ); + + /** + * @var array extention(.php, etc) configuration. + */ + var $ext = array( + 'php' => 'php', + 'tpl' => 'tpl', + ); + + /** + * @var array class definition. + */ + var $class = array( + /* + * TODO: When you override Configuration class, Logger class, + * SQL class, don't forget to change definition as follows! + */ + 'class' => 'Ethna_ClassFactory', + 'backend' => 'Ethna_Backend', + 'config' => 'Ethna_Config', + 'db' => 'Ethna_DB_PEAR', + 'error' => 'Ethna_ActionError', + 'form' => '{$project_id}_ActionForm', + 'i18n' => 'Ethna_I18N', + 'logger' => 'Ethna_Logger', + 'plugin' => 'Ethna_Plugin', + 'session' => 'Ethna_Session', + 'sql' => 'Ethna_AppSQL', + 'view' => '{$project_id}_ViewClass', + 'renderer' => 'Ethna_Renderer_Smarty', + 'url_handler' => '{$project_id}_UrlHandler', + ); + + /** + * @var array list of application id where Ethna searches plugin. + */ + var $plugin_search_appids = array( + /* + * write list of application id where Ethna searches plugin. + * + * Example: + * When there are plugins whose name are like "Common_Plugin_Foo_Bar" in + * application plugin directory, Ethna searches them in the following order. + * + * 1. Common_Plugin_Foo_Bar, + * 2. {$project_id}_Plugin_Foo_Bar + * 3. Ethna_Plugin_Foo_Bar + * + * 'Common', '{$project_id}', 'Ethna', + */ + '{$project_id}', 'Ethna', + ); + + /** + * @var array filter definition. + */ + var $filter = array( + /* + * TODO: when you use filter, write filter plugin name here. + * (If you specify class name, Ethna reads filter class in + * filter directory) + * + * Example: + * + * 'ExecutionTime', + */ + ); + + /**#@-*/ + + /** + * Get Default language and locale setting. + * If you want to change Ethna's output encoding, override this method. + * + * @access protected + * @return array locale name(e.x ja_JP, en_US .etc), + * system encoding name, + * client encoding name(= template encoding) + * (locale name is "ll_cc" format. ll = language code. cc = country code.) + */ + function _getDefaultLanguage() + { + return array('{$locale}', 'UTF-8', '{$client_enc}'); + } +} + +?> -- 2.11.0