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;
|
||||
|
||||
#[Attribute(Attribute::TARGET_PARAMETER)]
|
||||
class FromMapper
|
||||
class CastWith
|
||||
{
|
||||
/**
|
||||
* @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;
|
||||
|
||||
use Icefox\DTO\Attributes\FromInput;
|
||||
use Icefox\DTO\Attributes\FromMapper;
|
||||
use Icefox\DTO\Attributes\CastWith;
|
||||
use Icefox\DTO\Attributes\FromRouteParameter;
|
||||
use Icefox\DTO\Support\RuleFactory;
|
||||
use Icefox\DTO\Support\ValueFactory;
|
||||
|
|
@ -78,7 +78,7 @@ trait DataObject
|
|||
foreach ($parameters as $parameter) {
|
||||
$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(
|
||||
[App::make($mapper->newInstance()->class), 'map'],
|
||||
['value' => $validator->getValue($parameterName)],
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Icefox\DTO\Support;
|
||||
|
||||
use Icefox\DTO\Attributes\CastWith;
|
||||
use Icefox\DTO\Config;
|
||||
use Icefox\DTO\Attributes\FromMapper;
|
||||
use Icefox\DTO\ParameterMeta;
|
||||
use Illuminate\Support\Facades\App;
|
||||
|
|
@ -139,7 +141,7 @@ class RuleFactory
|
|||
}
|
||||
|
||||
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) {
|
||||
$realPrefix = $root . $scopedPrefix;
|
||||
$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;
|
||||
if (method_exists($mapperClass, 'rules')) {
|
||||
$subRules = App::call("$mapperClass@rules");
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace Icefox\DTO\Support;
|
||||
|
||||
use Icefox\DTO\Attributes\CastWith;
|
||||
use Icefox\DTO\Config;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use ReflectionNamedType;
|
||||
use ReflectionParameter;
|
||||
|
|
@ -20,7 +22,7 @@ class ValueFactory
|
|||
{
|
||||
public static function constructObject(string $className, mixed $rawValue): object
|
||||
{
|
||||
if ($mapper = config('dto.mappers.' . $className, null)) {
|
||||
if ($mapper = Config::getCaster($className)) {
|
||||
return $mapper($rawValue);
|
||||
}
|
||||
|
||||
|
|
@ -83,21 +85,32 @@ class ValueFactory
|
|||
return null;
|
||||
}
|
||||
|
||||
if (is_null($type)) {
|
||||
$reflectedType = $reflection->getType();
|
||||
if ($reflectedType instanceof ReflectionNamedType && $name = $reflectedType->getName()) {
|
||||
return match ($name) {
|
||||
'string' => $rawValue,
|
||||
'bool' => boolval($rawValue),
|
||||
'int' => intval($rawValue),
|
||||
'float' => floatval($rawValue),
|
||||
'array' => $rawValue,
|
||||
default => self::constructObject($name, $rawValue),
|
||||
};
|
||||
}
|
||||
return $rawValue;
|
||||
$castWithAttrs = $reflection->getAttributes(CastWith::class);
|
||||
if ($withCast = $reflection->getAttributes(CastWith::class)[0] ?? null) {
|
||||
$caster = $withCast->newInstance()->class;
|
||||
return App::call("$caster@cast", ['value' => $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;
|
||||
|
||||
return [
|
||||
'cast' => [],
|
||||
'rules' => [
|
||||
Collection::class => CollectionFactory::rules(...),
|
||||
],
|
||||
'default' => [
|
||||
'factories' => [
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ declare(strict_types=1);
|
|||
namespace Tests\Classes;
|
||||
|
||||
use Carbon\CarbonPeriodImmutable;
|
||||
use Icefox\DTO\Attributes\FromMapper;
|
||||
use Icefox\DTO\Attributes\CastWith;
|
||||
use Icefox\DTO\DataObject;
|
||||
|
||||
readonly class WithMapperObject
|
||||
|
|
@ -13,7 +13,7 @@ readonly class WithMapperObject
|
|||
use DataObject;
|
||||
|
||||
public function __construct(
|
||||
#[FromMapper(CarbonPeriodMapper::class)]
|
||||
#[CastWith(CarbonPeriodMapper::class)]
|
||||
public CarbonPeriodImmutable $period,
|
||||
) {}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue