* 変更点一覧
+** 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
- フォーム定義が配列で、Ethna_ActionForm#getHiddenVars の値を Ethna_ActionForm#setAppNE した場合、クロスサイトスクリプティング脆弱性が存在するバグを修正 (thanks: shuitic)
-- http://sourceforge.jp/ticket/browse.php?group_id=1343&tid=17332
+
** 2.5.0-preview3
*** features
}
/** バージョン定義 */
-define('ETHNA_VERSION', '2.5.0-preview4');
+define('ETHNA_VERSION', '2.5.0');
/**
* ダミーのエラーモード
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);
}
}
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);
}
}
/**
- * 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 = <<<EOD
+Type 'ethna help' for usage.
+
+EOD;
+ echo $message;
}
/**
/** Ethnaインストールルートディレクトリ */
define('ETHNA_INSTALL_BASE', dirname(dirname(__FILE__)));
+/** テストケースがあるディレクトリ */
+$test_dir = ETHNA_INSTALL_BASE . '/test';
+
/** include_pathの設定(このtest runnerがあるディレクトリを追加) */
-ini_set('include_path', dirname(ETHNA_INSTALL_BASE) . PATH_SEPARATOR . ini_get('include_path'));
+ini_set('include_path', realpath(ETHNA_INSTALL_BASE . '/class') . PATH_SEPARATOR . ini_get('include_path'));
+
/** Ethna関連クラスのインクルード */
-require_once 'Ethna/Ethna.php';
+require_once ETHNA_INSTALL_BASE . '/Ethna.php';
/** SimpleTestのインクルード */
require_once 'simpletest/unit_tester.php';
require_once 'simpletest/reporter.php';
-require_once 'Ethna/test/TextDetailReporter.php';
-require_once 'Ethna/test/Ethna_UnitTestBase.php';
-
-/** テストケースがあるディレクトリ */
-$test_dir = ETHNA_INSTALL_BASE . '/test';
+require_once $test_dir . '/TextDetailReporter.php';
+require_once $test_dir . '/Ethna_UnitTestBase.php';
$test = &new GroupTest('Ethna All tests');
}
/**
+ * フォーム定義変更用、ユーザ定義ヘルパメソッド
+ *
+ * Ethna_ActionForm#prepare() が実行される前に
* ユーザが動的にフォーム定義を変更したい場合に
* このメソッドをオーバーライドします。
+ *
* $this->backend も初期化済みのため、DBやセッション
* の値に基づいてフォーム定義を変更することができます。
*
}
/**
+ * フォーム定義変更用、ユーザ定義ヘルパメソッド
+ *
+ * フォームヘルパを使うときに、フォーム定義を動的に
+ * 変更したい場合に、このメソッドをオーバーライドします。
+ *
+ * 以下の定義をテンプレートで行った場合に呼び出されます。
+ *
+ * {form ethna_action=...} (ethna_action がない場合は呼び出されません)
+ * {form_input action=...} (action がない場合は呼び出されません)
+ *
+ * @access public
+ */
+ function setFormDef_ViewHelper()
+ {
+ // TODO: デフォルト実装は Ethna_ActionClass#prepare 前に
+ // 呼び出されるものと同じ。異なる場合にオーバライドする
+ $this->setFormDef_PreHelper();
+ }
+
+ /**
* ヘルパオブジェクト(アプリケーションオブジェクト)
* 経由でのフォーム値定義を設定する
*
// デフォルト値設定
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'] = "";
/** @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();
}
/**
- * アプリケーション実行後の後始末を行います。
+ * アプリケーション実行後の後始末を行います。
*
- * @access protected
+ * @access protected
*/
function end()
{
// 必要に応じてオーバライドして下さい。
- $this->logger->end();
+ $this->logger->end();
}
/**
$template = $this->getDirectory('template');
// 言語別ディレクトリ
- if (file_exists($template . '/' . $this->locale)) {
+ // _getDerfaultLanguageメソッドでロケールが指定されていた場合は、
+ // テンプレートディレクトリにも自動的にそれを付加する。
+ if (!empty($this->locale)) {
$template .= '/' . $this->locale;
}
* システムエンコーディング名,
* クライアントエンコーディング名 の配列
* (ロケール名は、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()
{
'version' => 'xmlrpc',
'encoding' => 'utf-8'
)
- );
+ );
xmlrpc_server_register_method(
$xmlrpc_server,
*/
function getActionRequest($action, $type = "hidden")
{
- $s = null;
+ $s = null;
if ($type == "hidden") {
- $s = sprintf('<input type="hidden" name="action_%s" value="true">', htmlspecialchars($action, ENT_QUOTES));
+ $s = sprintf('<input type="hidden" name="action_%s" value="true" />', htmlspecialchars($action, ENT_QUOTES));
} else if ($type == "url") {
$s = sprintf('action_%s=true', urlencode($action));
}
{
return str_replace('_', '/', $forward_name) . '.' . $this->ext['tpl'];
}
-
+
/**
* テンプレートパス名から遷移名を取得する
*
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);
* (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)
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));
}
/**
// 引数のはじめの一文字目と、アンダーバー直後の
// 1文字を必ず大文字にする。アンダーバーは削除される。
$name = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name));
-
+
// $name に foo_bar を渡し、AppID が Hogeの場合
// [Appid]_FooBar が返される
return sprintf('%s_%s', $this->getAppId(), $name);
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'])) {
/**
* DSNのアクセス分岐を行う
- *
+ *
* スレーブサーバへの振分け処理(デフォルト:ランダム)を変更したい場合はこのメソッドをオーバーライドする
*
* @access protected
list($usec, $sec) = explode(' ', microtime());
mt_srand($sec + ((float) $usec * 100000));
$n = mt_rand(0, count($dsn_list)-1);
-
+
return $dsn_list[$n];
}
}
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';
'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',
echo "<br>";
echo "In {$appid}-ini.php, please set as follows :<br><br>";
echo "\$config = array ( 'debug' => true, );";
- }
+ }
/**
* CLI実行中フラグを取得する
}
} else { // オプションとして解釈されない
- $nonparsed_arguments[] = $arg;
+
+ // non-parsed なオプションに辿り着いた
+ // ら、それ以降の解釈を停止する
+ // つまり、それ以降は全て値として解釈する
+ //
+ // これは POSIX_CORRECT な実装であって
+ // GNU Getopt な実装ではないが、実際に
+ // Console_Getopt で行われている以上、
+ // それに従った実装
+ $nonparsed_arguments = array_slice($args, $pos);
+ break;
}
}
* 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);
}
// }}}
return $r;
}
- $basedir = sprintf("%s/%s", $basedir, $id);
-
// ディレクトリ作成
if (is_dir($basedir) == false) {
// confirm
// ロケール名がディレクトリに含まれていない場合は、
// ディレクトリがないためなのでそれを補正
$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
if (isset($opt_list['basedir'])) {
$basedir = realpath(end($opt_list['basedir']));
} else {
- $basedir = getcwd();
+ $basedir = sprintf("%s/%s", getcwd(), strtolower($app_id));
}
// skeldir
{
return <<<EOS
add new template to project:
- {$this->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;
}
function getUsage()
{
return <<<EOS
-ethna {$this->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;
}
}
--- /dev/null
+<?php
+// vim: foldmethod=marker
+/**
+ * Ethna_Plugin_Handle_Help.php
+ *
+ * @author Tomoyuki MARUTA <maru_cc@users.sourceforge.jp>
+ * @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 <ichii386@schweetheart.jp>
+ * @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 <<<EOS
+help:
+ {$this->id} [command_name]
+
+EOS;
+ }
+
+ /**
+ * @access public
+ */
+ function getUsage()
+ {
+ return <<<EOS
+ethna {$this->id} [command_name]
+EOS;
+ }
+}
+// }}}
+?>
= 'default';
}
+ // 動的フォームヘルパを呼ぶ
+ if (isset($params['ethna_action'])) {
+ $ethna_action = $params['ethna_action'];
+ $view =& $c->getView();
+ $view->addActionFormHelper($ethna_action, true);
+ }
+
// ここで返す値は出力されない
return '';
$action = $block_params['ethna_action'];
}
if ($action !== null) {
- $view->addActionFormHelper($action);
+ $view->addActionFormHelper($action, true);
}
// default
/** 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. */
*
* 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',
+ * ),
*/
);
*/
);
- /**
- * @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',
- */
- );
-
/**#@-*/
/**
{
return array('{$locale}', 'UTF-8', '{$client_enc}');
}
+
+ /**
+ * テンプレートエンジンのデフォルト状態を設定する
+ *
+ * @access protected
+ * @param object Ethna_Renderer レンダラオブジェクト
+ * @obsolete
+ */
+ function _setDefaultTemplateEngine(&$renderer)
+ {
+ }
}
?>
"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}にはスカラー値を入力して下さい"
"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以下にしてください。"
*/
/**
- * {$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
{
}
?>
<?php
-require_once '{$basedir}/app/{$project_id}_Controller.php';
+require_once dirname(__FILE__) . '/../app/{$project_id}_Controller.php';
{$project_id}_Controller::main('{$project_id}_Controller', 'index');
?>
<?php
-require_once '{$basedir}/app/{$project_id}_Controller.php';
+require_once dirname(__FILE__) . '/../app/{$project_id}_Controller.php';
{$project_id}_Controller::main('{$project_id}_Controller', array(
'__ethna_info__',
<?php
error_reporting(E_ALL);
-require_once '{$basedir}/app/{$project_id}_Controller.php';
+require_once dirname(__FILE__) . '/../app/{$project_id}_Controller.php';
{$project_id}_Controller::main('{$project_id}_Controller', array(
'__ethna_unittest__',
$parsed_arg = array_shift($r);
$this->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()
// 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));
$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]);
$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);
$nonparsed_arg = array_shift($r);
$this->assertEqual('hoge', $nonparsed_arg[0]);
+ $this->assertEqual('-fuga', $nonparsed_arg[1]);
}
function test_longopt_optional()
$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]);
}
// }}}
}
$id = 'add-project';
$options = array(
'-b',
- $this->basedir,
+ $this->basedir . '/' . $this->project_name,
'-s',
$this->skel_dir,
$this->project_name,
}
}
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();
* @author halt feits <halt.feits@gmail.com>
*/
-//error_reporting(E_ALL);
-
/**
* Ethna_ViewClassクラスのテストケース
*
--- /dev/null
+<?php
+// vim: foldmethod=marker
+/**
+ * Ethna_Plugin_Handle_AddTemplate_Test.php
+ *
+ * @author Yoshinari Takaoka <takaoka@beatcraft.com>
+ * @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));
+ }
+}
+// }}}
+
+?>
$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()
{
return;
}
}
+
+
}
// }}}
--- /dev/null
+<?php
+// vim: foldmethod=marker
+/**
+ * Ethna_Plugin_Handle_PearLocal_Test.php
+ *
+ * @author Yoshinari Takaoka <takaoka@beatcraft.com>
+ * @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));
+ }
+}
+// }}}
+
+?>
*/
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));
--- /dev/null
+<?php
+/**
+ * {$project_id}_Controller.php
+ *
+ * @author {$author}
+ * @package {$project_id}
+ * @version $Id$
+ */
+
+/** Application base directory */
+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'));
+
+
+/** including application library. */
+require_once ETHNA_INSTALL_BASE . '/Ethna.php';
+require_once '{$project_id}_Error.php';
+require_once '{$project_id}_ActionClass.php';
+require_once '{$project_id}_ActionForm.php';
+require_once '{$project_id}_ViewClass.php';
+
+/**
+ * {$project_id} application Controller definition.
+ *
+ * @author {$author}
+ * @access public
+ * @package {$project_id}
+ */
+class {$project_id}_Controller extends Ethna_Controller
+{
+ /**#@+
+ * @access private
+ */
+
+ /**
+ * @var string Application ID(appid)
+ */
+ var $appid = '{$application_id}';
+
+ /**
+ * @var array forward definition.
+ */
+ var $forward = array(
+ /*
+ * TODO: write forward definition here.
+ *
+ * Example:
+ *
+ * 'index' => 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}');
+ }
+}
+
+?>