Source for file Ethna_ActionForm.php
Documentation is available at Ethna_ActionForm.php
// vim: foldmethod=marker
* @author Masaki Fujimoto <fujimoto@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php The BSD License
define('FILTER_HW', 'numeric_zentohan,alphabet_zentohan,ltrim,rtrim,ntrim');
define('FILTER_FW', 'kana_hantozen,ntrim');
* @author Masaki Fujimoto <fujimoto@php.net>
/** @var array フォーム値定義(デフォルト) */
var $form_template =
array();
/** @var array フォーム値定義 */
var $form_vars =
array();
/** @var array アプリケーション設定値 */
/** @var array アプリケーション設定値(自動エスケープなし) */
var $app_ne_vars =
array();
/** @var object Ethna_Backend バックエンドオブジェクト */
/** @var object Ethna_ActionError アクションエラーオブジェクト */
/** @var object Ethna_ActionError アクションエラーオブジェクト(省略形) */
/** @var object Ethna_I18N i18nオブジェクト */
/** @var object Ethna_Logger ログオブジェクト */
/** @var object Ethna_Plugin プラグインオブジェクト */
/** @var array フォーム定義要素 */
var $def =
array('name', 'required', 'max', 'min', 'regexp', 'mbregexp',
'custom', 'filter', 'form_type', 'type');
/** @var array フォーム定義のうち非プラグイン要素とみなすprefix */
var $def_noplugin =
array('type', 'form', 'name', 'plugin', 'filter',
/** @var bool 追加検証強制フラグ */
var $force_validate_plus =
false;
/** @var array アプリケーションオブジェクト(helper) */
var $helper_app_object =
array();
/** @var array アプリケーションオブジェクト(helper)で利用しないフォーム名 */
var $helper_skip_form =
array();
/** @var int フォーム配列で使用可能な深さの上限 */
* Ethna_ActionFormクラスのコンストラクタ
* @param object Ethna_Controller &$controller controllerオブジェクト
$this->backend =
& $controller->getBackend();
$this->action_error =
& $controller->getActionError();
$this->ae =
& $this->action_error;
$this->i18n =
& $controller->getI18N();
$this->logger =
& $controller->getLogger();
$this->plugin =
& $controller->getPlugin();
if (isset
($_SERVER['REQUEST_METHOD']) ==
false) {
// アプリケーションオブジェクト(helper)の生成
foreach ($this->helper_app_object as $key =>
$value) {
foreach ($this->form as $name =>
$value) {
foreach ($this->def as $k) {
if (isset
($value[$k]) ==
false) {
$this->form[$name][$k] =
null;
* @param string $name フォーム値の名称
return $this->_getVarsByFormName($this->form_vars, $name);
* @param string $name 取得するフォーム名(nullなら全ての定義を取得)
return $this->form[$name];
* @param string $name フォーム値の名称
* @return mixed フォーム値の表示名
if (isset
($this->form[$name]) ==
false) {
if (isset
($this->form[$name]['name'])
&&
$this->form[$name]['name'] !=
null) {
return $this->form[$name]['name'];
return $this->i18n->get($name);
* @param string $name フォーム名
function _getFormNameArray($name)
$buff =
preg_replace('/\]\[/', '[', $name); // hoge[foo][bar] => hoge[foo[bar]
$buff =
preg_replace('/\]/', "", $buff); // hoge][foo[bar] => hoge[foo[bar
$ret =
explode('[', $buff); // hoge[foo[bar => array('hoge', 'foo', 'var')
* @param array &$target 対象とする配列
function _getVarsByFormName(&$target, $name)
$keys =
$this->_getFormNameArray($name);
return $this->_getVarsByKeys($target, $keys);
* フォーム定義にキーがあるかどうかは無関係に登録します
* @param array &$target 対象とする配列
* @param mixde $value 登録する値
function _setVarsByFormName(&$target, $name, $vars)
$keys =
$this->_getFormNameArray($name);
* @param array &$target 対象とする配列
* @param array $keys キーの配列
function _getVarsByKeys(&$target, $keys)
if ($count ==
0) { // 探索完了
} elseif ($this->max_form_deps +
1 <=
$count) { // 深すぎる配列を制限する
return $this->_getVarsByKeys($target[$curval], $keys);
if ($count ==
0) { // 探索完了
} elseif ($this->max_form_deps +
1 <=
$count) { // 深すぎる配列を制限する
$target =
array($curval =>
null);
* $_FILESの中からキーで指定された要素を取り出す
* @param array &$target 対象とする配列
* @param string $key $_FILESに含まれる項目(tmp_name等)
function _getFilesInfoByFormName(&$target, $name, $key)
$form_keys =
$this->_getFormNameArray($name);
return $this->_getVarsByKeys($target, $form_keys);
* ユーザから送信されたフォーム値をフォーム値定義に従ってインポートする
if (isset
($_SERVER['REQUEST_METHOD']) ==
false) {
} else if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') ==
0) {
// ethna_fid というフォーム値は、フォーム定義に関わらず受け入れる
// これは、submitされたフォームを識別するために使われる
// 2. 画面の初期表示などで、submitされなかった
// 3. {form name=...} が未設定である
$this->form_vars['ethna_fid'] =
(isset
($http_vars['ethna_fid']) ==
false
||
is_null($http_vars['ethna_fid']))
:
$http_vars['ethna_fid'];
foreach ($this->form as $name =>
$def) {
$type =
is_array($def['type']) ?
$def['type'][0] :
$def['type'];
if (is_null($this->_getFilesInfoByFormName($_FILES, $name, 'tmp_name'))) {
if (is_array($this->_getFilesInfoByFormName($_FILES, $name, 'tmp_name')) ==
false) {
if (is_array($this->_getFilesInfoByFormName($_FILES, $name, 'tmp_name'))) {
foreach (array_keys($this->_getFilesInfoByFormName($_FILES, $name, 'name')) as $key) {
$files[$key]['name'] =
$this->_getFilesInfoByFormName($_FILES, $name.
"[".
$key.
"]", 'name');
$files[$key]['type'] =
$this->_getFilesInfoByFormName($_FILES, $name.
"[".
$key.
"]", 'type');
$files[$key]['size'] =
$this->_getFilesInfoByFormName($_FILES, $name.
"[".
$key.
"]", 'size');
$files[$key]['tmp_name'] =
$this->_getFilesInfoByFormName($_FILES, $name.
"[".
$key.
"]", 'tmp_name');
if ($this->_getFilesInfoByFormName($_FILES, $name.
"[".
$key.
"]", 'error') ==
null) {
$files[$key]['error'] =
0;
$files[$key]['error'] =
$this->_getFilesInfoByFormName($_FILES, $name.
"[".
$key.
"]", 'error');
$files['name'] =
$this->_getFilesInfoByFormName($_FILES, $name, 'name');
$files['type'] =
$this->_getFilesInfoByFormName($_FILES, $name, 'type');
$files['size'] =
$this->_getFilesInfoByFormName($_FILES, $name, 'size');
$files['tmp_name'] =
$this->_getFilesInfoByFormName($_FILES, $name, 'tmp_name');
if ($this->_getFilesInfoByFormName($_FILES, $name, 'error') ==
null) {
$files['error'] =
$this->_getFilesInfoByFormName($_FILES, $name, 'error');
$this->set($name, $files);
$target_var =
$this->_getVarsByFormName($http_vars, $name);
if (isset
($target_var) ==
false
if (isset
($http_vars["{
$name}_x"])
&& isset
($http_vars["{
$name}_y"])) {
$this->set($name, $http_vars["{
$name}_x"]);
// 厳密には、この配列の各要素はスカラーであるべき
$this->set($name, $target_var);
$this->form_vars =
array();
* @param string $name フォーム値の名称
* @param string $value 設定する値
function set($name, $value)
$this->_setVarsByFormName($this->form_vars, $name, $value);
* @param string $name 設定するフォーム名(nullなら全ての定義を設定)
* @param array $value 設定するフォーム値定義
function setDef($name, $value)
$this->form[$name] =
$value;
* @param bool $escape HTMLエスケープフラグ(true:エスケープする)
* @return array フォーム値を格納した配列
$this->_getArray($this->form_vars, $retval, $escape);
* @return mixed アプリケーション設定値
if (isset
($this->app_vars[$name]) ==
false) {
return $this->app_vars[$name];
function setApp($name, $value)
$this->app_vars[$name] =
$value;
* @param boolean $escape HTMLエスケープフラグ(true:エスケープする)
* @return array フォーム値を格納した配列
$this->_getArray($this->app_vars, $retval, $escape);
* アプリケーション設定値(自動エスケープなし)のアクセサ(R)
* @return mixed アプリケーション設定値
if (isset
($this->app_ne_vars[$name]) ==
false) {
return $this->app_ne_vars[$name];
* アプリケーション設定値(自動エスケープなし)のアクセサ(W)
$this->app_ne_vars[$name] =
$value;
* アプリケーション設定値(自動エスケープなし)を配列にして返す
* @param boolean $escape HTMLエスケープフラグ(true:エスケープする)
* @return array フォーム値を格納した配列
$this->_getArray($this->app_ne_vars, $retval, $escape);
* @param array &$vars フォーム(等)の配列
* @param array &$retval 配列への変換結果
* @param bool $escape HTMLエスケープフラグ(true:エスケープする)
function _getArray(&$vars, &$retval, $escape)
$retval[$name] =
array();
$this->_getArray($vars[$name], $retval[$name], $escape);
* (通常検証でエラーが発生した場合でも_validatePlus()が呼び出される)
* @return bool true:追加検証強制 false:追加検証非強制
return $this->force_validate_plus;
* @param $force_validate_plus 追加検証強制フラグ
$this->force_validate_plus =
$force_validate_plus;
foreach ($this->form as $name =>
$def) {
$this->_validateWithPlugin($name);
return $this->ae->count();
* @param string $form_name フォームの名前
* @todo ae 側に $key を与えられるようにする
function _validateWithPlugin($form_name)
$form_var =
$this->get($form_name);
$filter =
(isset
($this->form[$form_name]['filter']))
?
$this->form[$form_name]['filter']
if (is_array($this->form[$form_name]['type']) ==
false) {
$this->set($form_name, $this->_filter($form_var, $filter));
} else if ($form_var !=
null) { // 配列の場合
$this->set($form_name.
"[".
$key.
"]", $this->_filter($form_var[$key], $filter));
$this->set($form_name, $this->_filter($form_var, $filter));
$form_vars =
$this->get($form_name);
$plugin =
array_merge(array('type' =>
array()), $plugin);
if (is_array($this->form[$form_name]['type'])) {
$plugin['type']['type'] =
$this->form[$form_name]['type'][0];
$plugin['type']['type'] =
$this->form[$form_name]['type'];
if (isset
($this->form[$form_name]['type_error'])) {
$plugin['type']['error'] =
$this->form[$form_name]['type_error'];
if (is_array($this->form[$form_name]['type']) ==
false) {
// break: 明示されていなければ,エラーが起きたらvalidateを継続しない
$break = isset
($plugin[$name]['break']) ==
false
||
$plugin[$name]['break'];
$r =
& $v->validate($form_name, $form_vars, $plugin[$name]);
// break: 明示されていなければ,エラーが起きたらvalidateを継続しない
$break = isset
($plugin[$name]['break']) ==
false
||
$plugin[$name]['break'];
if (isset
($v->accept_array) &&
$v->accept_array ==
true) {
$r =
& $v->validate($form_name, $form_vars, $plugin[$name]);
foreach ($valid_keys as $key) {
$r =
& $v->validate($form_name, $form_vars[$key], $plugin[$name]);
unset
($valid_keys[$key]);
* @param string $name フォーム項目名
* @return array チェック対象のフォーム値(エラーが無い場合はnull)
$this->backend =
& $c->getBackend();
* @param string $name フォーム項目名
* @return object Ethna_Error エラーオブジェクト(エラーが無い場合はnull)
$string =
$this->get($name);
for ($i =
0; $i <
strlen($string); $i++
) {
} else if ($c ==
0xad ||
($c >=
0xf9 &&
$c <=
0xfc)) {
/* IBM拡張文字 / NEC選定IBM拡張文字 */
return $this->ae->add($name,
* @param string $name フォーム項目名
* @return object Ethna_Error エラーオブジェクト(エラーが無い場合はnull)
$form_vars =
$this->check($name);
if ($form_vars ==
null) {
foreach ($form_vars as $v) {
if ($v !=
"0" &&
$v !=
"1") {
return $this->ae->add($name,
* @param string $name フォーム項目名
* @return object Ethna_Error エラーオブジェクト(エラーが無い場合はnull)
$form_vars =
$this->check($name);
if ($form_vars ==
null) {
foreach ($form_vars as $v) {
return $this->ae->add($name,
* @param string $name フォーム項目名
* @return object Ethna_Error エラーオブジェクト(エラーが無い場合はnull)
$form_vars =
$this->check($name);
if ($form_vars ==
null) {
foreach ($form_vars as $v) {
if (preg_match('/^(http:\/\/|https:\/\/|ftp:\/\/)/', $v) ==
0) {
return $this->ae->add($name,
* @param array $include_list 配列が指定された場合、その配列に含まれるフォーム項目のみが対象となる
* @param array $exclude_list 配列が指定された場合、その配列に含まれないフォーム項目のみが対象となる
* @return string hiddenタグとして記述されたHTML
function getHiddenVars($include_list =
null, $exclude_list =
null)
foreach ($this->form as $key =>
$value) {
&&
in_array($key, $include_list) ==
false) {
&&
in_array($key, $exclude_list) ==
true) {
$type =
is_array($value['type']) ?
$value['type'][0] :
$value['type'];
$form_value =
$this->get($key);
$form_value =
array($form_value);
// フォーム定義がスカラーなのに配列が渡ってきた
// 場合は救いようがないのでNOTICE扱いとし、タグも出力しない
$form_value =
array($form_value);
// フォーム値が送られていない場合はそもそもhiddenタグを出力しない
foreach ($form_value as $k =>
$v) {
$form_name =
"$key" .
"[$k]";
sprintf("<input type=\"hidden\" name=\"%s\" value=\"%s\" />\n",
* @param string $name フォーム項目名
* @param int $code エラーコード
// フォーム定義にエラーメッセージが定義されていれば
$this->ae->add($name, $def[$code_map[$code]], $code);
// 定義されていない場合は、内部のメッセージを使う
switch ($def['form_type']) {
$message =
_et('Please input {form}.');
$message =
_et('Please select {form}.');
$message =
_et('Please input {form}.');
$message =
_et('Please input scalar value to {form}.');
$message =
_et('Please input array value to {form}.');
$message =
_et('Please input integer value to {form}.');
$message =
_et('Please input float value to {form}.');
$message =
_et('Please input valid datetime to {form}.');
$message =
_et('You can input 0 or 1 to {form}.');
_et('Please input more than %d(int) to {form}.'),
_et('Please input more than %f(float) to {form}.'),
_et('Please input datetime value %s or later to {form}.'),
_et('Please specify file whose size is more than %d KB.'),
_et('Please input more than %d full-size (%d half-size) characters to {form}.'),
$code, intval($def['min']/
2), $def['min']);
_et('Please input less than %d(int) to {form}.'),
_et('Please input less than %f(float) to {form}.'),
_et('Please input datetime value before %s to {form}.'),
_et('Please specify file whose size is less than %d KB to {form}.'),
_et('Please input less than %d full-size (%d half-size) characters to {form}.'),
$code, intval($def['max']/
2), $def['max']);
$message =
_et('Please input {form} properly.');
$this->ae->add($name, $message, $code);
* ユーザ定義検証メソッド(フォーム値間の連携チェック等)
* @param string $method_list カスタムメソッド名(カンマ区切り)
* @param string $name フォーム項目名
$method_list =
preg_split('/\s*,\s*/', $method_list,
-
1, PREG_SPLIT_NO_EMPTY);
foreach ($method_list as $method) {
* @param mixed $value フォーム値
* @param int $filter フィルタ定義
function _filter($value, $filter)
foreach (preg_split('/\s*,\s*/', $filter) as $f) {
$method =
sprintf('_filter_%s', $f);
$this->logger->log(LOG_WARNING,
'filter method is not defined [%s]', $method);
$value =
$this->$method($value);
* フォーム値変換フィルタ: 全角英数字->半角英数字
* @param mixed $value フォーム値
* フォーム値変換フィルタ: 全角数字->半角数字
* @param mixed $value フォーム値
* フォーム値変換フィルタ: 全角英字->半角英字
* @param mixed $value フォーム値
* @param mixed $value フォーム値
* @param mixed $value フォーム値
* フォーム値変換フィルタ: NULL(0x00)削除
* @param mixed $value フォーム値
* フォーム値変換フィルタ: 半角カナ->全角カナ
* @param mixed $value フォーム値
* @param array $form_template フォーム値テンプレート
* @return array フォーム値テンプレート
* Ethna_ActionForm#prepare() が実行される前に
* $this->backend も初期化済みのため、DBやセッション
* の値に基づいてフォーム定義を変更することができます。
// TODO: override this method.
* フォームヘルパを使うときに、フォーム定義を動的に
* 変更したい場合に、このメソッドをオーバーライドします。
* 以下の定義をテンプレートで行った場合に呼び出されます。
* {form ethna_action=...} (ethna_action がない場合は呼び出されません)
* {form_input action=...} (action がない場合は呼び出されません)
// TODO: デフォルト実装は Ethna_ActionClass#prepare 前に
// 呼び出されるものと同じ。異なる場合にオーバライドする
* ヘルパオブジェクト(アプリケーションオブジェクト)
foreach (array_keys($this->helper_app_object) as $key) {
$object =
& $this->helper_app_object[$key];
$prop_def =
$object->getDef();
foreach ($prop_def as $key =>
$value) {
// 1. override form_template
$form_key = isset
($value['form_name']) ?
$value['form_name'] :
$key;
if (isset
($this->form_template[$form_key]) ==
false) {
$this->form_template[$form_key] =
array();
$this->form_template[$form_key]['type'] =
$value['type'];
if (isset
($value['required'])) {
$this->form_template[$form_key]['required'] =
$value['required'];
$this->form_template[$form_key]['max'] =
$value['length'];
if (in_array($key, $this->helper_skip_form) ==
false) {
if (isset
($this->form[$key]) ==
false) {
$this->form[$key] =
array();
foreach ($this->form as $key =>
$value) {
$this->form[$value] =
array();
unset
($this->form[$key]);
foreach ($this->form as $key =>
$value) {
foreach ($this->form_template[$key] as $def_key =>
$def_value) {
$this->form[$key][$def_key] =
$def_value;
* フォーム値定義からプラグインの定義リストを分離する
* @param string $form_name プラグインの定義リストを取得するフォームの名前
// 'max_error' => 'too large!',
// 'min_error' => 'too small!',
// 'max' => array('max' => 10, 'error' => 'too large!'),
// 'min' => array('min' => 5, 'error' => 'too small!'),
$def =
$this->getDef($form_name);
if ($def[$key] ===
null) {
if (in_array($name, $this->def_noplugin)) {
if (count($snippet) ==
1) {
// プラグインパラメータがあらかじめ配列で指定されている(とみなす)
$tmp =
array($name =>
$def[$key]);
$tmp =
array($snippet[1] =>
$def[$key]);
if (isset
($plugin[$name]) ==
false) {
$plugin[$name] =
array();
* アプリケーションオブジェクト(helper)を生成する
$app_object =
& $this->backend->getObject($key);
Documentation generated on Fri, 11 Nov 2011 03:59:06 +0900 by phpDocumentor 1.4.3