Skip to content

Commit 721ba85

Browse files
committed
Improve Serializer internal codebase to allow more type conversion
1 parent bdce34b commit 721ba85

11 files changed

+66
-19
lines changed

src/Serializer/CallbackCasting.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@
3030
*/
3131
final class CallbackCasting implements TypeCasting
3232
{
33-
/** @var array<string, Closure(?string, bool, mixed...): mixed> */
33+
/** @var array<string, Closure(mixed, bool, mixed...): mixed> */
3434
private static array $types = [];
3535

36-
/** @var array<string, array<string, Closure(?string, bool, mixed...): mixed>> */
36+
/** @var array<string, array<string, Closure(mixed, bool, mixed...): mixed>> */
3737
private static array $aliases = [];
3838

3939
private string $type;
4040
private readonly bool $isNullable;
41-
/** @var Closure(?string, bool, mixed...): mixed */
41+
/** @var Closure(mixed, bool, mixed...): mixed */
4242
private Closure $callback;
4343
private array $options = [];
4444
private string $message;
@@ -54,7 +54,7 @@ public function __construct(
5454
$reflectionProperty instanceof ReflectionProperty => 'The property `'.$reflectionProperty->getDeclaringClass()->getName().'::'.$reflectionProperty->getName().'` must be typed with a supported type.',
5555
};
5656

57-
$this->callback = fn (?string $value, bool $isNullable, mixed ...$arguments): ?string => $value;
57+
$this->callback = fn (mixed $value, bool $isNullable, mixed ...$arguments): mixed => $value;
5858
}
5959

6060
/**
@@ -90,7 +90,7 @@ public function setOptions(?string $type = null, mixed ...$options): void
9090
/**
9191
* @return TValue
9292
*/
93-
public function toVariable(?string $value): mixed
93+
public function toVariable(mixed $value): mixed
9494
{
9595
try {
9696
return ($this->callback)($value, $this->isNullable, ...$this->options);
@@ -111,7 +111,7 @@ public function toVariable(?string $value): mixed
111111
}
112112

113113
/**
114-
* @param Closure(?string, bool, mixed...): TValue $callback
114+
* @param Closure(mixed, bool, mixed...): TValue $callback
115115
*/
116116
public static function register(string $type, Closure $callback, ?string $alias = null): void
117117
{

src/Serializer/CastToArray.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use ReflectionParameter;
1818
use ReflectionProperty;
1919

20+
use Traversable;
2021
use function explode;
2122
use function is_array;
2223
use function json_decode;
@@ -95,7 +96,7 @@ public function setOptions(
9596
};
9697
}
9798

98-
public function toVariable(?string $value): ?array
99+
public function toVariable(mixed $value): ?array
99100
{
100101
if (null === $value) {
101102
return match (true) {
@@ -109,6 +110,18 @@ public function toVariable(?string $value): ?array
109110
return [];
110111
}
111112

113+
if (is_array($value)) {
114+
return $value;
115+
}
116+
117+
if ($value instanceof Traversable) {
118+
return iterator_to_array($value);
119+
}
120+
121+
if (!is_string($value)) {
122+
throw TypeCastingFailed::dueToInvalidValue($value, $this->type->value);
123+
}
124+
112125
try {
113126
$result = match ($this->shape) {
114127
ArrayShape::Json => json_decode($value, true, $this->depth, $this->flags | JSON_THROW_ON_ERROR),

src/Serializer/CastToBool.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function setOptions(?bool $default = null): void
4040
/**
4141
* @throws TypeCastingFailed
4242
*/
43-
public function toVariable(?string $value): ?bool
43+
public function toVariable(mixed $value): ?bool
4444
{
4545
$returnValue = match (true) {
4646
null !== $value => filter_var($value, Type::Bool->filterFlag()),

src/Serializer/CastToDate.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ interface_exists($this->class) && null !== $className && class_exists($className
7979
/**
8080
* @throws TypeCastingFailed
8181
*/
82-
public function toVariable(?string $value): DateTimeImmutable|DateTime|null
82+
public function toVariable(mixed $value): DateTimeImmutable|DateTime|null
8383
{
8484
return match (true) {
8585
null !== $value && '' !== $value => $this->cast($value),
@@ -91,8 +91,20 @@ public function toVariable(?string $value): DateTimeImmutable|DateTime|null
9191
/**
9292
* @throws TypeCastingFailed
9393
*/
94-
private function cast(string $value): DateTimeImmutable|DateTime
94+
private function cast(mixed $value): DateTimeImmutable|DateTime
9595
{
96+
if ($value instanceof DateTimeInterface) {
97+
if ($value instanceof $this->class) {
98+
return $value;
99+
}
100+
101+
return ($this->class)::createFromInterface($value);
102+
}
103+
104+
if (!is_string($value)) {
105+
throw TypeCastingFailed::dueToInvalidValue($value, $this->class);
106+
}
107+
96108
try {
97109
$date = null !== $this->format ?
98110
($this->class)::createFromFormat($this->format, $value, $this->timezone) :

src/Serializer/CastToEnum.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public function setOptions(?string $default = null, ?string $className = null):
6666
/**
6767
* @throws TypeCastingFailed
6868
*/
69-
public function toVariable(?string $value): BackedEnum|UnitEnum|null
69+
public function toVariable(mixed $value): BackedEnum|UnitEnum|null
7070
{
7171
return match (true) {
7272
null !== $value => $this->cast($value),
@@ -78,8 +78,16 @@ public function toVariable(?string $value): BackedEnum|UnitEnum|null
7878
/**
7979
* @throws TypeCastingFailed
8080
*/
81-
private function cast(string $value): BackedEnum|UnitEnum
81+
private function cast(mixed $value): BackedEnum|UnitEnum
8282
{
83+
if ($value instanceof $this->class) {
84+
return $value;
85+
}
86+
87+
if (!is_string($value)) {
88+
throw throw TypeCastingFailed::dueToInvalidValue($value, $this->class);
89+
}
90+
8391
try {
8492
$enum = new ReflectionEnum($this->class);
8593
if (!$enum->isBacked()) {

src/Serializer/CastToFloat.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function setOptions(int|float|null $default = null): void
3939
/**
4040
* @throws TypeCastingFailed
4141
*/
42-
public function toVariable(?string $value): ?float
42+
public function toVariable(mixed $value): ?float
4343
{
4444
if (null === $value) {
4545
return match ($this->isNullable) {
@@ -48,6 +48,10 @@ public function toVariable(?string $value): ?float
4848
};
4949
}
5050

51+
if (!is_scalar($value)) {
52+
throw TypeCastingFailed::dueToInvalidValue($value, Type::Int->value);
53+
}
54+
5155
$float = filter_var($value, Type::Float->filterFlag());
5256

5357
return match ($float) {

src/Serializer/CastToInt.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function setOptions(?int $default = null): void
3939
/**
4040
* @throws TypeCastingFailed
4141
*/
42-
public function toVariable(?string $value): ?int
42+
public function toVariable(mixed $value): ?int
4343
{
4444
if (null === $value) {
4545
return match ($this->isNullable) {
@@ -48,6 +48,10 @@ public function toVariable(?string $value): ?int
4848
};
4949
}
5050

51+
if (!is_scalar($value)) {
52+
throw TypeCastingFailed::dueToInvalidValue($value, Type::Int->value);
53+
}
54+
5155
$int = filter_var($value, Type::Int->filterFlag());
5256

5357
return match ($int) {

src/Serializer/CastToString.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
use ReflectionParameter;
1717
use ReflectionProperty;
18+
use Stringable;
1819

1920
/**
2021
* @implements TypeCasting<?string>
@@ -38,10 +39,11 @@ public function setOptions(?string $default = null): void
3839
/**
3940
* @throws TypeCastingFailed
4041
*/
41-
public function toVariable(?string $value): ?string
42+
public function toVariable(mixed $value): ?string
4243
{
4344
$returnedValue = match(true) {
44-
null !== $value => $value,
45+
$value instanceof \Stringable,
46+
is_string($value) => (string) $value,
4547
$this->isNullable => $this->default,
4648
default => throw TypeCastingFailed::dueToNotNullableType($this->type->value),
4749
};

src/Serializer/PropertySetter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public function __construct(
3232
/**
3333
* @throws ReflectionException
3434
*/
35-
public function __invoke(object $object, ?string $value): void
35+
public function __invoke(object $object, mixed $value): void
3636
{
3737
$typeCastedValue = $this->cast->toVariable($value);
3838

src/Serializer/TypeCasting.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface TypeCasting
2323
*
2424
* @return TValue
2525
*/
26-
public function toVariable(?string $value): mixed;
26+
public function toVariable(mixed $value): mixed;
2727

2828
/**
2929
* Accepts additional parameters to configure the class

0 commit comments

Comments
 (0)