Skip to content

Commit 861d055

Browse files
committed
ChronosDate does not implement DateTimeInterface #9967
For coherence, we also update Chronos and cover everything with tests since we have more code than before.
1 parent 9aff229 commit 861d055

File tree

4 files changed

+186
-3
lines changed

4 files changed

+186
-3
lines changed

src/DBAL/Types/ChronosType.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,44 @@
77
use Cake\Chronos\Chronos;
88
use DateTimeInterface;
99
use Doctrine\DBAL\Platforms\AbstractPlatform;
10+
use Doctrine\DBAL\Types\ConversionException;
1011
use Doctrine\DBAL\Types\DateTimeType;
1112

1213
final class ChronosType extends DateTimeType
1314
{
1415
/**
15-
* @param null|DateTimeInterface|int|string $value
16+
* @return ($value is null ? null : string)
17+
*/
18+
public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string
19+
{
20+
if ($value === null) {
21+
return $value;
22+
}
23+
24+
if ($value instanceof DateTimeInterface) {
25+
return $value->format($platform->getDateTimeFormatString());
26+
}
27+
28+
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'Chronos']);
29+
}
30+
31+
/**
32+
* @return ($value is null ? null : Chronos)
1633
*/
1734
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?Chronos
1835
{
1936
if ($value === null || $value instanceof Chronos) {
2037
return $value;
2138
}
2239

40+
if (!is_string($value) && !$value instanceof DateTimeInterface) {
41+
throw ConversionException::conversionFailedFormat(
42+
$value,
43+
$this->getName(),
44+
$platform->getDateTimeFormatString(),
45+
);
46+
}
47+
2348
$val = new Chronos($value);
2449

2550
return $val;

src/DBAL/Types/DateType.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,44 @@
55
namespace Ecodev\Felix\DBAL\Types;
66

77
use Cake\Chronos\ChronosDate;
8-
use DateTimeInterface;
98
use Doctrine\DBAL\Platforms\AbstractPlatform;
9+
use Doctrine\DBAL\Types\ConversionException;
1010

1111
final class DateType extends \Doctrine\DBAL\Types\DateType
1212
{
1313
/**
14-
* @param null|ChronosDate|DateTimeInterface|string $value
14+
* @return ($value is null ? null : string)
15+
*/
16+
public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string
17+
{
18+
if ($value === null) {
19+
return $value;
20+
}
21+
22+
if ($value instanceof ChronosDate) {
23+
return $value->format($platform->getDateFormatString());
24+
}
25+
26+
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'ChronosDate']);
27+
}
28+
29+
/**
30+
* @return ($value is null ? null : ChronosDate)
1531
*/
1632
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?ChronosDate
1733
{
1834
if ($value === null || $value instanceof ChronosDate) {
1935
return $value;
2036
}
2137

38+
if (!is_string($value)) {
39+
throw ConversionException::conversionFailedFormat(
40+
$value,
41+
$this->getName(),
42+
$platform->getDateFormatString(),
43+
);
44+
}
45+
2246
$val = new ChronosDate($value);
2347

2448
return $val;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EcodevTests\Felix\DBAL\Types;
6+
7+
use Cake\Chronos\Chronos;
8+
use DateTimeImmutable;
9+
use Doctrine\DBAL\Platforms\AbstractPlatform;
10+
use Doctrine\DBAL\Platforms\MySQLPlatform;
11+
use Doctrine\DBAL\Types\ConversionException;
12+
use Ecodev\Felix\DBAL\Types\ChronosType;
13+
use PHPUnit\Framework\TestCase;
14+
15+
class ChronosTypeTest extends TestCase
16+
{
17+
private ChronosType $type;
18+
19+
private AbstractPlatform $platform;
20+
21+
protected function setUp(): void
22+
{
23+
$this->type = new ChronosType();
24+
$this->platform = new MySQLPlatform();
25+
}
26+
27+
public function testConvertToDatabaseValue(): void
28+
{
29+
self::assertSame('DATETIME', $this->type->getSqlDeclaration(['foo'], $this->platform));
30+
self::assertFalse($this->type->requiresSQLCommentHint($this->platform));
31+
32+
$actual = $this->type->convertToDatabaseValue(new Chronos('2016-01-01 15:58:59'), $this->platform);
33+
self::assertSame('2016-01-01 15:58:59', $actual, 'support Chronos');
34+
35+
$actual = $this->type->convertToDatabaseValue(new DateTimeImmutable('2016-01-01 15:58:59'), $this->platform);
36+
self::assertSame('2016-01-01 15:58:59', $actual, 'support DateTimeImmutable');
37+
38+
self::assertNull($this->type->convertToDatabaseValue(null, $this->platform), 'support null values');
39+
}
40+
41+
public function testConvertToPHPValue(): void
42+
{
43+
$actualPhp = $this->type->convertToPHPValue('2016-01-01 15:58:59', $this->platform);
44+
self::assertInstanceOf(Chronos::class, $actualPhp);
45+
self::assertSame('2016-01-01 15:58:59', $actualPhp->__toString(), 'support string');
46+
47+
$actualPhp = $this->type->convertToPHPValue(new Chronos('2016-01-01 15:58:59'), $this->platform);
48+
self::assertInstanceOf(Chronos::class, $actualPhp);
49+
self::assertSame('2016-01-01 15:58:59', $actualPhp->__toString(), 'support Chronos');
50+
51+
$actualPhp = $this->type->convertToPHPValue(new DateTimeImmutable('2016-01-01 15:58:59'), $this->platform);
52+
self::assertInstanceOf(Chronos::class, $actualPhp);
53+
self::assertSame('2016-01-01 15:58:59', $actualPhp->__toString(), 'support DateTimeImmutable');
54+
55+
self::assertNull($this->type->convertToPHPValue(null, $this->platform), 'support null values');
56+
}
57+
58+
public function testConvertToPHPValueThrowsWithInvalidValue(): void
59+
{
60+
$this->expectException(ConversionException::class);
61+
62+
$this->type->convertToPHPValue(123, $this->platform);
63+
}
64+
65+
public function testConvertToDatabaseValueThrowsWithInvalidValue(): void
66+
{
67+
$this->expectException(ConversionException::class);
68+
69+
$this->type->convertToDatabaseValue(123, $this->platform);
70+
}
71+
}

tests/DBAL/Types/DateTypeTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EcodevTests\Felix\DBAL\Types;
6+
7+
use Cake\Chronos\ChronosDate;
8+
use Doctrine\DBAL\Platforms\AbstractPlatform;
9+
use Doctrine\DBAL\Platforms\MySQLPlatform;
10+
use Doctrine\DBAL\Types\ConversionException;
11+
use Ecodev\Felix\DBAL\Types\DateType;
12+
use PHPUnit\Framework\TestCase;
13+
14+
class DateTypeTest extends TestCase
15+
{
16+
private DateType $type;
17+
18+
private AbstractPlatform $platform;
19+
20+
protected function setUp(): void
21+
{
22+
$this->type = new DateType();
23+
$this->platform = new MySQLPlatform();
24+
}
25+
26+
public function testConvertToDatabaseValue(): void
27+
{
28+
self::assertSame('DATE', $this->type->getSqlDeclaration(['foo'], $this->platform));
29+
self::assertFalse($this->type->requiresSQLCommentHint($this->platform));
30+
31+
$actual = $this->type->convertToDatabaseValue(new ChronosDate('2016-01-01'), $this->platform);
32+
self::assertSame('2016-01-01', $actual, 'support Chronos');
33+
34+
self::assertNull($this->type->convertToDatabaseValue(null, $this->platform), 'support null values');
35+
}
36+
37+
public function testConvertToPHPValue(): void
38+
{
39+
$actualPhp = $this->type->convertToPHPValue('2022-12-31', $this->platform);
40+
self::assertInstanceOf(ChronosDate::class, $actualPhp);
41+
self::assertSame('2022-12-31', $actualPhp->__toString(), 'support string');
42+
43+
$actualPhp = $this->type->convertToPHPValue(new ChronosDate('2022-12-31'), $this->platform);
44+
self::assertInstanceOf(ChronosDate::class, $actualPhp);
45+
self::assertSame('2022-12-31', $actualPhp->__toString(), 'support ChronosDate');
46+
47+
self::assertNull($this->type->convertToPHPValue(null, $this->platform), 'support null values');
48+
}
49+
50+
public function testConvertToPHPValueThrowsWithInvalidValue(): void
51+
{
52+
$this->expectException(ConversionException::class);
53+
54+
$this->type->convertToPHPValue(123, $this->platform);
55+
}
56+
57+
public function testConvertToDatabaseValueThrowsWithInvalidValue(): void
58+
{
59+
$this->expectException(ConversionException::class);
60+
61+
$this->type->convertToDatabaseValue(123, $this->platform);
62+
}
63+
}

0 commit comments

Comments
 (0)