Skip to content

Commit b4cbb52

Browse files
author
Kirill Nesmeyanov
committed
Add casting for string type
1 parent dc0ced9 commit b4cbb52

File tree

2 files changed

+54
-2
lines changed

2 files changed

+54
-2
lines changed

src/Type/StringType.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99

1010
class StringType implements TypeInterface
1111
{
12+
protected const NULL_TO_STRING = '';
13+
protected const TRUE_TO_STRING = 'true';
14+
protected const FALSE_TO_STRING = 'false';
15+
protected const NAN_TO_STRING = 'nan';
16+
protected const INF_TO_STRING = 'inf';
17+
1218
public function match(mixed $value, Context $context): bool
1319
{
1420
return \is_string($value);
@@ -21,14 +27,42 @@ public function match(mixed $value, Context $context): bool
2127
*/
2228
public function cast(mixed $value, Context $context): string
2329
{
24-
if ($this->match($value, $context)) {
30+
if (\is_string($value)) {
2531
/** @var string */
2632
return $value;
2733
}
2834

35+
if (!$context->isStrictTypesEnabled()) {
36+
return $this->tryCast($value, $context);
37+
}
38+
2939
throw InvalidValueException::createFromContext(
3040
value: $value,
3141
context: $context,
3242
);
3343
}
44+
45+
/**
46+
* @throws InvalidValueException
47+
*/
48+
private function tryCast(mixed $value, Context $context): string
49+
{
50+
return match (true) {
51+
$value === null => static::NULL_TO_STRING,
52+
$value === true => static::TRUE_TO_STRING,
53+
$value === false => static::FALSE_TO_STRING,
54+
\is_float($value) => match (true) {
55+
\is_nan($value) => static::NAN_TO_STRING,
56+
\is_infinite($value) => ($value >= 0 ? '' : '-') . static::INF_TO_STRING,
57+
default => (string) $value,
58+
},
59+
\is_int($value),
60+
$value instanceof \Stringable => (string) $value,
61+
$value instanceof \BackedEnum => (string) $value->value,
62+
default => throw InvalidValueException::createFromContext(
63+
value: $value,
64+
context: $context,
65+
),
66+
};
67+
}
3468
}

tests/Feature/Type/string.feature

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Feature: Checking the "StringType" type behavior
1313
| 42 | false |
1414
| 42.1 | false |
1515
| INF | false |
16+
| -INF | false |
1617
| NAN | false |
1718
| "string" | true |
1819
| null | false |
@@ -21,9 +22,25 @@ Feature: Checking the "StringType" type behavior
2122
| true | false |
2223
| false | false |
2324

24-
Scenario Outline: Casting "<value>" by the StringType
25+
Scenario Outline: Normalize "<value>" by the StringType
2526
When normalize
2627
Then cast of "<value>" must return <result>
28+
Examples:
29+
| value | result |
30+
| 42 | "42" |
31+
| -9223372036854775808 | "-9.2233720368548E+18" |
32+
| 42.1 | "42.1" |
33+
| INF | "inf" |
34+
| -INF | "-inf" |
35+
| NAN | "nan" |
36+
| "string" | "string" |
37+
| null | "" |
38+
| (object)[] | <error: Passed value {} is invalid> |
39+
| [] | <error: Passed value [] is invalid> |
40+
| true | "true" |
41+
| false | "false" |
42+
43+
Scenario Outline: Denormalize "<value>" by the StringType
2744
When denormalize
2845
Then cast of "<value>" must return <result>
2946
Examples:
@@ -32,6 +49,7 @@ Feature: Checking the "StringType" type behavior
3249
| -9223372036854775808 | <error: Passed value -9.2233720368548E+18 is invalid> |
3350
| 42.1 | <error: Passed value 42.1 is invalid> |
3451
| INF | <error: Passed value INF is invalid> |
52+
| -INF | <error: Passed value -INF is invalid> |
3553
| NAN | <error: Passed value NAN is invalid> |
3654
| "string" | "string" |
3755
| null | <error: Passed value null is invalid> |

0 commit comments

Comments
 (0)