Цитата (chee @ 31.01.2015 - 19:27) |
stump, за вас в оформлении кода уже все решили, вам осталось только использовать, гулите: PSR-0, PSR-2 |
class Validator
{
protected $handlersRules; //обрабочики правил
protected $rules; //переданные правила
protected $fields; //обрабатываемый массив данных
protected $process; //обработанные поля
protected $errors;
function __construct()
{
$this->handlersRules = array();
}
public function run(array $rules, array $fields)
{
$this->rules = $rules;
$this->fields = $fields;
$this->process = array();
$this->errors = array();
foreach ($rules as $name => $value) {
$this->processField($name);
}
return count($this->errors) ? false : $this->fields;
}
public function setHandler($name, Closure $handler)
{
$this->handlersRules[$name] = $handler;
}
public function getErrors()
{
return $this->errors;
}
protected function processField($fieldName)
{
//если для данного поля есть правила и оно еще не обрабатывалось
if(empty($this->process[$fieldName]) && isset($this->rules[$fieldName])){
$this->process[$fieldName] = true; //поле обрабатывается
$rules = $this->rules[$fieldName];
if (is_string($rules)) {
$rules = $this->parseRulesList($rules);
} elseif (!is_array($rules)) {
throw new Exception('Wrong rules format!');
}
foreach ($rules as $func => $params) {
$params = $this->mountSpecialParams($params, $fieldName);
$result = $this->performRule($func, $params);
//если функция обработки вернула boolean значит это функция проверки, иначе функция изменила значение
if (is_bool($result)) {
if ($result === false) {
$this->errors[$fieldName][$func] = $params;
}
} else $this->fields[$fieldName] = $result;
}
}
return $this->fields[$fieldName];
}
//приводим строковые правила к соответствующему массиву
protected function parseRulesList($rules)
{
$rules = explode('|', $rules);
$parsedRules = array();
foreach ($rules as $key => $rule) {
$rule = $this->parseRule($rule);
$parsedRules[$rule['func']] = $rule['params'];
}
return $parsedRules;
}
protected function parseRule($rule)
{
$params = array();
if (preg_match("/(.*?)\((.*)\)/", $rule, $match)) {
$rule = $match[1];
$params = array_map('trim', str_getcsv($match[2]));
}
return array(
'func' => $rule,
'params' => $params
);
}
//выполняем правило либо из обработчика, либо глобальную функцию или метод
protected function performRule($name, $params)
{
if (isset($this->handlersRules[$name])) {
$func = $this->handlersRules[$name];
} else {
$func = explode('->', $name);
if(count($func) == 1){
$func = $name;
}
if(!is_callable($func)){
throw new Exception('There is no such handler!');
}
}
return call_user_func_array($func, $params);
}
//заменяем параметры вида {name}, на предварительно обработанное значение с соответствующим именем из массива данных
protected function mountSpecialParams($params, $self)
{
$specialParams = preg_grep("/^\{.+\}$/", $params);
$hasSelf = false;
foreach ($specialParams as $key => $param) {
$param = trim(substr($param, 1, -1));
if($param == 'self' || $param == $self){
$param = $self;
$hasSelf = true;
}
$params[$key] = $this->processField($param);
}
if (!$hasSelf) {
array_unshift($params, $this->processField($self));
}
return $params;
}
}
$data = array(
'name' => ' Che Guevara ',
'password' => '123456',
'password_conf' => '123456'
);
$valid = new Validator();
$valid->setHandler('match', function($value, $match){
return $value === $match;
});
$valid->setHandler('str_range', function($str, $min, $max){
$length = strlen($str);
return $length >= $min && $length <= $max;
});
$rules = array(
'name' => 'trim|str_replace("Che Guevara", "Ernesto", {self})',
'password' => array(
'str_range' => array(6, 30),
'match' => array('{password_conf}'),
'md5' => array()
)
);
if ($result = $valid->run($rules, $data)) {
echo 'Валидация прошла успешно<br>';
echo 'Было:<br>';
echo '<pre>'.print_r($data,true).'</pre>';
echo 'Стало:<br>';
echo '<pre>'.print_r($result,true).'</pre>';
} else {
echo 'параметры не соответствуют правилам<br>';
echo 'Массив ошибок:<br>';
echo '<pre>'.print_r($valid->getErrors(),true).'</pre>';
}
Валидация прошла успешно
Было:
Array
(
[name] => Che Guevara
[password] => 123456
[password_conf] => 123456
)
Стало:
Array
(
[name] => Ernesto
[password] => e10adc3949ba59abbe56e057f20f883e
[password_conf] => 123456
)