1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of Railt package. |
4
|
|
|
* |
5
|
|
|
* For the full copyright and license information, please view the LICENSE |
6
|
|
|
* file that was distributed with this source code. |
7
|
|
|
*/ |
8
|
|
|
declare(strict_types=1); |
9
|
|
|
|
10
|
|
|
namespace Railt\CarbonExtension; |
11
|
|
|
|
12
|
|
|
use Carbon\Carbon; |
13
|
|
|
use Railt\CarbonExtension\Exception\InvalidDateTimeFormat; |
14
|
|
|
use Railt\Http\InputInterface; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Class Controller |
18
|
|
|
*/ |
19
|
|
|
class Controller |
20
|
|
|
{ |
21
|
|
|
/** |
22
|
|
|
* Simple Date format. |
23
|
|
|
* Example: `2005-08-15` |
24
|
|
|
*/ |
25
|
|
|
private const DATE = 'DATE'; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Simple Time format. |
29
|
|
|
* Example: `15:52:01` |
30
|
|
|
*/ |
31
|
|
|
private const TIME = 'TIME'; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* Simple DateTime format. |
35
|
|
|
* Example: `2005-08-15 15:52:01` |
36
|
|
|
*/ |
37
|
|
|
private const DATE_TIME = 'DATE_TIME'; |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* RFC 7231 date format. |
41
|
|
|
* Example: `Mon, 15 Aug 2005 15:52:01 GMT` |
42
|
|
|
*/ |
43
|
|
|
private const RFC7231 = 'RFC7231'; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* ISO-8601 date format. |
47
|
|
|
* Example: `2005-08-15T15:52:01+00:00` |
48
|
|
|
* |
49
|
|
|
* Note: This format is an alias of the RFC 3339 specification: |
50
|
|
|
* @see https://www.iso.org/iso-8601-date-and-time-format.html |
51
|
|
|
* @see https://www.ietf.org/rfc/rfc3339.txt |
52
|
|
|
*/ |
53
|
|
|
private const ISO8601 = 'ISO8601'; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* Human readable string. |
57
|
|
|
* Example: `2 days ago` |
58
|
|
|
*/ |
59
|
|
|
private const HUMAN_READABLE = 'HUMAN_READABLE'; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @param InputInterface $input |
63
|
|
|
* @return string |
64
|
|
|
* @throws \InvalidArgumentException |
65
|
|
|
*/ |
66
|
|
|
public function getDateTime(InputInterface $input): string |
67
|
|
|
{ |
68
|
|
|
return $this->format($this->extract($input), $input->get('format')); |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* @param \DateTimeInterface|\DateInterval $date |
73
|
|
|
* @param string $format |
74
|
|
|
* @return string |
75
|
|
|
* @throws \InvalidArgumentException |
76
|
|
|
* @throws \Symfony\Component\Translation\Exception\InvalidArgumentException |
77
|
|
|
*/ |
78
|
|
|
private function format($date, string $format): string |
79
|
|
|
{ |
80
|
|
|
switch ($format) { |
81
|
|
|
/** |
82
|
|
|
* Compatibility bugfix. |
83
|
|
|
* @see http://php.net/manual/en/class.datetime.php |
84
|
|
|
*/ |
85
|
|
|
case self::ISO8601: |
86
|
|
|
return $date->format(Carbon::RFC3339); |
87
|
|
|
|
88
|
|
|
case self::RFC7231: |
89
|
|
|
return $date->format(Carbon::RFC7231_FORMAT); |
90
|
|
|
|
91
|
|
|
case self::DATE_TIME: |
92
|
|
|
return $date->format('Y-m-d H:i:s'); |
93
|
|
|
|
94
|
|
|
case self::DATE: |
95
|
|
|
return $date->format('Y-m-d'); |
96
|
|
|
|
97
|
|
|
case self::TIME: |
98
|
|
|
return $date->format('H:i:s'); |
99
|
|
|
|
100
|
|
|
case self::HUMAN_READABLE && $date instanceof \DateTimeInterface: |
101
|
|
|
return Carbon::instance($date)->diffForHumans(); |
|
|
|
|
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
return $date->format(\constant(Carbon::class . '::' . $format)); |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @param InputInterface $input |
109
|
|
|
* @return Carbon |
110
|
|
|
* @throws \InvalidArgumentException |
111
|
|
|
*/ |
112
|
|
|
private function extract(InputInterface $input): Carbon |
113
|
|
|
{ |
114
|
|
|
$date = $input->getParent(); |
115
|
|
|
|
116
|
|
|
if ($date instanceof \DateTimeInterface) { |
117
|
|
|
return Carbon::instance($date); |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
$error = 'Return type of GraphQL DateTime must be an instance of DateTime, but %s given'; |
121
|
|
|
$type = \is_object($date) ? \get_class($date) : \strtolower(\gettype($date)); |
122
|
|
|
|
123
|
|
|
throw new \InvalidArgumentException(\sprintf($error, $type)); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* @param InputInterface $input |
128
|
|
|
* @return string |
129
|
|
|
* @throws \InvalidArgumentException |
130
|
|
|
*/ |
131
|
|
|
public function diff(InputInterface $input): string |
132
|
|
|
{ |
133
|
|
|
/** @var Carbon $value */ |
134
|
|
|
$value = $this->extract($input); |
135
|
|
|
|
136
|
|
|
/** @var Carbon $diff */ |
137
|
|
|
$diff = $this->extractDiff($input); |
138
|
|
|
|
139
|
|
|
/** @var string $format */ |
140
|
|
|
$format = $input->get('format'); |
141
|
|
|
|
142
|
|
|
return $format === self::HUMAN_READABLE |
143
|
|
|
? $value->diffForHumans($diff) |
144
|
|
|
: $this->format($value->diff($diff), $format); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* @param InputInterface $input |
149
|
|
|
* @return Carbon |
150
|
|
|
* @throws InvalidDateTimeFormat |
151
|
|
|
* @throws \InvalidArgumentException |
152
|
|
|
*/ |
153
|
|
|
private function extractDiff(InputInterface $input): Carbon |
154
|
|
|
{ |
155
|
|
|
if ($input->has('with')) { |
156
|
|
|
try { |
157
|
|
|
return Carbon::parse($input->get('with')); |
158
|
|
|
} catch (\Throwable $e) { |
159
|
|
|
throw new InvalidDateTimeFormat('Invalid DateTime format passed in "with" argument'); |
160
|
|
|
} |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
return Carbon::now($this->extract($input)->getTimezone()); |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
|
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.