Skip to content

Commit a948577

Browse files
committed
Simplify Value validation
1 parent 8fdc73c commit a948577

File tree

3 files changed

+18
-56
lines changed

3 files changed

+18
-56
lines changed

src/Item.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,22 +124,26 @@ public static function fromPair(array $pair): self
124124
*/
125125
public static function new(mixed $value): self
126126
{
127+
if ($value instanceof Item) {
128+
return new self(new Value($value->value()), $value->parameters());
129+
}
130+
127131
if (is_array($value)) {
128132
return self::fromPair($value);
129133
}
130134

131-
return self::fromValue(new Value($value));
135+
return self::fromValue(new Value($value)); /* @phpstan-ignore-line */
132136
}
133137

134138
/**
135139
* Returns a new bare instance from value or null on error.
136140
*
137-
* @param SfItemInput|array{0:SfItemInput, 1:Parameters|iterable<array{0:string, 1:SfItemInput}>} $value
141+
* @param SfTypeInput|Item|array{0:SfTypeInput, 1:Parameters|iterable<array{0:string, 1:SfTypeInput}>} $value
138142
*/
139-
public static function tryNew(mixed $value): ?self
143+
public static function tryNew(StructuredFieldProvider|Item|DateTimeInterface|Bytes|DisplayString|Token|array|int|float|string|bool $value): ?self
140144
{
141145
try {
142-
return self::fromValue(new Value($value));
146+
return self::new($value);
143147
} catch (SyntaxError) {
144148
return null;
145149
}

src/Value.php

Lines changed: 8 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,10 @@
1111
use Stringable;
1212
use Throwable;
1313

14-
use function abs;
1514
use function date_default_timezone_get;
16-
use function floor;
1715
use function is_float;
1816
use function is_int;
1917
use function json_encode;
20-
use function preg_match;
2118
use function preg_replace;
2219
use function round;
2320

@@ -34,9 +31,9 @@ final class Value
3431
public readonly Type $type;
3532

3633
/**
37-
* @throws InvalidArgument
34+
* @throws SyntaxError
3835
*/
39-
public function __construct(mixed $value)
36+
public function __construct(Item|Token|Bytes|DisplayString|DateTimeInterface|int|float|string|bool $value)
4037
{
4138
[$this->value, $this->type] = match (true) {
4239
$value instanceof Item => [$value->value(), $value->type()],
@@ -46,49 +43,7 @@ public function __construct(mixed $value)
4643
false === $value,
4744
$value => [$value, Type::Boolean],
4845
$value instanceof DateTimeInterface => [self::filterDate($value), Type::Date],
49-
is_int($value) => [self::filterIntegerRange($value, 'Integer'), Type::Integer],
50-
is_float($value) => [self::filterDecimal($value), Type::Decimal],
51-
is_string($value) => [self::filterString($value), Type::String],
52-
default => throw new InvalidArgument('Unknown or unsupported type.')
53-
};
54-
}
55-
56-
/**
57-
* Filter a decimal according to RFC8941.
58-
*
59-
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-3.3.1
60-
*/
61-
private static function filterIntegerRange(int $value, string $type): int
62-
{
63-
return match (true) {
64-
Type::MAXIMUM_INT < abs($value) => throw new SyntaxError($type.' are limited to 15 digits.'),
65-
default => $value,
66-
};
67-
}
68-
69-
/**
70-
* Filter a decimal according to RFC8941.
71-
*
72-
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-3.3.2
73-
*/
74-
private static function filterDecimal(float $value): float
75-
{
76-
return match (true) {
77-
Type::MAXIMUM_FLOAT < abs(floor($value)) => throw new SyntaxError('The integer portion of decimals is limited to 12 digits.'),
78-
default => $value,
79-
};
80-
}
81-
82-
/**
83-
* Filter a decimal according to RFC8941.
84-
*
85-
* @see https://www.rfc-editor.org/rfc/rfc9651.html#section-3.3.3
86-
*/
87-
private static function filterString(string $value): string
88-
{
89-
return match (true) {
90-
1 === preg_match('/[^\x20-\x7E]/i', $value) => throw new SyntaxError('The string contains invalid characters.'),
91-
default => $value,
46+
default => [$value, Type::fromVariable($value)],
9247
};
9348
}
9449

@@ -99,9 +54,11 @@ private static function filterString(string $value): string
9954
*/
10055
private static function filterDate(DateTimeInterface $value): DateTimeImmutable
10156
{
102-
self::filterIntegerRange($value->getTimestamp(), 'Date timestamp');
103-
104-
return $value instanceof DateTimeImmutable ? $value : DateTimeImmutable::createFromInterface($value);
57+
return match (true) {
58+
!Type::Integer->supports($value->getTimestamp()) => throw new SyntaxError('Date timestamp are limited to 15 digits.'),
59+
!$value instanceof DateTimeImmutable => DateTimeImmutable::createFromInterface($value),
60+
default => $value,
61+
};
10562
}
10663

10764
/**

tests/ParametersTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use LogicException;
88
use PHPUnit\Framework\Attributes\DataProvider;
99
use PHPUnit\Framework\Attributes\Test;
10+
use TypeError;
1011

1112
final class ParametersTest extends StructuredFieldTestCase
1213
{
@@ -363,7 +364,7 @@ public function it_can_delete_a_member_via_array_access(): void
363364
#[Test]
364365
public function it_throws_if_the_structured_field_is_not_supported(): void
365366
{
366-
$this->expectException(InvalidArgument::class);
367+
$this->expectException(TypeError::class);
367368

368369
Parameters::fromPairs([['foo', InnerList::new(42)]]);
369370
}

0 commit comments

Comments
 (0)