CastWith
This commit is contained in:
parent
bef42b3352
commit
afb47c1977
7 changed files with 56 additions and 26 deletions
|
|
@ -7,7 +7,7 @@ namespace Icefox\DTO\Attributes;
|
||||||
use Attribute;
|
use Attribute;
|
||||||
|
|
||||||
#[Attribute(Attribute::TARGET_PARAMETER)]
|
#[Attribute(Attribute::TARGET_PARAMETER)]
|
||||||
class FromMapper
|
class CastWith
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param class-string $class
|
* @param class-string $class
|
||||||
18
src/Config.php
Normal file
18
src/Config.php
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Icefox\DTO;
|
||||||
|
|
||||||
|
class Config
|
||||||
|
{
|
||||||
|
public static function getCaster(string $className): ?callable
|
||||||
|
{
|
||||||
|
return config('dto.cast.' . $className, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getRules(string $className): ?callable
|
||||||
|
{
|
||||||
|
return config('dto.rules.' . $className, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||||
namespace Icefox\DTO;
|
namespace Icefox\DTO;
|
||||||
|
|
||||||
use Icefox\DTO\Attributes\FromInput;
|
use Icefox\DTO\Attributes\FromInput;
|
||||||
use Icefox\DTO\Attributes\FromMapper;
|
use Icefox\DTO\Attributes\CastWith;
|
||||||
use Icefox\DTO\Attributes\FromRouteParameter;
|
use Icefox\DTO\Attributes\FromRouteParameter;
|
||||||
use Icefox\DTO\Support\RuleFactory;
|
use Icefox\DTO\Support\RuleFactory;
|
||||||
use Icefox\DTO\Support\ValueFactory;
|
use Icefox\DTO\Support\ValueFactory;
|
||||||
|
|
@ -78,7 +78,7 @@ trait DataObject
|
||||||
foreach ($parameters as $parameter) {
|
foreach ($parameters as $parameter) {
|
||||||
$parameterName = $parameter->reflection->getName();
|
$parameterName = $parameter->reflection->getName();
|
||||||
|
|
||||||
if ($mapper = array_first($parameter->reflection->getAttributes(FromMapper::class))) {
|
if ($mapper = array_first($parameter->reflection->getAttributes(CastWith::class))) {
|
||||||
$value = App::call(
|
$value = App::call(
|
||||||
[App::make($mapper->newInstance()->class), 'map'],
|
[App::make($mapper->newInstance()->class), 'map'],
|
||||||
['value' => $validator->getValue($parameterName)],
|
['value' => $validator->getValue($parameterName)],
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Icefox\DTO\Support;
|
namespace Icefox\DTO\Support;
|
||||||
|
|
||||||
|
use Icefox\DTO\Attributes\CastWith;
|
||||||
|
use Icefox\DTO\Config;
|
||||||
use Icefox\DTO\Attributes\FromMapper;
|
use Icefox\DTO\Attributes\FromMapper;
|
||||||
use Icefox\DTO\ParameterMeta;
|
use Icefox\DTO\ParameterMeta;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
|
|
@ -139,7 +141,7 @@ class RuleFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($type instanceof ReflectionNamedType && $name = $type->getName()) {
|
if ($type instanceof ReflectionNamedType && $name = $type->getName()) {
|
||||||
if ($globalRules = config('dto.rules.' . $name)) {
|
if ($globalRules = Config::getRules($name)) {
|
||||||
foreach ($globalRules($parameter->reflection, $parameter->tag->getType()) as $scopedPrefix => $values) {
|
foreach ($globalRules($parameter->reflection, $parameter->tag->getType()) as $scopedPrefix => $values) {
|
||||||
$realPrefix = $root . $scopedPrefix;
|
$realPrefix = $root . $scopedPrefix;
|
||||||
$rules[$realPrefix] = array_values(array_unique(array_merge($rules[$realPrefix] ?? [], $values)));
|
$rules[$realPrefix] = array_values(array_unique(array_merge($rules[$realPrefix] ?? [], $values)));
|
||||||
|
|
@ -166,7 +168,7 @@ class RuleFactory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($parameter->reflection->getAttributes(FromMapper::class) as $attr) {
|
foreach ($parameter->reflection->getAttributes(CastWith::class) as $attr) {
|
||||||
$mapperClass = $attr->newInstance()->class;
|
$mapperClass = $attr->newInstance()->class;
|
||||||
if (method_exists($mapperClass, 'rules')) {
|
if (method_exists($mapperClass, 'rules')) {
|
||||||
$subRules = App::call("$mapperClass@rules");
|
$subRules = App::call("$mapperClass@rules");
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Icefox\DTO\Support;
|
namespace Icefox\DTO\Support;
|
||||||
|
|
||||||
|
use Icefox\DTO\Attributes\CastWith;
|
||||||
|
use Icefox\DTO\Config;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
use ReflectionNamedType;
|
use ReflectionNamedType;
|
||||||
use ReflectionParameter;
|
use ReflectionParameter;
|
||||||
|
|
@ -20,7 +22,7 @@ class ValueFactory
|
||||||
{
|
{
|
||||||
public static function constructObject(string $className, mixed $rawValue): object
|
public static function constructObject(string $className, mixed $rawValue): object
|
||||||
{
|
{
|
||||||
if ($mapper = config('dto.mappers.' . $className, null)) {
|
if ($mapper = Config::getCaster($className)) {
|
||||||
return $mapper($rawValue);
|
return $mapper($rawValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,21 +85,32 @@ class ValueFactory
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_null($type)) {
|
$castWithAttrs = $reflection->getAttributes(CastWith::class);
|
||||||
$reflectedType = $reflection->getType();
|
if ($withCast = $reflection->getAttributes(CastWith::class)[0] ?? null) {
|
||||||
if ($reflectedType instanceof ReflectionNamedType && $name = $reflectedType->getName()) {
|
$caster = $withCast->newInstance()->class;
|
||||||
return match ($name) {
|
return App::call("$caster@cast", ['value' => $rawValue]);
|
||||||
'string' => $rawValue,
|
|
||||||
'bool' => boolval($rawValue),
|
|
||||||
'int' => intval($rawValue),
|
|
||||||
'float' => floatval($rawValue),
|
|
||||||
'array' => $rawValue,
|
|
||||||
default => self::constructObject($name, $rawValue),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return $rawValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::resolveTypedValue($rawValue, $type);
|
if (!is_null($type)) {
|
||||||
|
return self::resolveTypedValue($rawValue, $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
$reflectedType = $reflection->getType();
|
||||||
|
if ($reflectedType instanceof ReflectionNamedType && $name = $reflectedType->getName()) {
|
||||||
|
if ($caster = Config::getCaster($name)) {
|
||||||
|
return App::call($caster, ['value' => $rawValue]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return match ($name) {
|
||||||
|
'string' => $rawValue,
|
||||||
|
'bool' => boolval($rawValue),
|
||||||
|
'int' => intval($rawValue),
|
||||||
|
'float' => floatval($rawValue),
|
||||||
|
'array' => $rawValue,
|
||||||
|
default => self::constructObject($name, $rawValue),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rawValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,8 @@ use Icefox\DTO\Factories\CollectionFactory;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'cast' => [],
|
||||||
'rules' => [
|
'rules' => [
|
||||||
Collection::class => CollectionFactory::rules(...),
|
Collection::class => CollectionFactory::rules(...),
|
||||||
],
|
],
|
||||||
'default' => [
|
|
||||||
'factories' => [
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
||||||
namespace Tests\Classes;
|
namespace Tests\Classes;
|
||||||
|
|
||||||
use Carbon\CarbonPeriodImmutable;
|
use Carbon\CarbonPeriodImmutable;
|
||||||
use Icefox\DTO\Attributes\FromMapper;
|
use Icefox\DTO\Attributes\CastWith;
|
||||||
use Icefox\DTO\DataObject;
|
use Icefox\DTO\DataObject;
|
||||||
|
|
||||||
readonly class WithMapperObject
|
readonly class WithMapperObject
|
||||||
|
|
@ -13,7 +13,7 @@ readonly class WithMapperObject
|
||||||
use DataObject;
|
use DataObject;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
#[FromMapper(CarbonPeriodMapper::class)]
|
#[CastWith(CarbonPeriodMapper::class)]
|
||||||
public CarbonPeriodImmutable $period,
|
public CarbonPeriodImmutable $period,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue