Skip to content

Commit d937631

Browse files
Improve error handling
1 parent 7c94c0e commit d937631

File tree

8 files changed

+94
-25
lines changed

8 files changed

+94
-25
lines changed

src/MartinGeorgiev/Doctrine/DBAL/Types/BaseRangeType.php

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
namespace MartinGeorgiev\Doctrine\DBAL\Types;
66

77
use Doctrine\DBAL\Platforms\AbstractPlatform;
8-
use Doctrine\DBAL\Types\Type;
98
use MartinGeorgiev\Doctrine\DBAL\Types\Exceptions\InvalidRangeForDatabaseException;
9+
use MartinGeorgiev\Doctrine\DBAL\Types\Exceptions\InvalidRangeForPHPException;
1010
use MartinGeorgiev\Doctrine\DBAL\Types\ValueObject\Range;
1111

1212
/**
@@ -18,18 +18,8 @@
1818
*
1919
* @author Martin Georgiev <martin.georgiev@gmail.com>
2020
*/
21-
abstract class BaseRangeType extends Type
21+
abstract class BaseRangeType extends BaseType
2222
{
23-
public function getName(): string
24-
{
25-
return static::TYPE_NAME;
26-
}
27-
28-
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
29-
{
30-
return static::TYPE_NAME;
31-
}
32-
3323
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
3424
{
3525
if ($value === null) {
@@ -55,7 +45,7 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?Range
5545
}
5646

5747
if (!\is_string($value)) {
58-
throw InvalidRangeForDatabaseException::forInvalidType($value);
48+
throw InvalidRangeForPHPException::forInvalidType($value);
5949
}
6050

6151
if ($value === '') {
@@ -65,7 +55,7 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?Range
6555
try {
6656
return $this->createFromString($value);
6757
} catch (\InvalidArgumentException) {
68-
throw InvalidRangeForDatabaseException::forInvalidFormat($value);
58+
throw InvalidRangeForPHPException::forInvalidFormat($value);
6959
}
7060
}
7161

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MartinGeorgiev\Doctrine\DBAL\Types\Exceptions;
6+
7+
use Doctrine\DBAL\Types\ConversionException;
8+
9+
/**
10+
* Exception thrown when an invalid PHP value is provided for range creation.
11+
*
12+
* @since 3.3
13+
*
14+
* @author Martin Georgiev <martin.georgiev@gmail.com>
15+
*/
16+
class InvalidRangeForPHPException extends ConversionException
17+
{
18+
private static function create(string $message, mixed $value): self
19+
{
20+
return new self(\sprintf($message, \var_export($value, true)));
21+
}
22+
23+
public static function forInvalidNumericBound(mixed $value): self
24+
{
25+
return self::create('Range bound must be numeric, %s given', $value);
26+
}
27+
28+
public static function forInvalidIntegerBound(mixed $value): self
29+
{
30+
return self::create('Range bound must be an integer, %s given', $value);
31+
}
32+
33+
public static function forInvalidDateTimeBound(mixed $value): self
34+
{
35+
return self::create('Range bound must be a DateTimeInterface instance, %s given', $value);
36+
}
37+
38+
public static function forInvalidType(mixed $value): self
39+
{
40+
return self::create('Invalid database value type for range conversion. Expected string, %s given', $value);
41+
}
42+
43+
public static function forInvalidFormat(string $value): self
44+
{
45+
return new self(\sprintf('Invalid range format from database: %s', $value));
46+
}
47+
}

src/MartinGeorgiev/Doctrine/DBAL/Types/ValueObject/BaseIntegerRange.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44

55
namespace MartinGeorgiev\Doctrine\DBAL\Types\ValueObject;
66

7+
use MartinGeorgiev\Doctrine\DBAL\Types\Exceptions\InvalidRangeForPHPException;
8+
79
/**
810
* Base class for PostgreSQL integer range types.
911
*
12+
* @extends Range<int>
13+
*
1014
* @since 3.3
1115
*
1216
* @author Martin Georgiev <martin.georgiev@gmail.com>
@@ -30,6 +34,10 @@ protected function compareBounds(mixed $a, mixed $b): int
3034

3135
protected function formatValue(mixed $value): string
3236
{
37+
if (!\is_int($value)) {
38+
throw InvalidRangeForPHPException::forInvalidIntegerBound($value);
39+
}
40+
3341
return (string) $value;
3442
}
3543

src/MartinGeorgiev/Doctrine/DBAL/Types/ValueObject/BaseTimestampRange.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,13 @@
44

55
namespace MartinGeorgiev\Doctrine\DBAL\Types\ValueObject;
66

7+
use MartinGeorgiev\Doctrine\DBAL\Types\Exceptions\InvalidRangeForPHPException;
8+
79
/**
810
* Base class for PostgreSQL timestamp range types.
911
*
12+
* @extends Range<\DateTimeInterface>
13+
*
1014
* @since 3.3
1115
*
1216
* @author Martin Georgiev <martin.georgiev@gmail.com>
@@ -25,6 +29,14 @@ public function __construct(
2529

2630
protected function compareBounds(mixed $a, mixed $b): int
2731
{
32+
if (!$a instanceof \DateTimeInterface) {
33+
throw InvalidRangeForPHPException::forInvalidDateTimeBound($a);
34+
}
35+
36+
if (!$b instanceof \DateTimeInterface) {
37+
throw InvalidRangeForPHPException::forInvalidDateTimeBound($b);
38+
}
39+
2840
$timestampComparison = $a->getTimestamp() <=> $b->getTimestamp();
2941
if ($timestampComparison !== 0) {
3042
return $timestampComparison;

src/MartinGeorgiev/Doctrine/DBAL/Types/ValueObject/DateRange.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace MartinGeorgiev\Doctrine\DBAL\Types\ValueObject;
66

7+
use MartinGeorgiev\Doctrine\DBAL\Types\Exceptions\InvalidRangeForPHPException;
8+
79
/**
810
* Represents a PostgreSQL DATERANGE (date range).
911
*
@@ -39,6 +41,14 @@ public function __construct(
3941

4042
protected function compareBounds(mixed $a, mixed $b): int
4143
{
44+
if (!$a instanceof \DateTimeInterface) {
45+
throw InvalidRangeForPHPException::forInvalidDateTimeBound($a);
46+
}
47+
48+
if (!$b instanceof \DateTimeInterface) {
49+
throw InvalidRangeForPHPException::forInvalidDateTimeBound($b);
50+
}
51+
4252
return $a->getTimestamp() <=> $b->getTimestamp();
4353
}
4454

src/MartinGeorgiev/Doctrine/DBAL/Types/ValueObject/NumericRange.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace MartinGeorgiev\Doctrine\DBAL\Types\ValueObject;
66

7+
use MartinGeorgiev\Doctrine\DBAL\Types\Exceptions\InvalidRangeForPHPException;
8+
79
/**
810
* Represents a PostgreSQL NUMRANGE (numeric range).
911
*
@@ -39,6 +41,14 @@ public function __construct(
3941

4042
protected function compareBounds(mixed $a, mixed $b): int
4143
{
44+
if (!\is_numeric($a)) {
45+
throw InvalidRangeForPHPException::forInvalidNumericBound($a);
46+
}
47+
48+
if (!\is_numeric($b)) {
49+
throw InvalidRangeForPHPException::forInvalidNumericBound($b);
50+
}
51+
4252
return (float) $a <=> (float) $b;
4353
}
4454

src/MartinGeorgiev/Doctrine/DBAL/Types/ValueObject/Range.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ abstract protected function compareBounds(mixed $a, mixed $b): int;
7575

7676
abstract protected function formatValue(mixed $value): string;
7777

78+
/**
79+
* @param string $rangeString The PostgreSQL range string (e.g., '[1,10)', 'empty')
80+
*/
7881
public static function fromString(string $rangeString): static
7982
{
8083
$rangeString = \trim($rangeString);
@@ -130,9 +133,6 @@ public function contains(mixed $target): bool
130133
return true;
131134
}
132135

133-
/**
134-
* Uses PostgreSQL's explicit empty state rather than mathematical tricks.
135-
*/
136136
public static function empty(): static
137137
{
138138
return new static(null, null, true, false, true);

tests/Unit/MartinGeorgiev/Doctrine/DBAL/Types/BaseRangeTestCase.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,6 @@ public function has_name(): void
3333
self::assertEquals($this->getExpectedTypeName(), $this->fixture->getName());
3434
}
3535

36-
#[Test]
37-
public function can_get_sql_declaration(): void
38-
{
39-
$result = $this->fixture->getSQLDeclaration([], $this->platform);
40-
41-
self::assertEquals($this->getExpectedSqlDeclaration(), $result);
42-
}
43-
4436
#[DataProvider('provideValidTransformations')]
4537
#[Test]
4638
public function can_transform_from_php_value(?Range $range, ?string $postgresValue): void

0 commit comments

Comments
 (0)