2 // vim: foldmethod=marker
6 * @author Masaki Fujimoto <fujimoto@php.net>
7 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
13 define('FILTER_HW', 'numeric_zentohan,alphabet_zentohan,ltrim,rtrim,ntrim');
16 define('FILTER_FW', 'kana_hantozen,ntrim');
19 // {{{ Ethna_ActionForm
23 * @author Masaki Fujimoto <fujimoto@php.net>
27 class Ethna_ActionForm
33 /** @var array フォーム値定義(デフォルト) */
34 var $form_template = array();
36 /** @var array フォーム値定義 */
39 /** @var array フォーム値 */
40 var $form_vars = array();
42 /** @var array アプリケーション設定値 */
43 var $app_vars = array();
45 /** @var array アプリケーション設定値(自動エスケープなし) */
46 var $app_ne_vars = array();
48 /** @var object Ethna_Backend バックエンドオブジェクト */
51 /** @var object Ethna_ActionError アクションエラーオブジェクト */
54 /** @var object Ethna_ActionError アクションエラーオブジェクト(省略形) */
57 /** @var object Ethna_I18N i18nオブジェクト */
60 /** @var object Ethna_Logger ログオブジェクト */
63 /** @var object Ethna_Plugin プラグインオブジェクト */
66 /** @var array フォーム定義要素 */
67 var $def = array('name', 'required', 'max', 'min', 'regexp', 'mbregexp',
68 'custom', 'filter', 'form_type', 'type');
70 /** @var array フォーム定義のうち非プラグイン要素とみなすprefix */
71 var $def_noplugin = array('type', 'form', 'name', 'plugin', 'filter',
74 /** @var bool 追加検証強制フラグ */
75 var $force_validate_plus = false;
77 /** @var array アプリケーションオブジェクト(helper) */
78 var $helper_app_object = array();
80 /** @var array アプリケーションオブジェクト(helper)で利用しないフォーム名 */
81 var $helper_skip_form = array();
83 /** @var int フォーム配列で使用可能な深さの上限 */
84 var $max_form_deps = 10;
89 * Ethna_ActionFormクラスのコンストラクタ
92 * @param object Ethna_Controller &$controller controllerオブジェクト
94 function Ethna_ActionForm(&$controller)
96 $this->backend =& $controller->getBackend();
97 $this->action_error =& $controller->getActionError();
98 $this->ae =& $this->action_error;
99 $this->i18n =& $controller->getI18N();
100 $this->logger =& $controller->getLogger();
101 $this->plugin =& $controller->getPlugin();
103 if (isset($_SERVER['REQUEST_METHOD']) == false) {
108 $this->form_template = $this->_setFormTemplate($this->form_template);
110 // アプリケーションオブジェクト(helper)の生成
111 foreach ($this->helper_app_object as $key => $value) {
112 if (is_object($value)) {
115 $this->helper_app_object[$key] =& $this->_getHelperAppObject($key);
119 $this->_setFormDef_HelperObj();
120 $this->_setFormDef();
123 foreach ($this->form as $name => $value) {
124 foreach ($this->def as $k) {
125 if (isset($value[$k]) == false) {
126 $this->form[$name][$k] = null;
136 * @param string $name フォーム値の名称
137 * @return mixed フォーム値
141 return $this->_getVarsByFormName($this->form_vars, $name);
148 * @param string $name 取得するフォーム名(nullなら全ての定義を取得)
149 * @return array フォーム値定義
151 function getDef($name = null)
153 if (is_null($name)) {
157 if (array_key_exists($name, $this->form) == false) {
160 return $this->form[$name];
168 * @param string $name フォーム値の名称
169 * @return mixed フォーム値の表示名
171 function getName($name)
173 if (isset($this->form[$name]) == false) {
176 if (isset($this->form[$name]['name'])
177 && $this->form[$name]['name'] != null) {
178 return $this->form[$name]['name'];
181 // try message catalog
182 return $this->i18n->get($name);
189 * @param string $name フォーム名
190 * @return array キーの配列
192 function _getFormNameArray($name)
195 if (preg_match('/^.*\[[^\]]+\]$/', $name)) {
196 $buff = preg_replace('/\]\[/', '[', $name); // hoge[foo][bar] => hoge[foo[bar]
197 $buff = preg_replace('/\]/', "", $buff); // hoge][foo[bar] => hoge[foo[bar
198 $ret = explode('[', $buff); // hoge[foo[bar => array('hoge', 'foo', 'var')
207 * 配列の中からキーで指定された要素を取り出す
210 * @param array &$target 対象とする配列
211 * @param string $nane キー
212 * @return string 指定された要素
214 function _getVarsByFormName(&$target, $name)
216 $keys = $this->_getFormNameArray($name);
217 return $this->_getVarsByKeys($target, $keys);
221 * 配列の中にキーで指定された要素を登録する
222 * フォーム定義にキーがあるかどうかは無関係に登録します
225 * @param array &$target 対象とする配列
226 * @param string $nane キー
227 * @param mixde $value 登録する値
229 function _setVarsByFormName(&$target, $name, $vars)
231 $keys = $this->_getFormNameArray($name);
232 $this->_setVarsByKeys($target, $keys, $vars);
236 * 配列の中からキーで指定された要素を取り出す
239 * @param array &$target 対象とする配列
240 * @param array $keys キーの配列
241 * @return string 指定された要素
243 function _getVarsByKeys(&$target, $keys)
245 $count = count($keys);
246 if ($count == 0) { // 探索完了
248 } elseif ($this->max_form_deps + 1 <= $count) { // 深すぎる配列を制限する
253 $curval = array_shift($keys);
254 if (is_array($target) && array_key_exists($curval, $target)) {
255 return $this->_getVarsByKeys($target[$curval], $keys);
260 function _setVarsByKeys(&$target, $keys, &$var)
262 $count = count($keys);
263 if ($count == 0) { // 探索完了
266 } elseif ($this->max_form_deps + 1 <= $count) { // 深すぎる配列を制限する
271 $curval = array_shift($keys);
272 if (is_array($target)) {
273 if (! array_key_exists($curval, $target)) {
274 $target[$curval] = null;
277 $target = array($curval => null);
280 $this->_setVarsByKeys($target[$curval], $keys, $var);
284 * $_FILESの中からキーで指定された要素を取り出す
287 * @param array &$target 対象とする配列
288 * @param string $nane キー
289 * @param string $key $_FILESに含まれる項目(tmp_name等)
290 * @return string 指定された要素
292 function _getFilesInfoByFormName(&$target, $name, $key)
294 $form_keys = $this->_getFormNameArray($name);
295 array_splice($form_keys, 1, 0, $key);
296 return $this->_getVarsByKeys($target, $form_keys);
300 * ユーザから送信されたフォーム値をフォーム値定義に従ってインポートする
304 function setFormVars()
306 if (isset($_SERVER['REQUEST_METHOD']) == false) {
308 } else if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0) {
309 $http_vars =& $_POST;
315 // ethna_fid というフォーム値は、フォーム定義に関わらず受け入れる
316 // これは、submitされたフォームを識別するために使われる
317 // null の場合は、以下の場合である
319 // 1. フォームヘルパが使われていない
320 // 2. 画面の初期表示などで、submitされなかった
321 // 3. {form name=...} が未設定である
323 $this->form_vars['ethna_fid'] = (isset($http_vars['ethna_fid']) == false
324 || is_null($http_vars['ethna_fid']))
326 : $http_vars['ethna_fid'];
328 foreach ($this->form as $name => $def) {
329 $type = is_array($def['type']) ? $def['type'][0] : $def['type'];
330 if ($type == VAR_TYPE_FILE) {
334 if (is_null($this->_getFilesInfoByFormName($_FILES, $name, 'tmp_name'))) {
335 $this->set($name, null);
340 if (is_array($def['type'])) {
341 if (is_array($this->_getFilesInfoByFormName($_FILES, $name, 'tmp_name')) == false) {
342 $this->handleError($name, E_FORM_WRONGTYPE_ARRAY);
343 $this->set($name, null);
347 if (is_array($this->_getFilesInfoByFormName($_FILES, $name, 'tmp_name'))) {
348 $this->handleError($name, E_FORM_WRONGTYPE_SCALAR);
349 $this->set($name, null);
355 if (is_array($def['type'])) {
358 foreach (array_keys($this->_getFilesInfoByFormName($_FILES, $name, 'name')) as $key) {
359 $files[$key] = array();
360 $files[$key]['name'] = $this->_getFilesInfoByFormName($_FILES, $name."[".$key."]", 'name');
361 $files[$key]['type'] = $this->_getFilesInfoByFormName($_FILES, $name."[".$key."]", 'type');
362 $files[$key]['size'] = $this->_getFilesInfoByFormName($_FILES, $name."[".$key."]", 'size');
363 $files[$key]['tmp_name'] = $this->_getFilesInfoByFormName($_FILES, $name."[".$key."]", 'tmp_name');
364 if ($this->_getFilesInfoByFormName($_FILES, $name."[".$key."]", 'error') == null) {
366 $files[$key]['error'] = 0;
368 $files[$key]['error'] = $this->_getFilesInfoByFormName($_FILES, $name."[".$key."]", 'error');
372 $files['name'] = $this->_getFilesInfoByFormName($_FILES, $name, 'name');
373 $files['type'] = $this->_getFilesInfoByFormName($_FILES, $name, 'type');
374 $files['size'] = $this->_getFilesInfoByFormName($_FILES, $name, 'size');
375 $files['tmp_name'] = $this->_getFilesInfoByFormName($_FILES, $name, 'tmp_name');
376 if ($this->_getFilesInfoByFormName($_FILES, $name, 'error') == null) {
380 $files['error'] = $this->_getFilesInfoByFormName($_FILES, $name, 'error');
385 $this->set($name, $files);
390 $target_var = $this->_getVarsByFormName($http_vars, $name);
393 if (isset($target_var) == false
394 || is_null($target_var)) {
395 $this->set($name, null);
396 if (isset($http_vars["{$name}_x"])
397 && isset($http_vars["{$name}_y"])) {
399 $this->set($name, $http_vars["{$name}_x"]);
405 if (is_array($def['type'])) {
406 if (is_array($target_var) == false) {
407 // 厳密には、この配列の各要素はスカラーであるべき
408 $this->handleError($name, E_FORM_WRONGTYPE_ARRAY);
409 $this->set($name, null);
413 if (is_array($target_var)) {
414 $this->handleError($name, E_FORM_WRONGTYPE_SCALAR);
415 $this->set($name, null);
421 $this->set($name, $target_var);
427 * ユーザから送信されたフォーム値をクリアする
431 function clearFormVars()
433 $this->form_vars = array();
440 * @param string $name フォーム値の名称
441 * @param string $value 設定する値
443 function set($name, $value)
445 $this->_setVarsByFormName($this->form_vars, $name, $value);
452 * @param string $name 設定するフォーム名(nullなら全ての定義を設定)
453 * @param array $value 設定するフォーム値定義
454 * @return array フォーム値定義
456 function setDef($name, $value)
458 if (is_null($name)) {
459 $this->form = $value;
462 $this->form[$name] = $value;
469 * @param bool $escape HTMLエスケープフラグ(true:エスケープする)
470 * @return array フォーム値を格納した配列
472 function &getArray($escape = true)
476 $this->_getArray($this->form_vars, $retval, $escape);
482 * アプリケーション設定値のアクセサ(R)
485 * @param string $name キー
486 * @return mixed アプリケーション設定値
488 function getApp($name)
490 if (isset($this->app_vars[$name]) == false) {
493 return $this->app_vars[$name];
497 * アプリケーション設定値のアクセサ(W)
500 * @param string $name キー
501 * @param mixed $value 値
503 function setApp($name, $value)
505 $this->app_vars[$name] = $value;
509 * アプリケーション設定値を配列にして返す
512 * @param boolean $escape HTMLエスケープフラグ(true:エスケープする)
513 * @return array フォーム値を格納した配列
515 function &getAppArray($escape = true)
519 $this->_getArray($this->app_vars, $retval, $escape);
525 * アプリケーション設定値(自動エスケープなし)のアクセサ(R)
528 * @param string $name キー
529 * @return mixed アプリケーション設定値
531 function getAppNE($name)
533 if (isset($this->app_ne_vars[$name]) == false) {
536 return $this->app_ne_vars[$name];
540 * アプリケーション設定値(自動エスケープなし)のアクセサ(W)
543 * @param string $name キー
544 * @param mixed $value 値
546 function setAppNE($name, $value)
548 $this->app_ne_vars[$name] = $value;
552 * アプリケーション設定値(自動エスケープなし)を配列にして返す
555 * @param boolean $escape HTMLエスケープフラグ(true:エスケープする)
556 * @return array フォーム値を格納した配列
558 function &getAppNEArray($escape = false)
562 $this->_getArray($this->app_ne_vars, $retval, $escape);
571 * @param array &$vars フォーム(等)の配列
572 * @param array &$retval 配列への変換結果
573 * @param bool $escape HTMLエスケープフラグ(true:エスケープする)
575 function _getArray(&$vars, &$retval, $escape)
577 foreach (array_keys($vars) as $name) {
578 if (is_array($vars[$name])) {
579 $retval[$name] = array();
580 $this->_getArray($vars[$name], $retval[$name], $escape);
582 $retval[$name] = $escape
583 ? htmlspecialchars($vars[$name], ENT_QUOTES) : $vars[$name];
590 * (通常検証でエラーが発生した場合でも_validatePlus()が呼び出される)
592 * @return bool true:追加検証強制 false:追加検証非強制
594 function isForceValidatePlus()
596 return $this->force_validate_plus;
603 * @param $force_validate_plus 追加検証強制フラグ
605 function setForceValidatePlus($force_validate_plus)
607 $this->force_validate_plus = $force_validate_plus;
614 * @return int 発生したエラーの数
618 foreach ($this->form as $name => $def) {
619 $this->_validateWithPlugin($name);
622 if ($this->ae->count() == 0 || $this->isForceValidatePlus()) {
624 $this->_validatePlus();
627 return $this->ae->count();
631 * プラグインを使ったフォーム値検証メソッド
634 * @param string $form_name フォームの名前
635 * @todo ae 側に $key を与えられるようにする
637 function _validateWithPlugin($form_name)
640 if ($this->form[$form_name]['type'] != VAR_TYPE_FILE) {
643 $form_var = $this->get($form_name);
644 $filter = (isset($this->form[$form_name]['filter']))
645 ? $this->form[$form_name]['filter']
649 if (is_array($this->form[$form_name]['type']) == false) {
650 $this->set($form_name, $this->_filter($form_var, $filter));
651 } else if ($form_var != null) { // 配列の場合
652 foreach (array_keys($form_var) as $key) {
653 $this->set($form_name."[".$key."]", $this->_filter($form_var[$key], $filter));
655 } else { // 配列で値が空の場合
656 $this->set($form_name, $this->_filter($form_var, $filter));
660 $form_vars = $this->get($form_name);
661 $plugin = $this->_getPluginDef($form_name);
663 // type のチェックを処理の最初に追加
664 $plugin = array_merge(array('type' => array()), $plugin);
665 if (is_array($this->form[$form_name]['type'])) {
666 $plugin['type']['type'] = $this->form[$form_name]['type'][0];
668 $plugin['type']['type'] = $this->form[$form_name]['type'];
670 if (isset($this->form[$form_name]['type_error'])) {
671 $plugin['type']['error'] = $this->form[$form_name]['type_error'];
675 if (is_array($this->form[$form_name]['type']) == false) {
676 foreach (array_keys($plugin) as $name) {
677 // break: 明示されていなければ,エラーが起きたらvalidateを継続しない
678 $break = isset($plugin[$name]['break']) == false
679 || $plugin[$name]['break'];
683 $v =& $this->plugin->getPlugin('Validator',
684 ucfirst(strtolower($name)));
685 if (Ethna::isError($v)) {
691 $r =& $v->validate($form_name, $form_vars, $plugin[$name]);
695 if (Ethna::isError($r)) {
696 $this->ae->addObject($form_name, $r);
708 // break 指示用の key list
709 $valid_keys = is_array($form_vars) ? array_keys($form_vars) : array();
711 foreach (array_keys($plugin) as $name) {
712 // break: 明示されていなければ,エラーが起きたらvalidateを継続しない
713 $break = isset($plugin[$name]['break']) == false
714 || $plugin[$name]['break'];
718 $v =& $this->plugin->getPlugin('Validator', ucfirst(strtolower($name)));
719 if (Ethna::isError($v)) {
724 if (isset($v->accept_array) && $v->accept_array == true) {
727 $r =& $v->validate($form_name, $form_vars, $plugin[$name]);
730 if (Ethna::isError($r)) {
731 $this->ae->addObject($form_name, $r);
740 foreach ($valid_keys as $key) {
743 $r =& $v->validate($form_name, $form_vars[$key], $plugin[$name]);
746 if (Ethna::isError($r)) {
747 $this->ae->addObject($form_name, $r);
749 unset($valid_keys[$key]);
760 * @param string $name フォーム項目名
761 * @return array チェック対象のフォーム値(エラーが無い場合はnull)
763 function check($name)
765 if (is_null($this->get($name)) || $this->get($name) === "") {
770 $c =& Ethna_Controller::getInstance();
771 $this->backend =& $c->getBackend();
773 return to_array($this->get($name));
780 * @param string $name フォーム項目名
781 * @return object Ethna_Error エラーオブジェクト(エラーが無い場合はnull)
783 function &checkVendorChar($name)
786 $string = $this->get($name);
788 for ($i = 0; $i < strlen($string); $i++) {
790 $c = ord($string{$i});
793 } else if ($c == 0x8e) {
796 } else if ($c == 0x8f) {
799 } else if ($c == 0xad || ($c >= 0xf9 && $c <= 0xfc)) {
800 /* IBM拡張文字 / NEC選定IBM拡張文字 */
801 return $this->ae->add($name,
802 _et('{form} contains machine dependent code.'), E_FORM_INVALIDCHAR);
815 * @param string $name フォーム項目名
816 * @return object Ethna_Error エラーオブジェクト(エラーが無い場合はnull)
818 function &checkBoolean($name)
821 $form_vars = $this->check($name);
823 if ($form_vars == null) {
827 foreach ($form_vars as $v) {
831 if ($v != "0" && $v != "1") {
832 return $this->ae->add($name,
833 _et('Please input {form} properly.'), E_FORM_INVALIDCHAR);
844 * @param string $name フォーム項目名
845 * @return object Ethna_Error エラーオブジェクト(エラーが無い場合はnull)
847 function &checkMailaddress($name)
850 $form_vars = $this->check($name);
852 if ($form_vars == null) {
856 foreach ($form_vars as $v) {
860 if (Ethna_Util::checkMailaddress($v) == false) {
861 return $this->ae->add($name,
862 _et('Please input {form} properly.'), E_FORM_INVALIDCHAR);
873 * @param string $name フォーム項目名
874 * @return object Ethna_Error エラーオブジェクト(エラーが無い場合はnull)
876 function &checkURL($name)
879 $form_vars = $this->check($name);
881 if ($form_vars == null) {
885 foreach ($form_vars as $v) {
889 if (preg_match('/^(http:\/\/|https:\/\/|ftp:\/\/)/', $v) == 0) {
890 return $this->ae->add($name,
891 _et('Please input {form} properly.'), E_FORM_INVALIDCHAR);
899 * フォーム値をhiddenタグとして返す
902 * @param array $include_list 配列が指定された場合、その配列に含まれるフォーム項目のみが対象となる
903 * @param array $exclude_list 配列が指定された場合、その配列に含まれないフォーム項目のみが対象となる
904 * @return string hiddenタグとして記述されたHTML
906 function getHiddenVars($include_list = null, $exclude_list = null)
909 foreach ($this->form as $key => $value) {
910 if (is_array($include_list) == true
911 && in_array($key, $include_list) == false) {
914 if (is_array($exclude_list) == true
915 && in_array($key, $exclude_list) == true) {
919 $type = is_array($value['type']) ? $value['type'][0] : $value['type'];
920 if ($type == VAR_TYPE_FILE) {
924 $form_value = $this->get($key);
925 if (is_array($value['type'])) {
930 if (is_array($form_value) == false) {
931 $form_value = array($form_value);
934 // フォーム定義がスカラーなのに配列が渡ってきた
935 // 場合は救いようがないのでNOTICE扱いとし、タグも出力しない
936 if (is_array($form_value)) {
937 $this->handleError($key, E_FORM_WRONGTYPE_ARRAY);
940 $form_value = array($form_value);
944 if (is_null($this->get($key))) {
945 // フォーム値が送られていない場合はそもそもhiddenタグを出力しない
949 foreach ($form_value as $k => $v) {
951 $form_name = "$key" . "[$k]";
956 sprintf("<input type=\"hidden\" name=\"%s\" value=\"%s\" />\n",
957 $form_name, htmlspecialchars($v, ENT_QUOTES));
967 * @param string $name フォーム項目名
968 * @param int $code エラーコード
970 function handleError($name, $code)
972 $def = $this->getDef($name);
976 E_FORM_REQUIRED => 'required_error',
977 E_FORM_WRONGTYPE_SCALAR => 'type_error',
978 E_FORM_WRONGTYPE_ARRAY => 'type_error',
979 E_FORM_WRONGTYPE_INT => 'type_error',
980 E_FORM_WRONGTYPE_FLOAT => 'type_error',
981 E_FORM_WRONGTYPE_DATETIME => 'type_error',
982 E_FORM_WRONGTYPE_BOOLEAN => 'type_error',
983 E_FORM_MIN_INT => 'min_error',
984 E_FORM_MIN_FLOAT => 'min_error',
985 E_FORM_MIN_DATETIME => 'min_error',
986 E_FORM_MIN_FILE => 'min_error',
987 E_FORM_MIN_STRING => 'min_error',
988 E_FORM_MAX_INT => 'max_error',
989 E_FORM_MAX_FLOAT => 'max_error',
990 E_FORM_MAX_DATETIME => 'max_error',
991 E_FORM_MAX_FILE => 'max_error',
992 E_FORM_MAX_STRING => 'max_error',
993 E_FORM_REGEXP => 'regexp_error',
995 // フォーム定義にエラーメッセージが定義されていれば
997 if (array_key_exists($code_map[$code], $def)) {
998 $this->ae->add($name, $def[$code_map[$code]], $code);
1002 // 定義されていない場合は、内部のメッセージを使う
1003 if ($code == E_FORM_REQUIRED) {
1004 switch ($def['form_type']) {
1005 case FORM_TYPE_TEXT:
1006 case FORM_TYPE_PASSWORD:
1007 case FORM_TYPE_TEXTAREA:
1008 case FORM_TYPE_SUBMIT:
1009 $message = _et('Please input {form}.');
1011 case FORM_TYPE_SELECT:
1012 case FORM_TYPE_RADIO:
1013 case FORM_TYPE_CHECKBOX:
1014 case FORM_TYPE_FILE:
1015 $message = _et('Please select {form}.');
1018 $message = _et('Please input {form}.');
1021 } else if ($code == E_FORM_WRONGTYPE_SCALAR) {
1022 $message = _et('Please input scalar value to {form}.');
1023 } else if ($code == E_FORM_WRONGTYPE_ARRAY) {
1024 $message = _et('Please input array value to {form}.');
1025 } else if ($code == E_FORM_WRONGTYPE_INT) {
1026 $message = _et('Please input integer value to {form}.');
1027 } else if ($code == E_FORM_WRONGTYPE_FLOAT) {
1028 $message = _et('Please input float value to {form}.');
1029 } else if ($code == E_FORM_WRONGTYPE_DATETIME) {
1030 $message = _et('Please input valid datetime to {form}.');
1031 } else if ($code == E_FORM_WRONGTYPE_BOOLEAN) {
1032 $message = _et('You can input 0 or 1 to {form}.');
1033 } else if ($code == E_FORM_MIN_INT) {
1034 $this->ae->add($name,
1035 _et('Please input more than %d(int) to {form}.'),
1036 $code, $def['min']);
1038 } else if ($code == E_FORM_MIN_FLOAT) {
1039 $this->ae->add($name,
1040 _et('Please input more than %f(float) to {form}.'),
1041 $code, $def['min']);
1043 } else if ($code == E_FORM_MIN_DATETIME) {
1044 $this->ae->add($name,
1045 _et('Please input datetime value %s or later to {form}.'),
1046 $code, $def['min']);
1048 } else if ($code == E_FORM_MIN_FILE) {
1049 $this->ae->add($name,
1050 _et('Please specify file whose size is more than %d KB.'),
1051 $code, $def['min']);
1053 } else if ($code == E_FORM_MIN_STRING) {
1054 $this->ae->add($name,
1055 _et('Please input more than %d full-size (%d half-size) characters to {form}.'),
1056 $code, intval($def['min']/2), $def['min']);
1058 } else if ($code == E_FORM_MAX_INT) {
1059 $this->ae->add($name,
1060 _et('Please input less than %d(int) to {form}.'),
1061 $code, $def['max']);
1063 } else if ($code == E_FORM_MAX_FLOAT) {
1064 $this->ae->add($name,
1065 _et('Please input less than %f(float) to {form}.'),
1066 $code, $def['max']);
1068 } else if ($code == E_FORM_MAX_DATETIME) {
1069 $this->ae->add($name,
1070 _et('Please input datetime value before %s to {form}.'),
1071 $code, $def['max']);
1073 } else if ($code == E_FORM_MAX_FILE) {
1074 $this->ae->add($name,
1075 _et('Please specify file whose size is less than %d KB to {form}.'),
1076 $code, $def['max']);
1078 } else if ($code == E_FORM_MAX_STRING) {
1079 $this->ae->add($name,
1080 _et('Please input less than %d full-size (%d half-size) characters to {form}.'),
1081 $code, intval($def['max']/2), $def['max']);
1083 } else if ($code == E_FORM_REGEXP) {
1084 $message = _et('Please input {form} properly.');
1087 $this->ae->add($name, $message, $code);
1091 * ユーザ定義検証メソッド(フォーム値間の連携チェック等)
1095 function _validatePlus()
1103 * @param string $method_list カスタムメソッド名(カンマ区切り)
1104 * @param string $name フォーム項目名
1106 function _validateCustom($method_list, $name)
1108 $method_list = preg_split('/\s*,\s*/', $method_list,
1109 -1, PREG_SPLIT_NO_EMPTY);
1110 if (is_array($method_list) == false) {
1113 foreach ($method_list as $method) {
1114 $this->$method($name);
1122 * @param mixed $value フォーム値
1123 * @param int $filter フィルタ定義
1124 * @return mixed 変換結果
1126 function _filter($value, $filter)
1128 if (is_null($filter)) {
1132 foreach (preg_split('/\s*,\s*/', $filter) as $f) {
1133 $method = sprintf('_filter_%s', $f);
1134 if (method_exists($this, $method) == false) {
1135 $this->logger->log(LOG_WARNING,
1136 'filter method is not defined [%s]', $method);
1139 $value = $this->$method($value);
1146 * フォーム値変換フィルタ: 全角英数字->半角英数字
1149 * @param mixed $value フォーム値
1150 * @return mixed 変換結果
1152 function _filter_alnum_zentohan($value)
1154 return mb_convert_kana($value, "a");
1158 * フォーム値変換フィルタ: 全角数字->半角数字
1161 * @param mixed $value フォーム値
1162 * @return mixed 変換結果
1164 function _filter_numeric_zentohan($value)
1166 return mb_convert_kana($value, "n");
1170 * フォーム値変換フィルタ: 全角英字->半角英字
1173 * @param mixed $value フォーム値
1174 * @return mixed 変換結果
1176 function _filter_alphabet_zentohan($value)
1178 return mb_convert_kana($value, "r");
1182 * フォーム値変換フィルタ: 左空白削除
1185 * @param mixed $value フォーム値
1186 * @return mixed 変換結果
1188 function _filter_ltrim($value)
1190 return ltrim($value);
1194 * フォーム値変換フィルタ: 右空白削除
1197 * @param mixed $value フォーム値
1198 * @return mixed 変換結果
1200 function _filter_rtrim($value)
1202 return rtrim($value);
1206 * フォーム値変換フィルタ: NULL(0x00)削除
1209 * @param mixed $value フォーム値
1210 * @return mixed 変換結果
1212 function _filter_ntrim($value)
1214 return str_replace("\x00", "", $value);
1218 * フォーム値変換フィルタ: 半角カナ->全角カナ
1221 * @param mixed $value フォーム値
1222 * @return mixed 変換結果
1224 function _filter_kana_hantozen($value)
1226 return mb_convert_kana($value, "K");
1230 * フォーム値定義テンプレートを設定する
1233 * @param array $form_template フォーム値テンプレート
1234 * @return array フォーム値テンプレート
1236 function _setFormTemplate($form_template)
1238 return $form_template;
1242 * ユーザが動的にフォーム定義を変更したい場合に
1243 * このメソッドをオーバーライドします。
1244 * $this->backend も初期化済みのため、DBやセッション
1245 * の値に基づいてフォーム定義を変更することができます。
1249 function setFormDef_PreHelper()
1251 // TODO: override this method.
1255 * ヘルパオブジェクト(アプリケーションオブジェクト)
1260 function _setFormDef_HelperObj()
1262 foreach (array_keys($this->helper_app_object) as $key) {
1263 $object =& $this->helper_app_object[$key];
1264 $prop_def = $object->getDef();
1266 foreach ($prop_def as $key => $value) {
1267 // 1. override form_template
1268 $form_key = isset($value['form_name']) ? $value['form_name'] : $key;
1270 if (isset($this->form_template[$form_key]) == false) {
1271 $this->form_template[$form_key] = array();
1274 $this->form_template[$form_key]['type'] = $value['type'];
1275 if (isset($value['required'])) {
1276 $this->form_template[$form_key]['required'] = $value['required'];
1279 if ($value['type'] == VAR_TYPE_STRING && isset($value['length'])) {
1280 $this->form_template[$form_key]['max'] = $value['length'];
1283 // 2. then activate form
1284 if (in_array($key, $this->helper_skip_form) == false) {
1285 if (isset($this->form[$key]) == false) {
1286 $this->form[$key] = array();
1298 function _setFormDef()
1300 foreach ($this->form as $key => $value) {
1301 if (is_numeric($key)) {
1302 $this->form[$value] = array();
1303 unset($this->form[$key]);
1307 foreach ($this->form as $key => $value) {
1308 if (array_key_exists($key, $this->form_template)
1309 && is_array($this->form_template)) {
1310 foreach ($this->form_template[$key] as $def_key => $def_value) {
1311 if (array_key_exists($def_key, $value) == false) {
1312 $this->form[$key][$def_key] = $def_value;
1320 * フォーム値定義からプラグインの定義リストを分離する
1323 * @param string $form_name プラグインの定義リストを取得するフォームの名前
1325 function _getPluginDef($form_name)
1328 // 'name' => 'number',
1330 // 'max_error' => 'too large!',
1332 // 'min_error' => 'too small!',
1335 // as plugin parameters:
1337 // $plugin_def = array(
1338 // 'max' => array('max' => 10, 'error' => 'too large!'),
1339 // 'min' => array('min' => 5, 'error' => 'too small!'),
1342 $def = $this->getDef($form_name);
1344 foreach (array_keys($def) as $key) {
1346 if ($def[$key] === null) {
1351 $snippet = explode('_', $key, 2);
1352 $name = $snippet[0];
1355 if (in_array($name, $this->def_noplugin)) {
1359 if (count($snippet) == 1) {
1361 if (is_array($def[$key])) {
1362 // プラグインパラメータがあらかじめ配列で指定されている(とみなす)
1365 $tmp = array($name => $def[$key]);
1369 $tmp = array($snippet[1] => $def[$key]);
1373 if (isset($plugin[$name]) == false) {
1374 $plugin[$name] = array();
1376 $plugin[$name] = array_merge($plugin[$name], $tmp);
1383 * アプリケーションオブジェクト(helper)を生成する
1387 function &_getHelperAppObject($key)
1389 $app_object =& $this->backend->getObject($key);