137 lines
4.1 KiB
PHP
137 lines
4.1 KiB
PHP
<?php
|
|
|
|
namespace Kiri\Router\Validator;
|
|
|
|
use Exception;
|
|
use Kiri;
|
|
use Kiri\Di\Inject\Container;
|
|
use Kiri\Di\Interface\InjectParameterInterface;
|
|
use Kiri\Router\Base\Middleware;
|
|
use Kiri\Router\Validator\Types\ArrayProxy;
|
|
use Kiri\Router\Validator\Types\BoolProxy;
|
|
use Kiri\Router\Validator\Types\FloatProxy;
|
|
use Kiri\Router\Validator\Types\IntProxy;
|
|
use Kiri\Router\Validator\Types\MixedProxy;
|
|
use Kiri\Router\Validator\Types\StringProxy;
|
|
use Kiri\Router\Validator\Types\TypesProxy;
|
|
use Kiri\Server\ServerInterface;
|
|
use ReflectionNamedType;
|
|
use ReflectionProperty;
|
|
use ReflectionUnionType;
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
#[\Attribute(\Attribute::TARGET_PARAMETER)]
|
|
class BindForm implements InjectParameterInterface
|
|
{
|
|
|
|
|
|
/**
|
|
* @param string $formValidate
|
|
*/
|
|
public function __construct(readonly public string $formValidate)
|
|
{
|
|
}
|
|
|
|
|
|
/**
|
|
* @param string $class
|
|
* @param string $method
|
|
* @return mixed
|
|
* @throws
|
|
*/
|
|
public function dispatch(string $class, string $method): object
|
|
{
|
|
$validator = new Validator();
|
|
$reflect = Kiri::getDi()->getReflectionClass($this->formValidate);
|
|
$object = $validator->setFormData($reflect->newInstanceWithoutConstructor());
|
|
foreach ($reflect->getProperties() as $property) {
|
|
$ignoring = $property->getAttributes(Ignoring::class);
|
|
if (count($ignoring) === 0) {
|
|
$this->properties($validator, $property, $object);
|
|
}
|
|
}
|
|
|
|
Middleware::setValidator($class, $method, $validator);
|
|
|
|
return $validator->getFormData();
|
|
}
|
|
|
|
|
|
/**
|
|
* @param Validator $validator
|
|
* @param ReflectionProperty $property
|
|
* @param object $object
|
|
* @return void
|
|
* @throws Exception
|
|
*/
|
|
protected function properties(Validator $validator, ReflectionProperty $property, object $object): void
|
|
{
|
|
$propertyContainer = $property->getAttributes(Container::class);
|
|
if (count($propertyContainer) > 0) {
|
|
($propertyContainer[0]->newInstance())->dispatch($object, $property->getName());
|
|
}
|
|
|
|
|
|
$binding = $property->getAttributes(Binding::class);
|
|
if (count($binding) > 0) {
|
|
/** @var Binding $rule */
|
|
$rule = $binding[0]->newInstance();
|
|
|
|
$validator->addRule($property->getName(), $rule->dispatch($object, $property->getName()));
|
|
$validator->setAlias($property->getName(), $rule->field);
|
|
}
|
|
|
|
$validator->addRule($property->getName(), [[$this->_typeValidator($property), 'dispatch', false]]);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param ReflectionProperty $property
|
|
* @return TypesProxy
|
|
* @throws Exception
|
|
*/
|
|
private function _typeValidator(ReflectionProperty $property): TypesProxy
|
|
{
|
|
$getType = $property->getType();
|
|
if (is_null($getType)) {
|
|
$service = Kiri::getDi();
|
|
if ($service->has(ServerInterface::class)) {
|
|
$service->get(ServerInterface::class)->shutdown();
|
|
}
|
|
throw new Exception('Field ' . $property->getDeclaringClass()->getName() . '::' . $property->getName() . ' must have a numerical type set.');
|
|
}
|
|
$array = ['allowsNull' => $property->getType()->allowsNull()];
|
|
if (!$getType instanceof ReflectionUnionType) {
|
|
$array = array_merge($array, ['class' => $this->_typeProxy($getType)]);
|
|
} else {
|
|
$types = [];
|
|
foreach ($getType->getTypes() as $type) {
|
|
$types[] = $type->getName();
|
|
}
|
|
$array = array_merge($array, ['types' => $types, 'class' => MixedProxy::class]);
|
|
}
|
|
return Kiri::createObject($array);
|
|
}
|
|
|
|
|
|
/**
|
|
* @param ReflectionNamedType $type
|
|
* @return string|null
|
|
*/
|
|
private function _typeProxy(ReflectionNamedType $type): ?string
|
|
{
|
|
return match ($type->getName()) {
|
|
'array' => ArrayProxy::class,
|
|
'bool' => BoolProxy::class,
|
|
'float' => FloatProxy::class,
|
|
'int' => IntProxy::class,
|
|
'string' => StringProxy::class,
|
|
default => null
|
|
};
|
|
}
|
|
|
|
}
|