ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilDateDurationInputGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
28{
29 protected ilObjUser $user;
30
31 protected ?ilDateTime $start = null;
32 protected ?int $startyear = null;
33 protected ?string $start_text = null;
34 protected ?string $end_text = null;
35 protected int $minute_step_size = 5;
36 protected ?ilDateTime $end = null;
37 protected bool $showtime = false;
38 protected bool $toggle_fulltime = false;
39 protected string $toggle_fulltime_txt = '';
40 protected bool $toggle_fulltime_checked = false;
41 protected bool $allowOpenIntervals = false;
42 protected string $invalid_input_start = '';
43 protected string $invalid_input_end = '';
44
45 public function __construct(
46 string $a_title = "",
47 string $a_postvar = ""
48 ) {
49 global $DIC;
50
51 $this->lng = $DIC->language();
52 $this->user = $DIC->user();
53 parent::__construct($a_title, $a_postvar);
54 $this->setType("dateduration");
55 }
56
57 // Enable toggling between date and time
58 public function enableToggleFullTime(
59 string $a_title,
60 bool $a_checked
61 ): void {
62 $this->toggle_fulltime_txt = $a_title;
63 $this->toggle_fulltime_checked = $a_checked;
64 $this->toggle_fulltime = true;
65 }
66
67 public function enabledToggleFullTime(): bool
68 {
69 return $this->toggle_fulltime;
70 }
71
81 public function setStart(?ilDateTime $a_date = null): void
82 {
83 $this->start = $a_date;
84 }
85
86 public function setStartText(string $a_txt): void
87 {
88 $this->start_text = $a_txt;
89 }
90
91 public function getStartText(): ?string
92 {
93 return $this->start_text;
94 }
95
96 public function setEndText(string $a_txt): void
97 {
98 $this->end_text = $a_txt;
99 }
100
101 public function getEndText(): ?string
102 {
103 return $this->end_text;
104 }
105
106 public function getStart(): ?ilDateTime
107 {
108 return $this->start;
109 }
110
120 public function setEnd(?ilDateTime $a_date = null): void
121 {
122 $this->end = $a_date;
123 }
124
125 public function getEnd(): ?ilDateTime
126 {
127 return $this->end;
128 }
129
130 public function setShowTime(bool $a_showtime): void
131 {
132 $this->showtime = $a_showtime;
133 }
134
135 public function getShowTime(): bool
136 {
137 return $this->showtime;
138 }
139
140 public function setStartYear(int $a_year): void
141 {
142 $this->startyear = $a_year;
143 }
144
145 public function getStartYear(): ?int
146 {
147 return $this->startyear;
148 }
149
155 public function setMinuteStepSize(int $a_step_size): void
156 {
157 $this->minute_step_size = $a_step_size;
158 }
159
163 public function getMinuteStepSize(): int
164 {
165 return 1;
166 }
167
168 public function setValueByArray(array $a_values): void
169 {
170 $incoming = $a_values[$this->getPostVar()] ?? [];
171 if (is_array($incoming) && $incoming !== []) {
172 $format = isset($incoming['tgl']) ? 0 : $this->getDatePickerTimeFormat();
173 $this->toggle_fulltime_checked = (bool) ($incoming['tgl'] ?? false);
174
175 if ($this->openIntervalsAllowed()) {
176 if (isset($incoming['start']) && is_string($incoming['start']) && trim($incoming['start']) !== '') {
177 $this->setStart(ilCalendarUtil::parseIncomingDate($incoming["start"], (bool) $format));
178 } else {
179 $this->setStart(new ilDate(null, IL_CAL_UNIX));
180 }
181
182 if (isset($incoming['end']) && is_string($incoming['end']) && trim($incoming['end']) !== '') {
183 $this->setEnd(ilCalendarUtil::parseIncomingDate($incoming["end"], (bool) $format));
184 } else {
185 $this->setEnd(new ilDate(null, IL_CAL_UNIX));
186 }
187 } else {
188 # 0033160
189 if ($incoming['start'] instanceof ilDateTime) {
190 $this->setStart($incoming['start']);
191 } else {
192 $this->setStart(ilCalendarUtil::parseIncomingDate((string) $incoming["start"], (bool) $format));
193 }
194 if ($incoming['end'] instanceof ilDateTime) {
195 $this->setEnd($incoming['end']);
196 } else {
197 $this->setEnd(ilCalendarUtil::parseIncomingDate((string) $incoming["end"], (bool) $format));
198 }
199 }
200 }
201
202 foreach ($this->getSubItems() as $item) {
203 $item->setValueByArray($a_values);
204 }
205 }
206
207 public function checkInput(): bool
208 {
210
211 if ($this->getDisabled()) {
212 return true;
213 }
214
215 $post = $this->strArray($this->getPostVar());
216
217 $start = $post["start"] ?? '';
218 $end = $post["end"] ?? '';
219
220 // if full day is active, ignore time format
221 $format = isset($post['tgl'])
222 ? 0
223 : $this->getDatePickerTimeFormat();
224
225 // always done to make sure there are no obsolete values left
226 $this->setStart();
227 $this->setEnd();
228
229 $valid_start = false;
230 if (trim($start)) {
231 $parsed = ilCalendarUtil::parseIncomingDate($start, (bool) $format);
232 if ($parsed) {
233 $this->setStart($parsed);
234 $valid_start = true;
235 }
236 } elseif (!$this->getRequired() && !trim($end)) {
237 $valid_start = true;
238 } elseif ($this->openIntervalsAllowed() && !strlen(trim($start))) {
239 $valid_start = true;
240 }
241
242 $valid_end = false;
243 if (trim($end)) {
244 $parsed = ilCalendarUtil::parseIncomingDate($end, (bool) $format);
245 if ($parsed) {
246 $this->setEnd($parsed);
247 $valid_end = true;
248 }
249 } elseif (!$this->getRequired() && !trim($start)) {
250 $valid_end = true;
251 } elseif ($this->openIntervalsAllowed() && !strlen(trim($end))) {
252 $valid_end = true;
253 }
254
255 if ($this->getStartYear()) {
256 if ($valid_start &&
257 $this->getStart()->get(IL_CAL_FKT_DATE, "Y") < $this->getStartYear()) {
258 $valid_start = false;
259 }
260 if ($valid_end &&
261 $this->getEnd()->get(IL_CAL_FKT_DATE, "Y") < $this->getStartYear()) {
262 $valid_end = false;
263 }
264 }
265 $valid = ($valid_start && $valid_end);
266
267 if ($valid &&
268 $this->getStart() &&
269 $this->getEnd() &&
270 ilDateTime::_after($this->getStart(), $this->getEnd())) {
271 $valid = false;
272 }
273
274 if ($this->openIntervalsAllowed()) {
275 $valid = true;
276 } elseif (!$valid) {
277 $this->invalid_input_start = $start;
278 $this->invalid_input_end = $end;
279 $this->setAlert($lng->txt("form_msg_wrong_date"));
280 }
281
282 if ($valid) {
283 $valid = $this->checkSubItemsInput();
284 }
285
286 return $valid;
287 }
288
289 public function getInput(): array
290 {
291 $ret = $this->strArray($this->getPostVar());
292
293 if ($this->openIntervalsAllowed()) {
294 if (!$this->getStart()) {
295 $ret["start"] = null;
296 }
297
298 if (!$this->getEnd()) {
299 $ret["end"] = null;
300 }
301 } elseif (
302 !$this->getStart() ||
303 !$this->getEnd()
304 ) {
305 $ret["start"] = null;
306 $ret["end"] = null;
307 }
308 $ret["fullday"] = (bool) ($ret["tgl"] ?? false);
309 return $ret;
310 }
311
312 protected function getDatePickerTimeFormat(): int
313 {
314 return (int) $this->getShowTime();
315 }
316
317 protected function getDatetimeFormatForInput(): string
318 {
319 $format = 'Y-m-d';
320 if ($this->getShowTime()) {
321 $format .= '\TH:i';
322 }
323 return $format;
324 }
325
326 public function render(): string
327 {
328 $ilUser = $this->user;
330 $toggle_id = null;
331
332 $tpl = new ilTemplate("tpl.prop_datetime_duration.html", true, true, "components/ILIAS/Form");
333
334 if ($this->enabledToggleFullTime()) {
335 $this->setShowTime(true);
336
337 $toggle_id = 't' . md5($this->getPostVar() . '_fulltime'); // :TODO: unique?
338
339 $tpl->setCurrentBlock('toggle_fullday');
340 $tpl->setVariable('DATE_TOGGLE_ID', $this->getPostVar() . '[tgl]');
341 $tpl->setVariable('FULLDAY_TOGGLE_ID', $toggle_id);
342 $tpl->setVariable('FULLDAY_TOGGLE_CHECKED', $this->toggle_fulltime_checked ? 'checked="checked"' : '');
343 $tpl->setVariable('FULLDAY_TOGGLE_DISABLED', $this->getDisabled() ? 'disabled="disabled"' : '');
344 $tpl->setVariable('TXT_TOGGLE_FULLDAY', $this->toggle_fulltime_txt);
345 $tpl->parseCurrentBlock();
346 }
347
348 // config picker
349 if (!$this->getDisabled()) {
350 // :TODO: unique?
351 $picker_start_id = 'p' . md5($this->getPostVar() . '_start');
352 $picker_end_id = 'p' . md5($this->getPostVar() . '_end');
353
354 $tpl->setVariable('DATEPICKER_START_ID', $picker_start_id);
355 $tpl->setVariable('DATEPICKER_END_ID', $picker_end_id);
356
357 $this->global_tpl->addOnLoadCode(
358 'il.Form.initDateDurationPicker("' .
359 $picker_start_id . '","' .
360 $picker_end_id . '","' .
361 $toggle_id .
362 '");'
363 );
364 } else {
365 $tpl->setVariable('DATEPICKER_START_DISABLED', 'disabled="disabled" ');
366 $tpl->setVariable('DATEPICKER_END_DISABLED', 'disabled="disabled" ');
367 }
368
369 $type = 'date';
370 if ($this->getShowTime()) {
371 $type = 'datetime-local';
372 }
373 $tpl->setVariable('DATEPICKER_START_TYPE', $type);
374 $tpl->setVariable('DATEPICKER_END_TYPE', $type);
375
376 $start_txt = $this->getStartText();
377 if ($start_txt === null) {
378 $start_txt = $lng->txt("form_date_duration_start");
379 }
380 if (trim($start_txt)) {
381 $tpl->setVariable('START_LABEL', $start_txt);
382 $tpl->setVariable('START_ARIA_LABEL', ilLegacyFormElementsUtil::prepareFormOutput($start_txt));
383 $tpl->touchBlock('start_width_bl');
384 }
385
386 $end_txt = $this->getEndText();
387 if ($end_txt === null) {
388 $end_txt = $lng->txt("form_date_duration_end");
389 }
390 if (trim($end_txt)) {
391 $tpl->setVariable('END_LABEL', $end_txt);
392 $tpl->setVariable('END_ARIA_LABEL', ilLegacyFormElementsUtil::prepareFormOutput($end_txt));
393 $tpl->touchBlock('end_width_bl');
394 }
395
396
397 $tpl->setVariable('DATE_START_ID', $this->getPostVar() . '[start]');
398 $tpl->setVariable('DATE_END_ID', $this->getPostVar() . '[end]');
399
400 /*
401 * For date input, step is in days, for datetime-local
402 * it is in seconds.
403 */
404 $step_size = 60;
405 if (!$this->getShowTime()) {
406 $step_size = 1;
407 }
408 $tpl->setVariable('DATEPICKER_START_STEP', $step_size);
409 $tpl->setVariable('DATEPICKER_END_STEP', $step_size);
410
411 if ($this->getStartYear()) {
412 $min = DateTimeImmutable::createFromFormat(
413 'Y',
414 (string) $this->getStartYear()
415 )->format($this->getDatetimeFormatForInput());
416 $tpl->setVariable('DATEPICKER_START_MIN', $min);
417 $tpl->setVariable('DATEPICKER_END_MIN', $min);
418 }
419
420 // values
421
422 $out_format = $this->getDatetimeFormatForInput();
423 $date_value = $this->prepareInvalidInputAsValue($this->invalid_input_start);
424 if (!$date_value &&
425 $this->getStart()) {
426 $date_value = $this->getStart()->get(IL_CAL_FKT_DATE, $out_format, $ilUser->getTimeZone());
427 }
428 $tpl->setVariable('DATEPICKER_START_VALUE', $date_value);
429
430 $date_value = $this->prepareInvalidInputAsValue($this->invalid_input_end);
431 if (!$date_value &&
432 $this->getEnd()) {
433 $date_value = $this->getEnd()->get(IL_CAL_FKT_DATE, $out_format, $ilUser->getTimeZone());
434 }
435 $tpl->setVariable('DATEPICKER_END_VALUE', $date_value);
436
437 if ($this->getRequired()) {
438 $tpl->setVariable("START_REQUIRED", "required=\"required\"");
439 $tpl->setVariable("END_REQUIRED", "required=\"required\"");
440 }
441
442 return $tpl->get();
443 }
444
445 protected function prepareInvalidInputAsValue(string $invalid_input): string
446 {
447 $timestamp = strtotime(htmlspecialchars($invalid_input));
448 if ($timestamp === false) {
449 return '';
450 }
451 return date($this->getDatetimeFormatForInput(), $timestamp);
452 }
453
454
455 public function insert(ilTemplate $a_tpl): void
456 {
457 $html = $this->render();
458
459 $a_tpl->setCurrentBlock("prop_generic");
460 $a_tpl->setVariable("PROP_GENERIC", $html);
461 $a_tpl->parseCurrentBlock();
462 }
463
464 public function getTableFilterHTML(): string
465 {
466 return $this->render();
467 }
468
469 public function getValue(): array
470 {
471 return array(
472 'start' => $this->getStart() ? $this->getStart()->get(IL_CAL_UNIX) : null,
473 'end' => $this->getEnd() ? $this->getEnd()->get(IL_CAL_UNIX) : null
474 );
475 }
476
483 public function setValue($value): void
484 {
485 if (is_array($value)) {
486 $this->setStart(new ilDateTime($value['start'], IL_CAL_UNIX));
487 $this->setEnd(new ilDateTime($value['end'], IL_CAL_UNIX));
488 }
489 }
490
491 public function hideSubForm(): bool
492 {
493 if ($this->invalid_input_start ||
494 $this->invalid_input_end) {
495 return false;
496 }
497
498 return ((!$this->getStart() || $this->getStart()->isNull()) &&
499 (!$this->getEnd() || $this->getEnd()->isNull()));
500 }
501
502 public function openIntervalsAllowed(): bool
503 {
504 return $this->allowOpenIntervals;
505 }
506
507 public function setAllowOpenIntervals(bool $allowOpenInterval): void
508 {
509 $this->allowOpenIntervals = $allowOpenInterval;
510 }
511
512 public function getTableFilterLabelFor(): string
513 {
514 return $this->getFieldId() . "[start]";
515 }
516
517 public function getFormLabelFor(): string
518 {
519 return $this->getFieldId() . "[start]";
520 }
521}
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:544
const IL_CAL_UNIX
const IL_CAL_FKT_DATE
static parseIncomingDate($value, bool $add_time=false)
Try to parse incoming value to date object.
input GUI for a time span (start and end date)
checkInput()
Check input, strip slashes etc.
setAllowOpenIntervals(bool $allowOpenInterval)
getTableFilterLabelFor()
Get label "for" attribute value.
__construct(string $a_title="", string $a_postvar="")
getMinuteStepSize()
Fixed to one minute increments, see https://mantis.ilias.de/view.php?id=42740.
getFormLabelFor()
Get label "for" attribute value for form.
setMinuteStepSize(int $a_step_size)
Set minute step size E.g 5 => The selection will only show 00,05,10... minutes.
setValue($value)
Called from table gui with the stored session value Attention: If the user resets the table filter,...
setEnd(?ilDateTime $a_date=null)
Set end date E.g $dt_form->setDate(new ilDateTime(time(),IL_CAL_UTC)); or $dt_form->setDate(new ilDat...
enableToggleFullTime(string $a_title, bool $a_checked)
setStart(?ilDateTime $a_date=null)
Set start date E.g $dt_form->setDate(new ilDateTime(time(),IL_CAL_UTC)); or $dt_form->setDate(new ilD...
getTableFilterHTML()
Get input item HTML to be inserted into table filters.
prepareInvalidInputAsValue(string $invalid_input)
@classDescription Date and time handling
static _after(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is after end This method does not consider tz offsets.
Class for single dates.
static prepareFormOutput($a_str, bool $a_strip=false)
User class.
This class represents a property that may include a sub form.
special template class to simplify handling of ITX/PEAR
setCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
parseCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
$valid
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$post
Definition: ltitoken.php:46
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
global $lng
Definition: privfeed.php:31
global $DIC
Definition: shib_login.php:26