2023-04-15 23:29:27 +08:00
|
|
|
<?php
|
2023-04-16 01:24:30 +08:00
|
|
|
declare(strict_types=1);
|
2023-04-15 23:29:27 +08:00
|
|
|
|
2023-04-15 23:31:16 +08:00
|
|
|
namespace Kiri\Router\Validator;
|
2023-04-15 23:29:27 +08:00
|
|
|
|
2023-12-13 18:59:56 +08:00
|
|
|
use Exception;
|
2023-11-10 10:18:22 +08:00
|
|
|
use Kiri\Router\Constrict\ConstrictRequest;
|
2023-04-15 23:31:16 +08:00
|
|
|
use Kiri\Router\Interface\ValidatorInterface;
|
2023-11-09 22:08:24 +08:00
|
|
|
use Psr\Http\Message\RequestInterface;
|
2023-04-15 23:31:16 +08:00
|
|
|
use Psr\Http\Message\ServerRequestInterface;
|
2023-11-10 15:19:51 +08:00
|
|
|
use ReflectionException;
|
2023-12-04 22:15:18 +08:00
|
|
|
use ReflectionNamedType;
|
|
|
|
|
use ReflectionUnionType;
|
2023-04-15 23:29:27 +08:00
|
|
|
|
2023-10-08 18:48:09 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* class Validator
|
|
|
|
|
*/
|
2023-04-15 23:29:27 +08:00
|
|
|
class Validator
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
2023-08-18 21:08:58 +08:00
|
|
|
/**
|
|
|
|
|
* @var ValidatorInterface[]
|
|
|
|
|
*/
|
2023-08-21 17:24:55 +08:00
|
|
|
protected array $rules = [];
|
2023-04-15 23:29:27 +08:00
|
|
|
|
|
|
|
|
|
2023-11-10 10:18:22 +08:00
|
|
|
/**
|
|
|
|
|
* @var string
|
|
|
|
|
*/
|
2023-08-21 17:24:55 +08:00
|
|
|
protected string $message = '';
|
2023-04-15 23:29:27 +08:00
|
|
|
|
|
|
|
|
|
2023-11-10 10:18:22 +08:00
|
|
|
/**
|
|
|
|
|
* @var object
|
|
|
|
|
*/
|
2023-08-21 17:24:55 +08:00
|
|
|
protected object $formData;
|
2023-04-15 23:31:16 +08:00
|
|
|
|
|
|
|
|
|
2023-12-04 22:15:18 +08:00
|
|
|
/**
|
|
|
|
|
* @var array
|
|
|
|
|
*/
|
|
|
|
|
protected array $types = [];
|
|
|
|
|
|
|
|
|
|
|
2023-08-18 21:08:58 +08:00
|
|
|
/**
|
|
|
|
|
* @param object $formData
|
2023-12-04 21:17:04 +08:00
|
|
|
* @return object
|
2023-08-18 21:08:58 +08:00
|
|
|
*/
|
2023-12-04 21:17:04 +08:00
|
|
|
public function setFormData(object $formData): object
|
2023-08-18 21:08:58 +08:00
|
|
|
{
|
|
|
|
|
$this->formData = $formData;
|
2023-12-04 21:17:04 +08:00
|
|
|
return $formData;
|
2023-08-18 21:08:58 +08:00
|
|
|
}
|
2023-04-16 03:51:18 +08:00
|
|
|
|
|
|
|
|
|
2023-12-04 22:15:18 +08:00
|
|
|
/**
|
|
|
|
|
* @param string $property
|
|
|
|
|
* @param ReflectionNamedType|ReflectionUnionType $types
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function setTypes(string $property, ReflectionNamedType|ReflectionUnionType $types): void
|
|
|
|
|
{
|
|
|
|
|
$this->types[$property] = $types;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-08-18 21:08:58 +08:00
|
|
|
/**
|
|
|
|
|
* @return object
|
|
|
|
|
*/
|
|
|
|
|
public function getFormData(): object
|
|
|
|
|
{
|
|
|
|
|
return $this->formData;
|
|
|
|
|
}
|
2023-04-16 03:51:18 +08:00
|
|
|
|
2023-08-18 21:08:58 +08:00
|
|
|
/**
|
|
|
|
|
* @param string $name
|
|
|
|
|
* @param ValidatorInterface $rule
|
|
|
|
|
* @return void
|
|
|
|
|
*/
|
|
|
|
|
public function addRule(string $name, ValidatorInterface $rule): void
|
|
|
|
|
{
|
2023-11-09 20:45:16 +08:00
|
|
|
if (!isset($this->rules[$name])) {
|
|
|
|
|
$this->rules[$name] = [];
|
|
|
|
|
}
|
|
|
|
|
$this->rules[$name][] = $rule;
|
2023-08-18 21:08:58 +08:00
|
|
|
}
|
2023-04-15 23:31:16 +08:00
|
|
|
|
|
|
|
|
|
2023-05-02 15:28:28 +08:00
|
|
|
/**
|
2023-11-10 10:18:22 +08:00
|
|
|
* @param RequestInterface|ServerRequestInterface|ConstrictRequest $request
|
2023-08-18 21:08:58 +08:00
|
|
|
* @return bool
|
2023-12-12 15:35:35 +08:00
|
|
|
* @throws
|
2023-08-18 21:08:58 +08:00
|
|
|
*/
|
2023-11-10 10:18:22 +08:00
|
|
|
public function run(RequestInterface|ServerRequestInterface|ConstrictRequest $request): bool
|
2023-08-18 21:08:58 +08:00
|
|
|
{
|
2023-11-09 22:08:24 +08:00
|
|
|
if (!empty($this->message)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-12-12 16:25:31 +08:00
|
|
|
$params = !$request->isPost() ? $request->getQueryParams() : $request->getParsedBody();
|
2023-11-10 15:27:48 +08:00
|
|
|
|
|
|
|
|
foreach ($params as $name => $value) {
|
2023-12-04 22:15:18 +08:00
|
|
|
if (!isset($this->types[$name])) {
|
2023-11-10 15:30:30 +08:00
|
|
|
continue;
|
|
|
|
|
}
|
2023-11-10 15:27:48 +08:00
|
|
|
$rules = $this->rules[$name] ?? [];
|
|
|
|
|
foreach ($rules as $item) {
|
2023-11-09 22:08:24 +08:00
|
|
|
/** @var ValidatorInterface $item */
|
|
|
|
|
if (!$item->dispatch($value, $this->formData)) {
|
2023-11-09 20:45:16 +08:00
|
|
|
return $this->addError($name);
|
|
|
|
|
}
|
2023-08-18 21:08:58 +08:00
|
|
|
}
|
2023-12-04 22:15:18 +08:00
|
|
|
|
|
|
|
|
/** @var ReflectionNamedType|ReflectionUnionType $property */
|
|
|
|
|
$property = $this->types[$name];
|
|
|
|
|
if ($property instanceof ReflectionUnionType) {
|
|
|
|
|
foreach ($property->getTypes() as $type) {
|
2023-12-04 22:05:34 +08:00
|
|
|
$typeName = $type->getName();
|
|
|
|
|
if ($typeName == 'string' && is_string($value)) {
|
|
|
|
|
$this->formData->{$name} = $value;
|
|
|
|
|
break;
|
|
|
|
|
} else if ($typeName == 'int' && $value == ($int = intval($value))) {
|
|
|
|
|
$this->formData->{$name} = $int;
|
|
|
|
|
break;
|
|
|
|
|
} else if ($typeName == 'bool' && in_array($value, ['true', 'false'])) {
|
|
|
|
|
$this->formData->{$name} = $value == 'true';
|
|
|
|
|
break;
|
|
|
|
|
} else if ($typeName == 'float' && $value == ($flo = floatval($value))) {
|
|
|
|
|
$this->formData->{$name} = $flo;
|
|
|
|
|
break;
|
|
|
|
|
} else if ($typeName == 'array' && is_array($value)) {
|
|
|
|
|
$this->formData->{$name} = $value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ($this->formData->{$name} != $value) {
|
2023-12-13 18:59:56 +08:00
|
|
|
throw new Exception('Fail type value.');
|
2023-12-04 22:05:34 +08:00
|
|
|
}
|
|
|
|
|
} else {
|
2023-12-04 23:26:57 +08:00
|
|
|
$this->formData->{$name} = match ($property->getName()) {
|
2023-12-04 22:05:34 +08:00
|
|
|
'int' => (int)$value,
|
2023-11-10 15:19:51 +08:00
|
|
|
'float' => (float)$value,
|
2023-12-04 22:15:18 +08:00
|
|
|
'bool' => $value == 'true',
|
2023-12-13 18:59:56 +08:00
|
|
|
'array' => $this->arrayCheck($property, $name, $value),
|
2023-11-10 15:19:51 +08:00
|
|
|
default => $value
|
|
|
|
|
};
|
|
|
|
|
}
|
2023-08-18 21:08:58 +08:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-12-13 18:59:56 +08:00
|
|
|
/**
|
|
|
|
|
* @param ReflectionNamedType $property
|
|
|
|
|
* @param string $name
|
|
|
|
|
* @param string|array $value
|
|
|
|
|
* @return array
|
|
|
|
|
* @throws Exception
|
|
|
|
|
*/
|
|
|
|
|
protected function arrayCheck(ReflectionNamedType $property, string $name, string|array $value): array
|
|
|
|
|
{
|
|
|
|
|
if (empty($value) || !is_array($value)) {
|
|
|
|
|
if ($property->allowsNull()) {
|
|
|
|
|
$this->formData->{$name} = null;
|
|
|
|
|
}
|
|
|
|
|
throw new Exception('TypeError Cannot assign string to property ' . $name . ' of type array');
|
|
|
|
|
}
|
|
|
|
|
return $value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-08-18 21:08:58 +08:00
|
|
|
/**
|
|
|
|
|
* @param $field
|
|
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
private function addError($field): bool
|
|
|
|
|
{
|
2023-11-10 10:18:22 +08:00
|
|
|
$this->message = 'Field ' . $field . ' value format fail.';
|
2023-08-18 21:08:58 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @return string
|
|
|
|
|
*/
|
|
|
|
|
public function error(): string
|
|
|
|
|
{
|
|
|
|
|
return $this->message;
|
|
|
|
|
}
|
2023-04-15 23:29:27 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|