ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
ilCertificateDateHelperTest.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21use PHPUnit\Framework\Attributes\RunInSeparateProcess;
22use PHPUnit\Framework\Attributes\DataProvider;
23
25{
26 private const string USER_TIME_ZONE = 'Europe/Berlin';
27 private const string DEFAULT_TIME_ZONE = 'UTC';
28
29 private int $current_time;
30
31 protected function setUp(): void
32 {
33 parent::setUp();
34
35 class_exists('ilDateTime');
36
37 ilTimeZone::_setDefaultTimeZone(self::DEFAULT_TIME_ZONE);
38
39 $logger = $this->getMockBuilder(ilLogger::class)
40 ->disableOriginalConstructor()
41 ->getMock();
42
43 $logger_factory = $this->getMockBuilder(ilLoggerFactory::class)
44 ->disableOriginalConstructor()
45 ->onlyMethods(['getComponentLogger'])
46 ->getMock();
47 $logger_factory->method('getComponentLogger')->willReturn($logger);
48 $this->setGlobalVariable('ilLoggerFactory', $logger_factory);
49 $this->setGlobalVariable('lng', $this->getSystemLanguageMock());
50 $this->setGlobalVariable('ilUser', $this->getUserMock());
51 $this->current_time = time();
52 }
53
54 protected function tearDown(): void
55 {
57 parent::tearDown();
58 }
59
60 public static function dataProviderFormatDateWithDateFormat(): array
61 {
62 return [
63 [null, 'No date'],
64 ['2001-01-01', '1. Jan 2001'],
65 ['2001-01-01 00:00:00', '1. Jan 2001'],
66 [978307200, '1. Jan 2001'],
67 [0, 'No date'],
68 ['', 'No date'],
69 ];
70 }
71
72 #[DataProvider('dataProviderFormatDateWithDateFormat')]
73 public function testFormatDateWithDefaultFormat($input, $output): void
74 {
75 $helper = new ilCertificateDateHelper();
76 $this->assertEquals($output, $helper->formatDate($input));
77 }
78
79 public static function dataProviderFormatDateTimeWithDateTimeFormat(): array
80 {
81 return [
82 [null, 'No date'],
83 ['2001-01-01 00:00:00', '1. Jan 2001, 01:00'],
84 [978307200, '1. Jan 2001, 01:00'],
85 [0, 'No date'],
86 ['', 'No date'],
87 ];
88 }
89
90 #[DataProvider('dataProviderFormatDateTimeWithDateTimeFormat')]
91 public function testFormatDateTimeWithDefaultFormat($input, $output): void
92 {
93 $helper = new ilCertificateDateHelper();
94 $this->assertEquals($output, $helper->formatDateTime($input));
95 }
96
98 {
99 $used_relative_dates = ilDatePresentation::useRelativeDates();
100
101 $helper = new ilCertificateDateHelper();
102
103 $helper->formatDate('2001-01-01');
104 $this->assertEquals($used_relative_dates, ilDatePresentation::useRelativeDates());
105
107 $helper->formatDate('2001-01-01');
108 $this->assertTrue(ilDatePresentation::useRelativeDates());
109
111 $helper->formatDate('2001-01-01');
112 $this->assertFalse(ilDatePresentation::useRelativeDates());
113
114 ilDatePresentation::setUseRelativeDates($used_relative_dates);
115 }
116
117 public static function provideExplicitFormatCases(): array
118 {
119 $ts = 1757609100; // See snippet in: https://github.com/ILIAS-eLearning/ILIAS/pull/10084
120
121 class_exists('ilDateTime');
122
123 return [
124 'date: unix-int ok' => ['date', $ts, IL_CAL_UNIX, null, 'unix timestamp (int) accepted for date'],
125 'date: unix-string ok' => [
126 'date',
127 (string) $ts,
129 null,
130 'unix timestamp (string) accepted for date'
131 ],
132 'datetime: unix-int ok' => [
133 'datetime',
134 $ts,
136 null,
137 'unix timestamp (int) accepted for datetime'
138 ],
139 'datetime: unix-string ok' => [
140 'datetime',
141 (string) $ts,
143 null,
144 'unix timestamp (string) accepted for datetime'
145 ],
146
147 'date: negative-unix ok' => ['date', -1, IL_CAL_UNIX, null, 'negative unix timestamp accepted as int'],
148 'datetime: negative-unix ok' => [
149 'datetime',
150 -1,
152 null,
153 'negative unix timestamp accepted as int'
154 ],
155
156 'date: date ok' => ['date', '2025-09-12', IL_CAL_DATE, null, 'valid date string'],
157 'datetime: datetime ok' => [
158 'datetime',
159 '2025-09-12 20:30:00',
161 null,
162 'valid date-time string'
163 ],
164 'date: YYYYMMDD ok' => ['date', '20250912', IL_CAL_DATE, null, 'numeric YYYYMMDD is not treated as unix'],
165
166 'date: unix-string with DATE throws' => [
167 'date',
168 (string) $ts,
170 InvalidArgumentException::class,
171 'unix-like string with DATE format should be rejected'
172 ],
173 'datetime: unix-string with DATETIME throws' => [
174 'datetime',
175 (string) $ts,
177 InvalidArgumentException::class,
178 'unix-like string with DATETIME format should be rejected'
179 ],
180 'date: date with UNIX throws' => [
181 'date',
182 '2025-09-12',
184 InvalidArgumentException::class,
185 'non-numeric with UNIX should be rejected'
186 ],
187 'datetime: datetime with UNIX throws' => [
188 'datetime',
189 '2025-09-12 20:30:00',
191 InvalidArgumentException::class,
192 'non-numeric with UNIX should be rejected'
193 ],
194 ];
195 }
196
201 #[DataProvider('provideExplicitFormatCases')]
203 string $method,
204 $input,
205 int $format,
206 ?string $expected_exception,
207 string $why
208 ): void {
209 $helper = new ilCertificateDateHelper();
210
211 $cb = static function () use ($helper, $method, $input, $format) {
212 return $method === 'date'
213 ? $helper->formatDate($input, null, $format)
214 : $helper->formatDateTime($input, null, $format);
215 };
216
217 if ($expected_exception === null) {
218 $this->assertDoesNotThrow($cb, $why);
219 } else {
220 $this->assertThrows($cb, $expected_exception, null);
221 }
222 }
223
227 public static function dateFormattingMethodsProvider(): array
228 {
229 return [
230 'formatDateTime' => ['formatDateTime'],
231 'formatDate' => ['formatDate'],
232 ];
233 }
234
235 #[DataProvider('dateFormattingMethodsProvider')]
236 public function testCannotFormatNonDateString(string $method): void
237 {
238 $helper = new ilCertificateDateHelper();
239 $this->expectExceptionMessage('Cannot parse date: invalid-date');
240 $helper->$method('invalid-date');
241 }
242
243 #[RunInSeparateProcess]
244 public function testFormatDateWithUserLanguage(): void
245 {
246 $this->mockUserLanguageGerman();
247
248 $helper = new ilCertificateDateHelper();
249 $this->assertEquals('1. Mai 2001', $helper->formatDate('2001-05-01 01:30:59', $this->getUserMock()));
250 }
251
252 #[RunInSeparateProcess]
254 {
255 $this->mockUserLanguageGerman();
256
257 $helper = new ilCertificateDateHelper();
258 $this->assertEquals('1. Mai 2001, 03:30', $helper->formatDateTime('2001-05-01 01:30:59', $this->getUserMock()));
259 }
260
261 private function getUserMock(): ilObjUser
262 {
263 $user = $this->getMockBuilder(ilObjUser::class)
264 ->disableOriginalConstructor()
265 ->onlyMethods(['getTimeFormat', 'getLanguage', 'getTimeZone'])
266 ->getMock();
267 $user->method('getTimeFormat')->willReturn((string) ilCalendarSettings::TIME_FORMAT_24);
268 $user->method('getLanguage')->willReturn('de');
269 $user->method('getTimeZone')->willReturn(self::USER_TIME_ZONE);
270
271 return $user;
272 }
273
275 {
276 $lng = $this->getMockBuilder(ilLanguage::class)
277 ->onlyMethods(['txt', 'loadLanguageModule'])
278 ->disableOriginalConstructor()
279 ->getMock();
280 $lng->method('txt')->willReturnCallback(function (string $topic): string {
281 return match ($topic) {
282 'month_01_short' => 'Jan',
283 'month_01_long' => 'January',
284 'month_02_short' => 'Feb',
285 'month_03_short' => 'Mar',
286 'month_04_short' => 'Apr',
287 'month_05_short' => 'May',
288 'month_06_short' => 'Jun',
289 'month_07_short' => 'Jul',
290 'month_08_short' => 'Aug',
291 'month_09_short' => 'Sep',
292 'month_10_short' => 'Oct',
293 'month_11_short' => 'Nov',
294 'month_12_short' => 'Dec',
295 'no_date' => 'No date',
296 'today' => 'Today',
297 'yesterday' => 'Yesterday',
298 'tomorrow' => 'Tomorrow',
299 default => '-' . $topic . '-'
300 };
301 });
302
303 return $lng;
304 }
305
306 private function mockUserLanguageGerman(): void
307 {
308 if (!defined('ILIAS_LOG_ENABLED')) {
309 define('ILIAS_LOG_ENABLED', false);
310 }
311 if (!defined('ILIAS_ABSOLUTE_PATH')) {
312 define('ILIAS_ABSOLUTE_PATH', dirname(__FILE__, 5));
313 }
314
315 $ilClientIniFile = $this->getMockBuilder(ilIniFile::class)
316 ->disableOriginalConstructor()
317 ->getMock();
318 $this->setGlobalVariable('ilClientIniFile', $ilClientIniFile);
319
320 $ilDB = $this->createMock(ilDBInterface::class);
321 $ilDB->method('query')->willReturnCallback(function ($query): ilDBStatement {
322 $statement = $this->createMock(ilDBStatement::class);
323
324 if (str_contains($query, 'SELECT * FROM lng_modules')) {
325 $statement->method('numRows')->willReturn(1);
326 $statement->method('fetchRow')->willReturn([
327 'lang_array' => serialize([
328 'month_01_short' => 'Jan',
329 'month_01_long' => 'Januar',
330 'month_02_short' => 'Feb',
331 'month_03_short' => 'Mär',
332 'month_04_short' => 'Apr',
333 'month_05_short' => 'Mai',
334 'month_06_short' => 'Jun',
335 'month_07_short' => 'Jul',
336 'month_08_short' => 'Aug',
337 'month_09_short' => 'Sep',
338 'month_10_short' => 'Okt',
339 'month_11_short' => 'Nov',
340 'month_12_short' => 'Dez',
341 'no_date' => 'Kein Datum',
342 'today' => 'Heute',
343 'yesterday' => 'Gestern',
344 'tomorrow' => 'Morgen'
345 ]),
346 ]);
347 } else {
348 $statement->method('numRows')->willReturn(0);
349 $statement->method('fetchRow')->willReturn(false);
350 }
351
352 return $statement;
353 });
354
355 $this->setGlobalVariable('ilDB', $ilDB);
356 }
357}
const IL_CAL_DATE
const IL_CAL_UNIX
const IL_CAL_DATETIME
assertThrows(callable $cb, ?string $expected_class=null, ?string $expected_message=null)
@template T of Throwable
assertDoesNotThrow(callable $cb, string $message='')
setGlobalVariable(string $name, mixed $value)
testExplicitFormatsWorkAsExpected(string $method, $input, int $format, ?string $expected_exception, string $why)
formatDate($raw_date_input, ?ilObjUser $user=null, ?int $date_format=null)
static setUseRelativeDates(bool $a_status)
set use relative dates
language handling
User class.
static _restoreDefaultTimeZone()
static _setDefaultTimeZone(string $a_tz)
setGlobalVariable(string $name, mixed $value)
Interface ilDBStatement.
global $lng
Definition: privfeed.php:31