163 lines
4.9 KiB
PHP
163 lines
4.9 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Проверка коллекции
|
|
*/
|
|
namespace ctiso\Validator;
|
|
use Exception,
|
|
ctiso\Validator\Rule\AbstractRule,
|
|
ctiso\Collection;
|
|
|
|
/**
|
|
* @phpstan-type Rule array{
|
|
* validate:string, // Описание правила см. формат правила ниже
|
|
* name:string, // Имя переменой для проверки
|
|
* context?:object
|
|
* }
|
|
*/
|
|
class Validator
|
|
{
|
|
/** @var AbstractRule[] */
|
|
protected array $chain = []; // Массив правил
|
|
/** @var array<string, string> */
|
|
protected array $errorMsg = []; // Массив ошибок
|
|
|
|
/**
|
|
* Поля по умолчанию
|
|
* @var array<string, class-string<AbstractRule>>
|
|
*/
|
|
protected $type = [
|
|
'date' => Rule\Date::class,
|
|
'email' => Rule\Email::class,
|
|
'emaillist'=> Rule\EmailList::class,
|
|
'match' => Rule\MatchRule::class,
|
|
'time' => Rule\Time::class,
|
|
'alpha' => Rule\Alpha::class,
|
|
'require' => Rule\Notnull::class,
|
|
'numeric' => Rule\Numeric::class,
|
|
'unique' => Rule\Unique::class,
|
|
'filename' => Rule\FileName::class,
|
|
'count' => Rule\Count::class,
|
|
'isfile' => Rule\IsFile::class,
|
|
'code' => Rule\Code::class,
|
|
'reg' => Rule\PregMatch::class,
|
|
];
|
|
|
|
/**
|
|
* @param Rule[] $rules
|
|
*/
|
|
function __construct($rules = []) {
|
|
$this->addRuleList($rules);
|
|
}
|
|
|
|
/**
|
|
* Добавление правила в список
|
|
* @param string $name
|
|
* @param class-string<AbstractRule> $className
|
|
*/
|
|
function addRuleType(string $name, string $className): void {
|
|
$this->type[$name] = $className;
|
|
}
|
|
|
|
/**
|
|
* Добавление списка правил в специальном формате
|
|
* @param Rule[] $input
|
|
*/
|
|
public function addRuleList(array $input): void
|
|
{
|
|
// Разбор правила проверки
|
|
// Формат правила 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2'
|
|
foreach ($input as $value) {
|
|
// Список правил
|
|
if (! isset($value['validate'])) continue;
|
|
$rules = explode("|", $value['validate']);
|
|
|
|
foreach ($rules as $rule) {
|
|
// Список параметров правила
|
|
$rule_param = explode(",", $rule);
|
|
$name = array_shift($rule_param);
|
|
|
|
if (isset($this->type[$name])) {
|
|
$constructor = $this->type[$name];
|
|
$ruleObj = new $constructor($value['name'], false); // Нужны шаблонные сообщения для правил
|
|
if (isset($value['context'])) {
|
|
$ruleObj->setContext($value['context']);
|
|
}
|
|
foreach ($rule_param as $param) {
|
|
// Имя и значение параметра
|
|
list($p_name, $p_value) = explode("=", $param);
|
|
$ruleObj->$p_name = $p_value;
|
|
}
|
|
$this->addRule($ruleObj);
|
|
} else if (!empty($rule)) {
|
|
throw new Exception('Unknown validation rule "' . $rule . "'");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function addRule(array|AbstractRule $rule): void {
|
|
if (is_array($rule)) {
|
|
$this->chain = array_merge($this->chain, $rule);
|
|
} else {
|
|
$this->chain[] = $rule;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param AbstractRule $rule
|
|
*/
|
|
public function skip($rule, Collection $container): bool
|
|
{
|
|
if ($rule->skipEmpty()) {
|
|
$data = $container->get($rule->field);
|
|
if (!is_array($data)) {
|
|
$value = trim($data ?: '');
|
|
return $value == '';
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function reset(): void {
|
|
$this->errorMsg = [];
|
|
}
|
|
|
|
public function validate(Collection $container, $rule = null, $status = null): bool
|
|
{
|
|
$fields = [];
|
|
if ($rule) {
|
|
$this->chain = $rule;
|
|
}
|
|
|
|
foreach ($this->chain as $rule) {
|
|
//echo $key;
|
|
if (!in_array($rule->field, $fields) && !$this->skip($rule, $container) && !$rule->isValid($container, $status)) {
|
|
$name = $rule->field;
|
|
$this->errorMsg[$name] = $rule->getErrorMsg();
|
|
$fields [] = $name;
|
|
}
|
|
}
|
|
return $this->isValid();
|
|
}
|
|
|
|
public function addError(string $name, string $message)
|
|
{
|
|
$this->errorMsg[$name] = $message;
|
|
}
|
|
|
|
public function isError(): bool
|
|
{
|
|
return !empty($this->errorMsg);
|
|
}
|
|
|
|
public function isValid(): bool
|
|
{
|
|
return empty($this->errorMsg);
|
|
}
|
|
|
|
public function getErrorMsg()
|
|
{
|
|
return $this->errorMsg;
|
|
}
|
|
}
|