ILIAS  trunk Revision v12.0_alpha-1540-g00f839d5fa1
class.FormAdapterGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
26
31{
33
34 protected const DEFAULT_SECTION = "@internal_default_section";
35 protected string $submit_caption = "";
36 protected \ilLanguage $lng;
37 protected const ASYNC_NONE = 0;
38 protected const ASYNC_MODAL = 1;
39 protected const ASYNC_ON = 2;
40 protected \ILIAS\Data\Factory $data;
41 protected \ilObjUser $user;
42 protected string $last_key = "";
43 protected \ILIAS\Refinery\Factory $refinery;
44
45 protected string $title = "";
46 protected array $values = [];
47 protected array $disable = [];
48
49 protected ?array $raw_data = null;
50 protected \ILIAS\HTTP\Services $http;
51 protected \ilCtrlInterface $ctrl;
52 protected \ILIAS\DI\UIServices $ui;
53 protected array $fields = [];
54 protected array $field_path = [];
55 protected array $sections = [self::DEFAULT_SECTION => ["title" => "", "description" => "", "fields" => []]];
57 protected array $section_of_field = [];
58 protected ?array $class_path;
59 protected string $cmd = self::DEFAULT_SECTION;
60 protected ?Form\Standard $form = null;
61 protected array $upload_handler = [];
63 protected \ilGlobalTemplateInterface $main_tpl;
64 protected ?array $current_switch = null;
65 protected ?array $current_optional = null;
66 protected ?array $current_group = null;
67 protected static bool $initialised = false;
68
72 public function __construct(
73 ?array $class_path,
74 string $cmd,
75 string $submit_caption = ""
76 ) {
77 global $DIC;
78 $this->class_path = $class_path;
79 $this->cmd = $cmd;
80 $this->ui = $DIC->ui();
81 $this->ctrl = $DIC->ctrl();
82 $this->http = $DIC->http();
83 $this->lng = $DIC->language();
84 $this->refinery = $DIC->refinery();
85 $this->main_tpl = $DIC->ui()->mainTemplate();
86 $this->user = $DIC->user();
87 $this->data = new \ILIAS\Data\Factory();
88 $this->submit_caption = $submit_caption;
90 $this->initStdObjProperties($DIC);
91 $this->lng->loadLanguageModule("rep");
92 }
93
94 public static function getOnLoadCode(): string
95 {
96 return "il.repository.ui.init();\n" .
97 "il.repository.core.init('" . ILIAS_HTTP_PATH . "')";
98 }
99
100 public static function initJavascript(): void
101 {
102 global $DIC;
103
104 if (!isset($DIC["ui.factory"])) {
105 return;
106 }
107
108 $f = $DIC->ui()->factory();
109 $r = $DIC->ui()->renderer();
110 if (!self::$initialised) {
111 $main_tpl = $DIC->ui()->mainTemplate();
112 $debug = false;
113 if ($debug) {
114 $main_tpl->addJavaScript("../components/ILIAS/Repository/resources/repository.js");
115 } else {
116 $main_tpl->addJavaScript("assets/js/repository.js");
117 }
118
120
121 // render dummy components to load the necessary .js needed for async processing
122 $d = [];
123 $d[] = $f->input()->field()->text("");
124 $r->render($d);
125 self::$initialised = true;
126 }
127 }
128
129 public function asyncModal(): self
130 {
131 $this->async_mode = self::ASYNC_MODAL;
132 return $this;
133 }
134
135 public function async(): self
136 {
137 $this->async_mode = self::ASYNC_ON;
138 return $this;
139 }
140
141 public function syncModal(): self
142 {
143 return $this;
144 }
145
146 public function isSentAsync(): bool
147 {
148 return ($this->async_mode !== self::ASYNC_NONE);
149 }
150
151 public function getTitle(): string
152 {
153 return $this->title;
154 }
155
156 public function section(
157 string $key,
158 string $title,
159 string $description = ""
160 ): self {
161 if ($this->title == "") {
162 $this->title = $title;
163 }
164
165 $this->sections[$key] = [
166 "title" => $title,
167 "description" => $description,
168 "fields" => []
169 ];
170 $this->current_section = $key;
171 return $this;
172 }
173
174 public function text(
175 string $key,
176 string $title,
177 string $description = "",
178 ?string $value = null,
179 int $max_length = 0
180 ): self {
181 $this->values[$key] = $value;
182 $field = $this->ui->factory()->input()->field()->text($title, $description);
183 if ($max_length > 0) {
184 $field = $field->withMaxLength($max_length);
185 }
186 if (!is_null($value)) {
187 $field = $field->withValue($value);
188 }
189 $this->addField($key, $field);
190 return $this;
191 }
192
193 public function checkbox(
194 string $key,
195 string $title,
196 string $description = "",
197 ?bool $value = null,
198 ?bool $disabled = null
199 ): self {
200 $this->values[$key] = $value;
201 $field = $this->ui->factory()->input()->field()->checkbox($title, $description);
202 if (!is_null($value)) {
203 $field = $field->withValue($value);
204 }
205 if (!is_null($disabled)) {
206 $field = $field->withDisabled($disabled);
207 }
208 $this->addField($key, $field);
209 return $this;
210 }
211
212 public function hidden(
213 string $key,
214 string $value
215 ): self {
216 $this->values[$key] = $value;
217 $field = $this->ui->factory()->input()->field()->hidden();
218 $field = $field->withValue($value);
219 $this->addField($key, $field);
220 return $this;
221 }
222
223 public function required($required = true): self
224 {
225 if ($required && ($field = $this->getLastField())) {
226 if ($field instanceof \ILIAS\UI\Component\Input\Field\Text) {
227 $field = $field->withRequired(true, new NotEmpty(
228 new Factory(),
229 $this->lng
230 ));
231 } else {
232 $field = $field->withRequired(true);
233 }
234 $this->replaceLastField($field);
235 }
236 return $this;
237 }
238
239 public function disabled($disabled = true): self
240 {
241 if ($disabled && ($field = $this->getLastField())) {
242 $field = $field->withDisabled(true);
243 $this->disable[$this->last_key] = true;
244 $this->replaceLastField($field);
245 }
246 return $this;
247 }
248
249 public function textarea(
250 string $key,
251 string $title,
252 string $description = "",
253 ?string $value = null
254 ): self {
255 $this->values[$key] = $value;
256 $field = $this->ui->factory()->input()->field()->textarea($title, $description);
257 if (!is_null($value)) {
258 $field = $field->withValue($value);
259 }
260 $this->addField($key, $field);
261 return $this;
262 }
263
264 public function number(
265 string $key,
266 string $title,
267 string $description = "",
268 ?int $value = null,
269 ?int $min_value = null,
270 ?int $max_value = null
271 ): self {
272 $this->values[$key] = $value;
273 $trans = [];
274 if (!is_null($min_value)) {
275 $trans[] = $this->refinery->int()->isGreaterThanOrEqual($min_value);
276 }
277 if (!is_null($max_value)) {
278 $trans[] = $this->refinery->int()->isLessThanOrEqual($max_value);
279 }
280 $field = $this->ui->factory()->input()->field()->numeric($title, $description);
281 if (count($trans) > 0) {
282 $field = $field->withAdditionalTransformation($this->refinery->logical()->parallel($trans));
283 }
284 if (!is_null($value)) {
285 $field = $field->withValue($value);
286 }
287 $this->addField($key, $field);
288 return $this;
289 }
290
291 public function date(
292 string $key,
293 string $title,
294 string $description = "",
295 ?\ilDate $value = null
296 ): self {
297 $this->values[$key] = $value;
298 $field = $this->ui->factory()->input()->field()->dateTime($title, $description);
299
300 $format = $this->user->getDateFormat();
301 $dt_format = (string) $format;
302
303 $field = $field->withFormat($format);
304 if (!is_null($value)) {
305 $field = $field->withValue(
306 (new \DateTime($value->get(IL_CAL_DATE)))->format($dt_format)
307 );
308 }
309 $this->addField($key, $field);
310 return $this;
311 }
312
313 public function dateTime(
314 string $key,
315 string $title,
316 string $description = "",
317 ?\ilDateTime $value = null
318 ): self {
319 $this->values[$key] = $value;
320 $field = $this->ui->factory()->input()->field()->dateTime($title, $description)->withUseTime(true);
321
322 if ((int) $this->user->getTimeFormat() === \ilCalendarSettings::TIME_FORMAT_12) {
323 $dt_format = $this->data->dateFormat()->withTime12($this->user->getDateFormat());
324 } else {
325 $dt_format = $this->data->dateFormat()->withTime24($this->user->getDateFormat());
326 }
327 $field = $field->withFormat($dt_format);
328 if (!is_null($value) && !is_null($value->get(IL_CAL_DATETIME))) {
329 $field = $field->withValue(
330 (new \DateTime($value->get(IL_CAL_DATETIME)))->format(
331 ((string) $dt_format)
332 )
333 );
334 }
335 $this->addField($key, $field);
336 return $this;
337 }
338
339 public function dateTimeDuration(
340 string $key,
341 string $title,
342 string $description = "",
343 ?\ilDateTime $from = null,
344 ?\ilDateTime $to = null,
345 string $label_from = "",
346 string $label_to = ""
347 ): self {
348 $this->values[$key] = [$from, $to];
349 if ($label_from === "") {
350 $label_from = $this->lng->txt("rep_activation_limited_start");
351 }
352 if ($label_to === "") {
353 $label_to = $this->lng->txt("rep_activation_limited_end");
354 }
355 $field = $this->ui->factory()->input()->field()->duration($title, $description)->withUseTime(true)->withLabels($label_from, $label_to);
356
357 if ((int) $this->user->getTimeFormat() === \ilCalendarSettings::TIME_FORMAT_12) {
358 $dt_format = $this->data->dateFormat()->withTime12($this->user->getDateFormat());
359 } else {
360 $dt_format = $this->data->dateFormat()->withTime24($this->user->getDateFormat());
361 }
362 $field = $field->withFormat($dt_format);
363 $val_from = $val_to = null;
364 if (!is_null($from) && !is_null($from->get(IL_CAL_DATETIME))) {
365 $val_from = (new \DateTime(
366 $from->get(IL_CAL_DATETIME)
367 ))->format((string) $dt_format);
368 }
369 if (!is_null($to) && !is_null($to->get(IL_CAL_DATETIME))) {
370 $val_to = (new \DateTime(
371 $to->get(IL_CAL_DATETIME)
372 ))->format((string) $dt_format);
373 }
374 $field = $field->withValue([$val_from, $val_to]);
375 $this->addField($key, $field);
376 return $this;
377 }
378
379 protected function getDateTimeData(?\DateTimeImmutable $value, $use_time = false): \ilDate|\ilDateTime|null
380 {
381 if (is_null($value)) {
382 return null;
383 }
384 if ($use_time) {
385 return new \ilDateTime($value->format("Y-m-d H:i:s"), IL_CAL_DATETIME);
386 }
387 return new \ilDate($value->format("Y-m-d"), IL_CAL_DATE);
388 }
389
390 public function select(
391 string $key,
392 string $title,
393 array $options,
394 string $description = "",
395 ?string $value = null
396 ): self {
397 $this->values[$key] = $value;
398 $field = $this->ui->factory()->input()->field()->select($title, $options, $description);
399 if (!is_null($value)) {
400 $field = $field->withValue($value);
401 }
402 $this->addField(
403 $key,
404 $field
405 );
406 return $this;
407 }
408
409 public function radio(
410 string $key,
411 string $title,
412 string $description = "",
413 ?string $value = null
414 ): self {
415 $this->values[$key] = $value;
416 $field = $this->ui->factory()->input()->field()->radio($title, $description);
417 $this->addField(
418 $key,
419 $field
420 );
421 return $this;
422 }
423
424 public function radioOption(string $value, string $title, string $description = ""): self
425 {
426 if ($field = $this->getLastField()) {
427 $field = $field->withOption($value, $title, $description);
428 if (($this->values[$this->last_key] ?? null) === $value) {
429 $field = $field->withValue($value);
430 }
431 $this->replaceLastField($field);
432 }
433 return $this;
434 }
435
436 public function switch(
437 string $key,
438 string $title,
439 string $description = "",
440 ?string $value = null
441 ): self {
442 $this->values[$key] = $value;
443 $this->current_switch = [
444 "key" => $key,
445 "title" => $title,
446 "description" => $description,
447 "value" => $value,
448 "groups" => []
449 ];
450 return $this;
451 }
452
453 public function optional(
454 string $key,
455 string $title,
456 string $description = "",
457 ?bool $value = null
458 ): self {
459 $this->values[$key] = $value;
460 $this->current_optional = [
461 "key" => $key,
462 "title" => $title,
463 "description" => $description,
464 "value" => $value,
465 "group" => []
466 ];
467 return $this;
468 }
469
470 public function group(string $key, string $title, string $description = "", $disabled = false): self
471 {
472 $this->endCurrentGroup();
473 $this->current_group = [
474 "key" => $key,
475 "title" => $title,
476 "description" => $description,
477 "disabled" => $disabled,
478 "fields" => []
479 ];
480 return $this;
481 }
482
483 protected function endCurrentGroup(): void
484 {
485 if (!is_null($this->current_group)) {
486 if (!is_null($this->current_switch)) {
487 $fields = [];
488 foreach ($this->current_group["fields"] as $key) {
489 $fields[$key] = $this->fields[$key];
490 }
491 $this->current_switch["groups"][$this->current_group["key"]] =
492 $this->ui->factory()->input()->field()->group(
493 $fields,
494 $this->current_group["title"]
495 )->withByline($this->current_group["description"]);
496 if ($this->current_group["disabled"]) {
497 $this->current_switch["groups"][$this->current_group["key"]] =
498 $this->current_switch["groups"][$this->current_group["key"]]
499 ->withDisabled(true);
500 }
501 }
502 }
503 $this->current_group = null;
504 }
505
506 public function end(): self
507 {
508 $this->endCurrentGroup();
509 if (!is_null($this->current_switch)) {
510 $field = $this->ui->factory()->input()->field()->switchableGroup(
511 $this->current_switch["groups"],
512 $this->current_switch["title"],
513 $this->current_switch["description"]
514 );
515 if (!is_null($this->current_switch["value"])) {
516 $cvalue = $this->current_switch["value"];
517 if (isset($this->current_switch["groups"][$cvalue])) {
518 $field = $field->withValue($cvalue);
519 }
520 }
521 $key = $this->current_switch["key"];
522 $this->current_switch = null;
523 $this->addField($key, $field);
524 }
525 if (!is_null($this->current_optional)) {
526 $field = $this->ui->factory()->input()->field()->optionalGroup(
527 $this->current_optional["fields"],
528 $this->current_optional["title"],
529 $this->current_optional["description"]
530 );
531 if ($this->current_optional["value"]) {
532 $value = [];
533 foreach ($this->current_optional["fields"] as $key => $input) {
534 $value[$key] = $input->getValue();
535 }
536 $field = $field->withValue($value);
537 } else {
538 $field = $field->withValue(null);
539 }
540 $key = $this->current_optional["key"];
541 $this->current_optional = null;
542 $this->addField($key, $field);
543 }
544 return $this;
545 }
546
547 public function file(
548 string $key,
549 string $title,
550 \Closure $result_handler,
551 string $id_parameter,
552 string $description = "",
553 ?int $max_files = null,
554 array $mime_types = [],
555 array $ctrl_path = [],
556 string $logger_id = ""
557 ): self {
558 $this->upload_handler[$key] = new \ilRepoStandardUploadHandlerGUI(
559 $result_handler,
560 $id_parameter,
561 $logger_id,
562 $ctrl_path
563 );
564
565 foreach (["application/x-compressed", "application/x-zip-compressed"] as $zipmime) {
566 if (in_array("application/zip", $mime_types) &&
567 !in_array($zipmime, $mime_types)) {
568 $mime_types[] = $zipmime;
569 }
570 }
571
572 if (count($mime_types) > 0) {
573 $description .= $this->lng->txt("rep_allowed_types") . ": " .
574 implode(", ", $mime_types);
575 }
576
577 $field = $this->ui->factory()->input()->field()->file(
578 $this->upload_handler[$key],
579 $title,
580 $description
581 );
582 // not necessary, see https://github.com/ILIAS-eLearning/ILIAS/pull/9314
583 //->withMaxFileSize((int) \ilFileUtils::getPhpUploadSizeLimitInBytes());
584 if (!is_null($max_files)) {
585 $field = $field->withMaxFiles($max_files);
586 }
587 if (count($mime_types) > 0) {
588 $field = $field->withAcceptedMimeTypes($mime_types);
589 }
590
591 $this->addField(
592 $key,
593 $field
594 );
595 return $this;
596 }
597
599 {
600 if (!isset($this->upload_handler[$key])) {
601 throw new \ilException("Unknown file upload field: " . $key);
602 }
603 return $this->upload_handler[$key];
604 }
605
606
607 protected function addField(string $key, FormInput $field, $supress_0_key = false): void
608 {
609 if ($key === "") {
610 throw new \ilException("Missing Input Key: " . $key);
611 }
612 if (isset($this->field[$key])) {
613 throw new \ilException("Duplicate Input Key: " . $key);
614 }
615 $field_path = [];
616 if ($this->current_section !== self::DEFAULT_SECTION) {
617 $field_path[] = $this->current_section;
618 }
619 if (!is_null($this->current_group)) {
620 $this->current_group["fields"][] = $key;
621 if (!is_null($this->current_switch)) {
622 $field_path[] = $this->current_switch["key"];
623 $field_path[] = 1; // the value of subitems in SwitchableGroup are in the 1 key of the raw data
624 $field_path[] = $key;
625 }
626 } elseif (!is_null($this->current_optional)) {
627 $field_path[] = $this->current_optional["key"];
628 $this->current_optional["fields"][$key] = $field;
629 $field_path[] = $key;
630 } else {
631 $this->sections[$this->current_section]["fields"][] = $key;
632 $field_path[] = $key;
633 if ($field instanceof \ILIAS\UI\Component\Input\Field\SwitchableGroup) {
634 $field_path[] = 0; // the value of the SwitchableGroup is in the 0 key of the raw data
635 }
636 if ($field instanceof \ILIAS\UI\Component\Input\Field\OptionalGroup) {
637 //$field_path[] = 0; // the value of the SwitchableGroup is in the 0 key of the raw data
638 }
639 if ($field instanceof \ILIAS\UI\Component\Input\Field\File) {
640 if (!$supress_0_key) { // needed for tiles, that come with a custom transformation omitting the 0
641 $field_path[] = 0; // the value of File Inputs is in the 0 key of the raw data
642 }
643 }
644 }
645 $this->fields[$key] = $field;
646 $this->field_path[$key] = $field_path;
647 $this->last_key = $key;
648 $this->form = null;
649 }
650
651 protected function getFieldForKey(string $key): FormInput
652 {
653 if (!isset($this->fields[$key])) {
654 throw new \ilException("Unknown Key: " . $key);
655 }
656 return $this->fields[$key];
657 }
658
659 protected function getLastField(): ?FormInput
660 {
661 return $this->fields[$this->last_key] ?? null;
662 }
663
664 protected function replaceLastField(FormInput $field): void
665 {
666 if ($this->last_key !== "") {
667 $this->fields[$this->last_key] = $field;
668 }
669 // also replace the field in current optional, if it's in it
670 if (!is_null($this->current_optional) && isset($this->current_optional["fields"][$this->last_key])) {
671 $this->current_optional["fields"][$this->last_key] = $field;
672 }
673 }
674
675 public function getForm(): Form\Standard
676 {
677 $ctrl = $this->ctrl;
678
679 if (is_null($this->form)) {
680 $async = ($this->async_mode !== self::ASYNC_NONE);
681 $action = "";
682 if (!is_null($this->class_path)) {
683 $action = $ctrl->getLinkTargetByClass($this->class_path, $this->cmd, "", $async);
684 }
685 $inputs = [];
686 foreach ($this->sections as $sec_key => $section) {
687 if ($sec_key === self::DEFAULT_SECTION) {
688 foreach ($this->sections[$sec_key]["fields"] as $f_key) {
689 $inputs[$f_key] = $this->getFieldForKey($f_key);
690 }
691 } elseif (count($this->sections[$sec_key]["fields"]) > 0) {
692 $sec_inputs = [];
693 foreach ($this->sections[$sec_key]["fields"] as $f_key) {
694 $sec_inputs[$f_key] = $this->getFieldForKey($f_key);
695 }
696 $inputs[$sec_key] = $this->ui->factory()->input()->field()->section(
697 $sec_inputs,
698 $section["title"],
699 $section["description"]
700 );
701 }
702 }
703 $this->form = $this->ui->factory()->input()->container()->form()->standard(
704 $action,
705 $inputs
706 );
707 if ($this->submit_caption !== "") {
708 $this->form = $this->form->withSubmitLabel($this->submit_caption);
709 }
710 }
711 return $this->form;
712 }
713
714 public function getSubmitLabel(): string
715 {
716 return $this->getForm()->getSubmitLabel() ?? $this->lng->txt("save");
717 }
718
719 protected function _getData(): void
720 {
721 if (is_null($this->raw_data)) {
722 $request = $this->http->request();
723 $this->form = $this->getForm()->withRequest($request);
724 $this->raw_data = $this->form->getData();
725 }
726 }
727
728 public function isValid(): bool
729 {
730 $this->_getData();
731 return !(is_null($this->raw_data));
732 }
733
737 public function getData(string $key): mixed
738 {
739 $this->_getData();
740
741 if (!isset($this->fields[$key])) {
742 return null;
743 }
744
745 if (isset($this->disable[$key])) {
746 return $this->values[$key];
747 }
748
749 $value = $this->raw_data;
750 foreach ($this->field_path[$key] as $path_key) {
751 if (!isset($value[$path_key])) {
752 return null;
753 }
754 $value = $value[$path_key];
755 }
756
757 $field = $this->getFieldForKey($key);
758
759 if ($field instanceof \ILIAS\UI\Component\Input\Field\DateTime) {
761 $value = $this->getDateTimeData($value, $field->getUseTime());
762 }
763
764 if ($field instanceof \ILIAS\UI\Component\Input\Field\Duration) {
766 $value = [
767 $this->getDateTimeData($value["start"], $field->getUseTime()),
768 $this->getDateTimeData($value["end"], $field->getUseTime()),
769 ];
770 }
771
772 if ($field instanceof \ILIAS\UI\Component\Input\Field\OptionalGroup) {
773 $value = is_array($value);
774 }
775
776 return $value;
777 }
778
779 public function render(): string
780 {
781 if ($this->async_mode === self::ASYNC_NONE && !$this->ctrl->isAsynch()) {
782 $html = $this->ui->renderer()->render($this->getForm());
783 } else {
784 $html = $this->ui->renderer()->renderAsync($this->getForm()) . "<script>" . $this->getOnLoadCode() . "</script>";
785 }
786 return $html;
787 }
788}
Builds data types.
Definition: Factory.php:36
radio(string $key, string $title, string $description="", ?string $value=null)
checkbox(string $key, string $title, string $description="", ?bool $value=null, ?bool $disabled=null)
date(string $key, string $title, string $description="", ?\ilDate $value=null)
optional(string $key, string $title, string $description="", ?bool $value=null)
group(string $key, string $title, string $description="", $disabled=false)
text(string $key, string $title, string $description="", ?string $value=null, int $max_length=0)
number(string $key, string $title, string $description="", ?int $value=null, ?int $min_value=null, ?int $max_value=null)
getDateTimeData(?\DateTimeImmutable $value, $use_time=false)
select(string $key, string $title, array $options, string $description="", ?string $value=null)
dateTime(string $key, string $title, string $description="", ?\ilDateTime $value=null)
dateTimeDuration(string $key, string $title, string $description="", ?\ilDateTime $from=null, ?\ilDateTime $to=null, string $label_from="", string $label_to="")
section(string $key, string $title, string $description="")
__construct(?array $class_path, string $cmd, string $submit_caption="")
addField(string $key, FormInput $field, $supress_0_key=false)
textarea(string $key, string $title, string $description="", ?string $value=null)
file(string $key, string $title, \Closure $result_handler, string $id_parameter, string $description="", ?int $max_files=null, array $mime_types=[], array $ctrl_path=[], string $logger_id="")
radioOption(string $value, string $title, string $description="")
Definition: UI.php:24
const IL_CAL_DATE
const IL_CAL_DATETIME
@classDescription Date and time handling
Class for single dates.
addJavaScript(string $a_js_file, bool $a_add_version_parameter=true, int $a_batch=2)
Add a javascript file that should be included in the header.
addOnLoadCode(string $a_code, int $a_batch=2)
Add on load code.
This describes inputs that can be used in forms.
Definition: FormInput.php:33
This describes commonalities between all forms.
Definition: Form.php:34
This describes commonalities between all inputs.
Definition: Input.php:47
static http()
Fetches the global http state from ILIAS.
initStdObjProperties(Container $DIC)
form(?array $class_path, string $cmd, string $submit_caption="")
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Factory.php:21
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26