ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilDateDurationInputGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(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  {
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  {
209  $lng = $this->lng;
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;
329  $lng = $this->lng;
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  {
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 }
parseCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
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...
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)
$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.
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
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:544
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:26
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 class represents a property that may include a sub form.
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