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