blob: fa0d5b00c9853f21723f1793e6b03bdcb39820f4 [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3/**
4 * Thanks to https://github.com/flaushi for his suggestion:
5 * https://github.com/doctrine/dbal/issues/2873#issuecomment-534956358
6 */
7namespace Carbon\Doctrine;
8
9use Carbon\Carbon;
10use Carbon\CarbonInterface;
11use DateTimeInterface;
12use Doctrine\DBAL\Platforms\AbstractPlatform;
13use Doctrine\DBAL\Types\ConversionException;
14use Exception;
15
16/**
17 * @template T of CarbonInterface
18 */
19trait CarbonTypeConverter
20{
21 /**
22 * @return class-string<T>
23 */
24 protected function getCarbonClassName(): string
25 {
26 return Carbon::class;
27 }
28
29 public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
30 {
31 $precision = ($fieldDeclaration['precision'] ?: 10) === 10
32 ? DateTimeDefaultPrecision::get()
33 : $fieldDeclaration['precision'];
34 $type = parent::getSQLDeclaration($fieldDeclaration, $platform);
35
36 if (!$precision) {
37 return $type;
38 }
39
40 if (str_contains($type, '(')) {
41 return preg_replace('/\(\d+\)/', "($precision)", $type);
42 }
43
44 [$before, $after] = explode(' ', "$type ");
45
46 return trim("$before($precision) $after");
47 }
48
49 /**
50 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
51 *
52 * @return T|null
53 */
54 public function convertToPHPValue($value, AbstractPlatform $platform)
55 {
56 $class = $this->getCarbonClassName();
57
58 if ($value === null || is_a($value, $class)) {
59 return $value;
60 }
61
62 if ($value instanceof DateTimeInterface) {
63 return $class::instance($value);
64 }
65
66 $date = null;
67 $error = null;
68
69 try {
70 $date = $class::parse($value);
71 } catch (Exception $exception) {
72 $error = $exception;
73 }
74
75 if (!$date) {
76 throw ConversionException::conversionFailedFormat(
77 $value,
78 $this->getName(),
79 'Y-m-d H:i:s.u or any format supported by '.$class.'::parse()',
80 $error
81 );
82 }
83
84 return $date;
85 }
86
87 /**
88 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
89 *
90 * @return string|null
91 */
92 public function convertToDatabaseValue($value, AbstractPlatform $platform)
93 {
94 if ($value === null) {
95 return $value;
96 }
97
98 if ($value instanceof DateTimeInterface) {
99 return $value->format('Y-m-d H:i:s.u');
100 }
101
102 throw ConversionException::conversionFailedInvalidType(
103 $value,
104 $this->getName(),
105 ['null', 'DateTime', 'Carbon']
106 );
107 }
108}