This commit is contained in:
icefox 2026-02-25 12:29:47 -03:00
parent 6b1a385292
commit bba10b455f
No known key found for this signature in database
10 changed files with 296 additions and 514 deletions

View file

@ -7,6 +7,4 @@ namespace Icefox\DTO\Attributes;
use Attribute;
#[Attribute(Attribute::TARGET_METHOD)]
class OverwriteRules
{
}
class Overwrite {}

View file

@ -12,6 +12,7 @@ use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;
use Illuminate\Validation\Validator;
use Psr\Log\LoggerInterface;
class DataObjectFactory
{
@ -26,41 +27,13 @@ class DataObjectFactory
/**
* @param class-string $class
* @param array<string,mixed> $input
* @param array<string,mixed> $rawInput
* @param array<string,mixed> $routeParameters
*/
public static function fromArray(string $class, array $input, array $routeParameters): ?object
public static function fromArray(string $class, array $rawInput, array $routeParameters): ?object
{
$logger = Log::channel('dto');
$parameters = ReflectionHelper::getParametersMeta($class);
foreach ($parameters as $parameter) {
$parameterName = $parameter->reflection->getName();
foreach ($parameter->reflection->getAttributes(FromRouteParameter::class) as $fromRouteParameter) {
if ($value = $routeParameters[$fromRouteParameter->newInstance()->name] ?? null) {
$input[$parameterName] = $value;
continue 2;
}
}
foreach ($parameter->reflection->getAttributes(FromInput::class) as $attr) {
if ($value = $input[$attr->newInstance()->name] ?? null) {
$input[$parameterName] = $value;
continue 2;
}
}
if ($value = $input[$parameterName] ?? null) {
$input[$parameterName] = $value;
continue;
}
// if ($parameter->reflection->isDefaultValueAvailable()) {
// $input[$parameterName] = $parameter->reflection->getDefaultValue();
// continue;
// }
}
$logger->debug('input', $input);
$input = self::mapInput($class, $rawInput, $routeParameters, $logger);
$rules = (new RuleFactory($logger))->make($class);
@ -78,4 +51,45 @@ class DataObjectFactory
return ValueFactory::make($class, $validator->validated());
}
/**
* @param class-string $class
* @param array<string,mixed> $rawInput
* @param array<string,mixed> $routeParameters
* @return array<string,mixed>
*/
public static function mapInput(
string $class,
array $rawInput,
array $routeParameters,
LoggerInterface $logger,
): array {
$input = [];
$parameters = ReflectionHelper::getParametersMeta($class);
foreach ($parameters as $parameter) {
$parameterName = $parameter->reflection->getName();
foreach ($parameter->reflection->getAttributes(FromRouteParameter::class) as $fromRouteParameter) {
if ($value = $routeParameters[$fromRouteParameter->newInstance()->name] ?? null) {
$input[$parameterName] = $value;
continue 2;
}
}
foreach ($parameter->reflection->getAttributes(FromInput::class) as $attr) {
if ($value = $rawInput[$attr->newInstance()->name] ?? null) {
$input[$parameterName] = $value;
continue 2;
}
}
if ($value = $rawInput[$parameterName] ?? null) {
$input[$parameterName] = $value;
continue;
}
}
$logger->debug('input', $input);
return $input;
}
}

View file

@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Icefox\DTO;
use Icefox\DTO\Attributes\Flat;
use Icefox\DTO\Attributes\OverwriteRules;
use Icefox\DTO\Attributes\Overwrite;
use Icefox\DTO\Config;
use Icefox\DTO\ParameterMeta;
use Icefox\DTO\ReflectionHelper;
@ -30,7 +30,7 @@ use phpDocumentor\Reflection\Types\Object_;
final class RuleFactory
{
/**
* @return array<string, array<string|Rule>>
* @return array<string, array<int, mixed>>
*/
public function getRulesFromDocBlock(
Type $type,
@ -63,7 +63,7 @@ final class RuleFactory
/**
* @param array<ParameterMeta> $parameters
* @return array<string,array<int,string|Rule>>
* @return array<string,array<int,mixed>>
*/
public function infer(array $parameters, string $basePrefix): array
{
@ -80,7 +80,7 @@ final class RuleFactory
}
/**
* @return array<string, array<int, string|Rule>>
* @return array<string, array<int, mixed>>
*/
public function buildParameterRule(ParameterMeta $parameter, string $prefix): array
{
@ -150,7 +150,7 @@ final class RuleFactory
/**
* @param class-string $class
* @return array<string,array<int, string>>
* @return array<string,array<int, mixed>>
*/
public function make(string $class): array
{
@ -162,7 +162,7 @@ final class RuleFactory
$customRules = $hasRulesMethod ? App::call("$class::rules", []) : [];
if ($hasRulesMethod && !empty($classReflection->getMethod('rules')->getAttributes(OverwriteRules::class))) {
if ($hasRulesMethod && !empty($classReflection->getMethod('rules')->getAttributes(Overwrite::class))) {
$rules = $customRules;
} else {
$inferredRules = RuleFactory::infer($parameters, '');
@ -173,9 +173,9 @@ final class RuleFactory
}
/**
* @param array<string,array<int, string>> $first
* @param array<string,array<int, string>> $second
* @return array<string,array<int, string>>
* @param array<string,array<int, mixed>> $first
* @param array<string,array<int, mixed>> $second
* @return array<string,array<int, mixed>>
*/
public function mergeRules(array $first, array $second): array
{