80 $this->_rules = array();
81 $this->_filters = array();
82 $this->_xml_ruleset = NULL;
85 $this->
load($xml_path);
89 'email' =>
'/^[\w-]+((?:\.|\+|\~)[\w-]+)*@[\w-]+(\.[\w-]+)+$/',
90 'userid' =>
'/^[a-z]+[\w-]*[a-z0-9_]+$/i',
91 'url' =>
'/^(https?|ftp|mms):\/\/[0-9a-z-]+(\.[_0-9a-z-]+)+(:\d+)?/',
92 'alpha' =>
'/^[a-z]*$/i',
93 'alpha_number' =>
'/^[a-z][a-z0-9_]*$/i',
94 'number' =>
'/^(?:[1-9]\\d*|0)$/',
95 'float' =>
'/^\d+(\.\d+)?$/'
98 $this->_has_mb_func = is_callable(
'mb_strlen');
108 $this->_rules = NULL;
109 $this->_filters = NULL;
119 $this->_xml_ruleset = NULL;
121 $xml_path = realpath($xml_path);
122 if(!is_readable($xml_path))
128 $xml = $parser->loadXmlFile($xml_path);
129 if(!isset($xml->ruleset) || !isset($xml->ruleset->fields) || !isset($xml->ruleset->fields->field))
135 if(isset($xml->ruleset->customrules) && isset($xml->ruleset->customrules->rule))
137 $customrules = $xml->ruleset->customrules->rule;
138 if(!is_array($customrules))
140 $customrules = array($customrules);
145 foreach($customrules as $rule)
147 if(!isset($rule->attrs) || !isset($rule->attrs->name))
152 $message = $rule->message ? $rule->message->body : NULL;
153 $rule = (array) $rule->attrs;
154 $rule[
'message'] = $message;
155 $name = $rule[
'name'];
156 unset($rule[
'name']);
158 $rules[$name] = $rule;
161 $messages[
'invalid_' . $name] = $message;
171 $fields = $xml->ruleset->fields->field;
172 if(!is_array($fields))
174 $fields = array($fields);
178 $fieldsNames = array();
179 foreach($fields as $field)
184 if(!isset($field->attrs) || !isset($field->attrs->name))
189 $title = $field->title ? $field->title->body : NULL;
190 $filter = (array) $field->attrs;
191 $filter[
'title'] = $title;
193 $name = $filter[
'name'];
196 $fieldsNames[$name] = $title;
199 unset($filter[
'name']);
202 if(isset($field->if))
209 foreach($if as $idx => $cond)
211 $if[$idx] = (array) $cond->attrs;
216 $filters[$name] = $filter;
219 $this->_xml_ruleset = $xml->ruleset;
220 $this->_filters = $filters;
221 $this->_message = $messages;
222 $this->_fieldNames = $fieldsNames;
223 $this->_xml_path = $xml_path;
235 if(is_dir($cache_dir))
237 $this->_cache_dir = preg_replace(
'@/$@',
'', $cache_dir);
248 if(is_array($fields_))
254 $args = array_keys($this->_filters);
258 if(!is_array($fields))
263 $filter_default = array(
264 'required' =>
'false',
266 'modifiers' => array(),
273 $fields = array_map(array($this,
'arrayTrim'), $fields);
274 $field_names = array_keys($fields);
279 foreach($this->_filters as $key => $filter)
284 $names = preg_grep(
'/^' . preg_quote(substr($key, 1)) .
'/', $field_names);
286 elseif(substr($key, -2) ==
'[]')
288 $filters[substr($key, 0, -2)] = $filter;
289 unset($filters[$key]);
293 $filters[$key] = $filter;
301 foreach($names as $name)
303 $filters[$name] = $filter;
305 unset($filters[$key]);
308 foreach($filters as $key => $filter)
310 $fname = preg_replace(
'/\[\]$/',
'', $key);
311 $filter = array_merge($filter_default, $filter);
313 if(preg_match(
"/(^[a-z_]*)[\[](?:\'|\")?([a-z_]*)(?:\'|\")?[\]]$/i", $key, $matches))
315 $exists = array_key_exists($matches[1], $fields);
316 $value = $exists ? $fields[$matches[1]][$matches[2]] : NULL;
320 $exists = array_key_exists($key, $fields);
321 $value = $exists ? $fields[$fname] : NULL;
326 if(!isset($value[tmp_name]))
328 $value = implode(
'', $value);
332 $value = $value[
'name'];
337 foreach($filter[
'if'] as $cond)
339 if(!isset($cond[
'test']) || !isset($cond[
'attr']))
344 $func_body = preg_replace(
'/\\$(\w+)/',
'$c[\'$1\']', $cond[
'test']);
345 $func = create_function(
'$c',
"return !!({$func_body});");
349 $filter[$cond[
'attr']] = $cond[
'value'];
354 if(!$value && strlen($default = trim($filter[
'default'])))
357 if(is_null($fields_))
363 $fields_[$fname] = $value;
366 $value_len = strlen($value);
369 if(is_string($modifiers = $filter[
'modifiers']))
371 $modifiers = explode(
',', trim($modifiers));
375 if($filter[
'required'] ===
'true' && !$value_len)
377 return $this->
error($key,
'isnull');
381 if(!$exists && !$value_len)
387 if($length = $filter[
'length'])
389 list($min, $max) = explode(
':', trim($length));
390 $is_min_b = (substr($min, -1) ===
'b');
391 $is_max_b = (substr($max, -1) ===
'b');
392 list($min, $max) = array((
int) $min, (
int) $max);
394 $strbytes = strlen($value);
395 if(!$is_min_b || !$is_max_b)
397 $strlength = $this->_has_mb_func ? mb_strlen($value,
'utf-8') : $this->
mbStrLen($value);
400 if(($min && $min > ($is_min_b ? $strbytes : $strlength)) || ($max && $max < ($is_max_b ? $strbytes : $strlength)))
402 return $this->
error($key,
'outofrange');
407 if($equalto = $filter[
'equalto'])
409 if(!array_key_exists($equalto, $fields) || trim($fields[$equalto]) !== $value)
411 return $this->
error($key,
'equalto');
416 if($rules = $filter[
'rule'])
418 $rules = explode(
',', $rules);
419 foreach($rules as $rule)
421 $result = $this->
applyRule($rule, $value);
423 if(in_array(
'not', $modifiers))
429 return $this->
error($key,
'invalid_' . $rule);
445 if(!is_array($array))
450 foreach($array as $key => $value)
465 if(isset($this->_message[$msg]))
467 $msg = $this->_message[$msg];
472 $msg = isset($lang_filter->{$msg}) ? $lang_filter->{$msg} : $lang_filter->invalid;
475 if(isset($this->_fieldNames[$field]))
477 $fieldName = $this->_fieldNames[$field];
484 $msg = sprintf($msg, $fieldName);
486 $this->_last_error = array(
'field' => $field,
'msg' => $msg);
497 return $this->_last_error;
514 $args = array($name => $rule);
517 foreach(
$args as $name => $rule)
525 $rule = array(
'type' =>
'regex',
'test' => $rule);
528 if($rule[
'type'] ==
'enum')
530 $delim = isset($rule[
'delim']) ? $rule[
'delim'] :
',';
531 $rule[
'test'] = explode($delim, $rule[
'test']);
534 $this->_rules[$name] = $rule;
545 unset($this->_rules[$name]);
562 $args = array($name => $filter);
565 foreach(
$args as $name => $filter)
572 if(isset($filter[
'if']))
574 if(is_array($filter[
'if']) && count($filter[
'if']))
576 $key = key($filter[
'if']);
579 $filter[
'if'] = array($filter[
'if']);
584 unset($filter[
'if']);
588 $this->_filters[$name] = $filter;
599 unset($this->_filters[$name]);
610 $rule = $this->_rules[$name];
612 if(is_array($value) && isset($value[
'tmp_name']))
614 $value = $value[
'name'];
617 switch($rule[
'type'])
620 return (preg_match($rule[
'test'], $value) > 0);
622 return in_array($value, $rule[
'test']);
624 if(!$rule[
'func_test'])
626 $rule[
'func_test'] = create_function(
'$a',
'return (' . preg_replace(
'/\$\$/',
'$a', html_entity_decode($rule[
'test'])) .
');');
628 return $rule[
'func_test']($value);
641 $arr = count_chars($str);
642 for($i = 0x80; $i < 0xc0; $i++)
646 return array_sum($arr);
655 if(!$this->_cache_dir)
660 $dir = $this->_cache_dir .
'/ruleset';
661 if(!is_dir($dir) && !mkdir($dir))
665 if(!$this->_xml_path)
674 $filepath = $dir .
'/' . md5($this->_version .
' ' . $this->_xml_path) .
".{$lang_type}.js";
675 if(is_readable($filepath) && filemtime($filepath) > filemtime($this->_xml_path))
680 $content = $this->_compile2js();
681 if($content === FALSE)
699 $ruleset = basename($this->_xml_path,
'.xml');
702 if(preg_match(
'@(^|/)files/ruleset/\w+\.xml$@i', $this->_xml_path))
704 $ruleset =
'@' . $ruleset;
707 list($ruleset) = explode(
'.', $ruleset);
714 foreach($this->_rules as $name => $rule)
716 $name = strtolower($name);
718 if(in_array($name, array(
'email',
'userid',
'url',
'alpha',
'alpha_number',
'number',
'float')))
723 switch($rule[
'type'])
726 $addrules[] =
"v.cast('ADD_RULE', ['{$name}', {$rule['test']}]);";
729 $enums =
'"' . implode(
'","', $rule[
'test']) .
'"';
730 $addrules[] =
"v.cast('ADD_RULE', ['{$name}', function($$){ return ($.inArray($$,[{$enums}]) > -1); }]);";
733 $addrules[] =
"v.cast('ADD_RULE', ['{$name}', function($$){ return ({$rule['test']}); }]);";
738 if(isset($rule[
'message']))
740 $text = preg_replace(
'@\r?\n@',
'\\n', addslashes($rule[
'message']));
741 $addrules[] =
"v.cast('ADD_MESSAGE',['invalid_{$name}','{$text}']);";
744 $addrules = implode(
'', $addrules);
749 foreach($this->_filters as $name => $filter)
754 if(isset($filter[
'title']))
756 $field_lang = addslashes($filter[
'title']);
757 $messages[] =
"v.cast('ADD_MESSAGE',['{$name}','{$field_lang}']);";
759 elseif(isset($lang->{$name}))
761 $field_lang = addslashes($lang->{$name});
762 $messages[] =
"v.cast('ADD_MESSAGE',['{$name}','{$field_lang}']);";
765 if($filter[
'required'] ==
'true')
767 $field[] =
'required:true';
771 $field[] =
"rule:'" . strtolower($filter[
'rule']) .
"'";
773 if($filter[
'default'])
775 $field[] =
"default:'{$filter['default']}'";
777 if($filter[
'modifier'])
779 $field[] =
"modifier:'{$filter['modifier']}'";
781 if($filter[
'length'])
783 list($min, $max) = explode(
':', $filter[
'length']);
786 $field[] =
"minlength:'{$min}'";
790 $field[] =
"maxlength:'{$max}'";
796 if(!isset($filter[
'if'][0]))
798 $filter[
'if'] = array($filter[
'if']);
800 foreach($filter[
'if'] as $if)
802 $ifs[] =
"{test:'" . addslashes($if[
'test']) .
"', attr:'{$if['attr']}', value:'" . addslashes($if[
'value']) .
"'}";
804 $field[] =
"'if':[" . implode(
',', $ifs) .
"]";
808 $field =
'{' . implode(
',', $field) .
'}';
809 $content[] =
"'{$name}':{$field}";
815 return '/* Error : empty ruleset */';
819 foreach(
$lang->filter as $key => $text)
823 $text = preg_replace(
'@\r?\n@',
'\\n', addslashes($text));
824 $messages[] =
"v.cast('ADD_MESSAGE',['{$key}','{$text}']);";
828 $content = implode(
',', $content);
829 $messages = implode(
"\n", $messages);
831 return "(function($,v){\nv=xe.getApp('validator')[0];if(!v)return;\n{$addrules}\nv.cast('ADD_FILTER',['{$ruleset}', {{$content}}]);\n{$messages}\n})(jQuery);";
set($key, $val, $set_to_get_vars=0)
writeFile($filename, $buff, $mode="w")
__construct($xml_path= '')
addFilter($name, $filter= '')
addRule($name, $rule= '')
if(isset($_REQUEST['encode'])) if(isset($_REQUEST['decode'])) $lang