10000 add new DatePointType Doctrine type · symfony/symfony@eee2339 · GitHub
[go: up one dir, main page]

Skip to content

Commit eee2339

Browse files
committed
add new DatePointType Doctrine type
1 parent 0461860 commit eee2339

File tree

5 files changed

+212
-0
lines changed

5 files changed

+212
-0
lines changed

src/Symfony/Bridge/Doctrine/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ CHANGELOG
1010
---
1111

1212
* Accept `ReadableCollection` in `CollectionToArrayTransformer`
13+
* Add support for `Symfony\Component\Clock\DatePoint` as `DatePointType` Doctrine type
1314

1415
7.1
1516
---
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass;
13+
14+
use Symfony\Bridge\Doctrine\Types\DatePointType;
15+
use Symfony\Component\Clock\DatePoint;
16+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
17+
use Symfony\Component\DependencyInjection\ContainerBuilder;
18+
19+
final class RegisterDatePointTypePass implements CompilerPassInterface
20+
{
21+
public function process(ContainerBuilder $container): void
22+
{
23+
if (!class_exists(DatePoint::class)) {
24+
return;
25+
}
26+
27+
if (!$container->hasParameter('doctrine.dbal.connection_factory.types')) {
28+
return;
29+
}
30+
31+
$typeDefinition = $container->getParameter('doctrine.dbal.connection_factory.types');
32+
33+
if (is_array($typeDefinition) && !isset($typeDefinition['date_point'])) {
34+
$typeDefinition['date_point'] = ['class' => DatePointType::class];
35+
}
36+
37+
$container->setParameter('doctrine.dbal.connection_factory.types', $typeDefinition);
38+
}
39+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Tests\DependencyInjection\CompilerPass;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterDatePointTypePass;
16+
use Symfony\Bridge\Doctrine\Types\DatePointType;
17+
use Symfony\Component\Clock\DatePoint;
18+
use Symfony\Component\DependencyInjection\ContainerBuilder;
19+
20+
class RegisterDatePointTypePassTest extends TestCase
21+
{
22+
protected function setUp(): void
23+
{
24+
if (!class_exists(DatePoint::class)) {
25+
self::markTestSkipped('The DatePoint class is not available.');
26+
}
27+
}
28+
29+
public function testRegistered()
30+
{
31+
$container = new ContainerBuilder();
32+
$container->setParameter('doctrine.dbal.connection_factory.types', ['foo' => 'bar']);
33+
(new RegisterDatePointTypePass())->process($container);
34+
35+
$expected = [
36+
'foo' => 'bar',
37+
'date_point' => ['class' => DatePointType::class],
38+
];
39+
$this->assertSame($expected, $container->getParameter('doctrine.dbal.connection_factory.types'));
40+
}
41+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Tests\Types;
13+
14+
use DateTimeImmutable;
15+
use Doctrine\DBAL\Platforms\AbstractPlatform;
16+
use Doctrine\DBAL\Platforms\MariaDBPlatform;
17+
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
18+
use Doctrine\DBAL\Platforms\SqlitePlatform;
19+
use Doctrine\DBAL\Types\ConversionException;
20+
use Doctrine\DBAL\Types\Type;
21+
use PHPUnit\Framework\TestCase;
22+
use Symfony\Bridge\Doctrine\Types\DatePointType;
23+
use Symfony\Component\Clock\DatePoint;
24+
25+
final class DatePointTypeTest extends TestCase
26+
{
27+
private DatePointType $type;
28+
29+
public static function setUpBeforeClass(): void
30+
{
31+
$name = DatePointType::NAME;
32+
if (Type::hasType($name)) {
33+
Type::overrideType($name, DatePointType::class);
34+
} else {
35+
Type::addType($name, DatePointType::class);
36+
}
37+
}
38+
39+
protected function setUp(): void
40+
{
41+
if (!class_exists(DatePoint::class)) {
42+
self::markTestSkipped('The DatePoint class is not available.');
43+
}
44+
$this->type = Type::getType(DatePointType::NAME);
45+
}
46+
47+
public function testDatePointConvertsToDatabaseValue()
48+
{
49+
$datePoint = new DatePoint('2025-03-03 12:13:14');
50+
51+
$expected = $datePoint->format('Y-m-d H:i:s');
52+
$actual = $this->type->convertToDatabaseValue($datePoint, new PostgreSQLPlatform());
53+
54+
$this->assertSame($expected, $actual);
55+
}
56+
57+
public function testDatePointConvertsToPHPValue()
58+
{
59+
$datePoint = new DatePoint();
60+
$actual = $this->type->convertToPHPValue($datePoint, new SqlitePlatform());
61+
62+
$this->assertSame($datePoint, $actual);
63+
}
64+
65+
public function testNullConvertsToPHPValue()
66+
{
67+
$actual = $this->type->convertToPHPValue(null, new SqlitePlatform());
68+
69+
$this->assertNull($actual);
70+
}
71+
72+
public function testDateTimeImmutableConvertsToPHPValue()
73+
{
74+
$format = 'Y-m-d H:i:s';
75+
$dateTime = new DateTimeImmutable('2025-03-03 12:13:14');
76+
$actual = $this->type->convertToPHPValue($dateTime, new SqlitePlatform());
77+
$expected = DatePoint::createFromInterface($dateTime);
78+
79+
$this->assertSame($expected->format($format), $actual->format($format));
80+
}
81+
82+
public function testGetName()
83+
{
84+
$this->assertSame('date_point', $this->type->getName());
85+
}
86+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\Doctrine\Types;
13+
14+
use DateTimeInterface;
15+
use Doctrine\DBAL\Platforms\AbstractPlatform;
16+
use Doctrine\DBAL\Types\DateTimeImmutableType;
17+
use Symfony\Component\Clock\DatePoint;
18+
19+
final class DatePointType extends DateTimeImmutableType
20+
{
21+
public const NAME = 'date_point';
22+
23+
/**
24+
* @param T $value
25+
*
26+
* @return (T is null ? null : DatePoint)
27+
*
28+
* @template T
29+
*/
30+
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?DatePoint
31+
{
32+
if (null === $value || $value instanceof DatePoint) {
33+
return $value;
34+
}
35+
36+
$value = parent::convertToPHPValue($value, $platform);
37+
38+
return DatePoint::createFromInterface($value);
39+
}
40+
41+
public function getName(): string
42+
{
43+
return self::NAME;
44+
}
45+
}

0 commit comments

Comments
 (0)
0