phplibrary/src/Validator/Validator.php

172 lines
5.1 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 = [];
}
/**
* @param Collection $container
* @param AbstractRule[]|null $rules
* @param bool|null $status
* @return bool
*/
public function validate(Collection $container, $rules = null, $status = null): bool
{
$fields = [];
if ($rules) {
$this->chain = $rules;
}
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): void
{
$this->errorMsg[$name] = $message;
}
public function isError(): bool
{
return !empty($this->errorMsg);
}
public function isValid(): bool
{
return empty($this->errorMsg);
}
/**
* @return array<string, string>
*/
public function getErrorMsg(): array
{
return $this->errorMsg;
}
}