ILIAS  trunk Revision v12.0_alpha-1221-g4e438232683
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 ): self {
199 $this->values[$key] = $value;
200 $field = $this->ui->factory()->input()->field()->checkbox($title, $description);
201 if (!is_null($value)) {
202 $field = $field->withValue($value);
203 }
204 $this->addField($key, $field);
205 return $this;
206 }
207
208 public function hidden(
209 string $key,
210 string $value
211 ): self {
212 $this->values[$key] = $value;
213 $field = $this->ui->factory()->input()->field()->hidden();
214 $field = $field->withValue($value);
215 $this->addField($key, $field);
216 return $this;
217 }
218
219 public function required($required = true): self
220 {
221 if ($required && ($field = $this->getLastField())) {
222 if ($field instanceof \ILIAS\UI\Component\Input\Field\Text) {
223 $field = $field->withRequired(true, new NotEmpty(
224 new Factory(),
225 $this->lng
226 ));
227 } else {
228 $field = $field->withRequired(true);
229 }
230 $this->replaceLastField($field);
231 }
232 return $this;
233 }
234
235 public function disabled($disabled = true): self
236 {
237 if ($disabled && ($field = $this->getLastField())) {
238 $field = $field->withDisabled(true);
239 $this->disable[$this->last_key] = true;
240 $this->replaceLastField($field);
241 }
242 return $this;
243 }
244
245 public function textarea(
246 string $key,
247 string $title,
248 string $description = "",
249 ?string $value = null
250 ): self {
251 $this->values[$key] = $value;
252 $field = $this->ui->factory()->input()->field()->textarea($title, $description);
253 if (!is_null($value)) {
254 $field = $field->withValue($value);
255 }
256 $this->addField($key, $field);
257 return $this;
258 }
259
260 public function number(
261 string $key,
262 string $title,
263 string $description = "",
264 ?int $value = null,
265 ?int $min_value = null,
266 ?int $max_value = null
267 ): self {
268 $this->values[$key] = $value;
269 $trans = [];
270 if (!is_null($min_value)) {
271 $trans[] = $this->refinery->int()->isGreaterThanOrEqual($min_value);
272 }
273 if (!is_null($max_value)) {
274 $trans[] = $this->refinery->int()->isLessThanOrEqual($max_value);
275 }
276 $field = $this->ui->factory()->input()->field()->numeric($title, $description);
277 if (count($trans) > 0) {
278 $field = $field->withAdditionalTransformation($this->refinery->logical()->parallel($trans));
279 }
280 if (!is_null($value)) {
281 $field = $field->withValue($value);
282 }
283 $this->addField($key, $field);
284 return $this;
285 }
286
287 public function date(
288 string $key,
289 string $title,
290 string $description = "",
291 ?\ilDate $value = null
292 ): self {
293 $this->values[$key] = $value;
294 $field = $this->ui->factory()->input()->field()->dateTime($title, $description);
295
296 $format = $this->user->getDateFormat();
297 $dt_format = (string) $format;
298
299 $field = $field->withFormat($format);
300 if (!is_null($value)) {
301 $field = $field->withValue(
302 (new \DateTime($value->get(IL_CAL_DATE)))->format($dt_format)
303 );
304 }
305 $this->addField($key, $field);
306 return $this;
307 }
308
309 public function dateTime(
310 string $key,
311 string $title,
312 string $description = "",
313 ?\ilDateTime $value = null
314 ): self {
315 $this->values[$key] = $value;
316 $field = $this->ui->factory()->input()->field()->dateTime($title, $description)->withUseTime(true);
317
318 if ((int) $this->user->getTimeFormat() === \ilCalendarSettings::TIME_FORMAT_12) {
319 $dt_format = $this->data->dateFormat()->withTime12($this->user->getDateFormat());
320 } else {
321 $dt_format = $this->data->dateFormat()->withTime24($this->user->getDateFormat());
322 }
323 $field = $field->withFormat($dt_format);
324 if (!is_null($value) && !is_null($value->get(IL_CAL_DATETIME))) {
325 $field = $field->withValue(
326 (new \DateTime($value->get(IL_CAL_DATETIME)))->format(
327 ((string) $dt_format)
328 )
329 );
330 }
331 $this->addField($key, $field);
332 return $this;
333 }
334
335 public function dateTimeDuration(
336 string $key,
337 string $title,
338 string $description = "",
339 ?\ilDateTime $from = null,
340 ?\ilDateTime $to = null,
341 string $label_from = "",
342 string $label_to = ""
343 ): self {
344 $this->values[$key] = [$from, $to];
345 if ($label_from === "") {
346 $label_from = $this->lng->txt("rep_activation_limited_start");
347 }
348 if ($label_to === "") {
349 $label_to = $this->lng->txt("rep_activation_limited_end");
350 }
351 $field = $this->ui->factory()->input()->field()->duration($title, $description)->withUseTime(true)->withLabels($label_from, $label_to);
352
353 if ((int) $this->user->getTimeFormat() === \ilCalendarSettings::TIME_FORMAT_12) {
354 $dt_format = $this->data->dateFormat()->withTime12($this->user->getDateFormat());
355 } else {
356 $dt_format = $this->data->dateFormat()->withTime24($this->user->getDateFormat());
357 }
358 $field = $field->withFormat($dt_format);
359 $val_from = $val_to = null;
360 if (!is_null($from) && !is_null($from->get(IL_CAL_DATETIME))) {
361 $val_from = (new \DateTime(
362 $from->get(IL_CAL_DATETIME)
363 ))->format((string) $dt_format);
364 }
365 if (!is_null($to) && !is_null($to->get(IL_CAL_DATETIME))) {
366 $val_to = (new \DateTime(
367 $to->get(IL_CAL_DATETIME)
368 ))->format((string) $dt_format);
369 }
370 $field = $field->withValue([$val_from, $val_to]);
371 $this->addField($key, $field);
372 return $this;
373 }
374
375 protected function getDateTimeData(?\DateTimeImmutable $value, $use_time = false): \ilDate|\ilDateTime|null
376 {
377 if (is_null($value)) {
378 return null;
379 }
380 if ($use_time) {
381 return new \ilDateTime($value->format("Y-m-d H:i:s"), IL_CAL_DATETIME);
382 }
383 return new \ilDate($value->format("Y-m-d"), IL_CAL_DATE);
384 }
385
386 public function select(
387 string $key,
388 string $title,
389 array $options,
390 string $description = "",
391 ?string $value = null
392 ): self {
393 $this->values[$key] = $value;
394 $field = $this->ui->factory()->input()->field()->select($title, $options, $description);
395 if (!is_null($value)) {
396 $field = $field->withValue($value);
397 }
398 $this->addField(
399 $key,
400 $field
401 );
402 return $this;
403 }
404
405 public function radio(
406 string $key,
407 string $title,
408 string $description = "",
409 ?string $value = null
410 ): self {
411 $this->values[$key] = $value;
412 $field = $this->ui->factory()->input()->field()->radio($title, $description);
413 $this->addField(
414 $key,
415 $field
416 );
417 return $this;
418 }
419
420 public function radioOption(string $value, string $title, string $description = ""): self
421 {
422 if ($field = $this->getLastField()) {
423 $field = $field->withOption($value, $title, $description);
424 if (($this->values[$this->last_key] ?? null) === $value) {
425 $field = $field->withValue($value);
426 }
427 $this->replaceLastField($field);
428 }
429 return $this;
430 }
431
432 public function switch(
433 string $key,
434 string $title,
435 string $description = "",
436 ?string $value = null
437 ): self {
438 $this->values[$key] = $value;
439 $this->current_switch = [
440 "key" => $key,
441 "title" => $title,
442 "description" => $description,
443 "value" => $value,
444 "groups" => []
445 ];
446 return $this;
447 }
448
449 public function optional(
450 string $key,
451 string $title,
452 string $description = "",
453 ?bool $value = null
454 ): self {
455 $this->values[$key] = $value;
456 $this->current_optional = [
457 "key" => $key,
458 "title" => $title,
459 "description" => $description,
460 "value" => $value,
461 "group" => []
462 ];
463 return $this;
464 }
465
466 public function group(string $key, string $title, string $description = "", $disabled = false): self
467 {
468 $this->endCurrentGroup();
469 $this->current_group = [
470 "key" => $key,
471 "title" => $title,
472 "description" => $description,
473 "disabled" => $disabled,
474 "fields" => []
475 ];
476 return $this;
477 }
478
479 protected function endCurrentGroup(): void
480 {
481 if (!is_null($this->current_group)) {
482 if (!is_null($this->current_switch)) {
483 $fields = [];
484 foreach ($this->current_group["fields"] as $key) {
485 $fields[$key] = $this->fields[$key];
486 }
487 $this->current_switch["groups"][$this->current_group["key"]] =
488 $this->ui->factory()->input()->field()->group(
489 $fields,
490 $this->current_group["title"]
491 )->withByline($this->current_group["description"]);
492 if ($this->current_group["disabled"]) {
493 $this->current_switch["groups"][$this->current_group["key"]] =
494 $this->current_switch["groups"][$this->current_group["key"]]
495 ->withDisabled(true);
496 }
497 }
498 }
499 $this->current_group = null;
500 }
501
502 public function end(): self
503 {
504 $this->endCurrentGroup();
505 if (!is_null($this->current_switch)) {
506 $field = $this->ui->factory()->input()->field()->switchableGroup(
507 $this->current_switch["groups"],
508 $this->current_switch["title"],
509 $this->current_switch["description"]
510 );
511 if (!is_null($this->current_switch["value"])) {
512 $cvalue = $this->current_switch["value"];
513 if (isset($this->current_switch["groups"][$cvalue])) {
514 $field = $field->withValue($cvalue);
515 }
516 }
517 $key = $this->current_switch["key"];
518 $this->current_switch = null;
519 $this->addField($key, $field);
520 }
521 if (!is_null($this->current_optional)) {
522 $field = $this->ui->factory()->input()->field()->optionalGroup(
523 $this->current_optional["fields"],
524 $this->current_optional["title"],
525 $this->current_optional["description"]
526 );
527 if ($this->current_optional["value"]) {
528 $value = [];
529 foreach ($this->current_optional["fields"] as $key => $input) {
530 $value[$key] = $input->getValue();
531 }
532 $field = $field->withValue($value);
533 } else {
534 $field = $field->withValue(null);
535 }
536 $key = $this->current_optional["key"];
537 $this->current_optional = null;
538 $this->addField($key, $field);
539 }
540 return $this;
541 }
542
543 public function file(
544 string $key,
545 string $title,
546 \Closure $result_handler,
547 string $id_parameter,
548 string $description = "",
549 ?int $max_files = null,
550 array $mime_types = [],
551 array $ctrl_path = [],
552 string $logger_id = ""
553 ): self {
554 $this->upload_handler[$key] = new \ilRepoStandardUploadHandlerGUI(
555 $result_handler,
556 $id_parameter,
557 $logger_id,
558 $ctrl_path
559 );
560
561 foreach (["application/x-compressed", "application/x-zip-compressed"] as $zipmime) {
562 if (in_array("application/zip", $mime_types) &&
563 !in_array($zipmime, $mime_types)) {
564 $mime_types[] = $zipmime;
565 }
566 }
567
568 if (count($mime_types) > 0) {
569 $description .= $this->lng->txt("rep_allowed_types") . ": " .
570 implode(", ", $mime_types);
571 }
572
573 $field = $this->ui->factory()->input()->field()->file(
574 $this->upload_handler[$key],
575 $title,
576 $description
577 );
578 // not necessary, see https://github.com/ILIAS-eLearning/ILIAS/pull/9314
579 //->withMaxFileSize((int) \ilFileUtils::getPhpUploadSizeLimitInBytes());
580 if (!is_null($max_files)) {
581 $field = $field->withMaxFiles($max_files);
582 }
583 if (count($mime_types) > 0) {
584 $field = $field->withAcceptedMimeTypes($mime_types);
585 }
586
587 $this->addField(
588 $key,
589 $field
590 );
591 return $this;
592 }
593
595 {
596 if (!isset($this->upload_handler[$key])) {
597 throw new \ilException("Unknown file upload field: " . $key);
598 }
599 return $this->upload_handler[$key];
600 }
601
602
603 protected function addField(string $key, FormInput $field, $supress_0_key = false): void
604 {
605 if ($key === "") {
606 throw new \ilException("Missing Input Key: " . $key);
607 }
608 if (isset($this->field[$key])) {
609 throw new \ilException("Duplicate Input Key: " . $key);
610 }
611 $field_path = [];
612 if ($this->current_section !== self::DEFAULT_SECTION) {
613 $field_path[] = $this->current_section;
614 }
615 if (!is_null($this->current_group)) {
616 $this->current_group["fields"][] = $key;
617 if (!is_null($this->current_switch)) {
618 $field_path[] = $this->current_switch["key"];
619 $field_path[] = 1; // the value of subitems in SwitchableGroup are in the 1 key of the raw data
620 $field_path[] = $key;
621 }
622 } elseif (!is_null($this->current_optional)) {
623 $field_path[] = $this->current_optional["key"];
624 $this->current_optional["fields"][$key] = $field;
625 $field_path[] = $key;
626 } else {
627 $this->sections[$this->current_section]["fields"][] = $key;
628 $field_path[] = $key;
629 if ($field instanceof \ILIAS\UI\Component\Input\Field\SwitchableGroup) {
630 $field_path[] = 0; // the value of the SwitchableGroup is in the 0 key of the raw data
631 }
632 if ($field instanceof \ILIAS\UI\Component\Input\Field\OptionalGroup) {
633 //$field_path[] = 0; // the value of the SwitchableGroup is in the 0 key of the raw data
634 }
635 if ($field instanceof \ILIAS\UI\Component\Input\Field\File) {
636 if (!$supress_0_key) { // needed for tiles, that come with a custom transformation omitting the 0
637 $field_path[] = 0; // the value of File Inputs is in the 0 key of the raw data
638 }
639 }
640 }
641 $this->fields[$key] = $field;
642 $this->field_path[$key] = $field_path;
643 $this->last_key = $key;
644 $this->form = null;
645 }
646
647 protected function getFieldForKey(string $key): FormInput
648 {
649 if (!isset($this->fields[$key])) {
650 throw new \ilException("Unknown Key: " . $key);
651 }
652 return $this->fields[$key];
653 }
654
655 protected function getLastField(): ?FormInput
656 {
657 return $this->fields[$this->last_key] ?? null;
658 }
659
660 protected function replaceLastField(FormInput $field): void
661 {
662 if ($this->last_key !== "") {
663 $this->fields[$this->last_key] = $field;
664 }
665 // also replace the field in current optional, if it's in it
666 if (!is_null($this->current_optional) && isset($this->current_optional["fields"][$this->last_key])) {
667 $this->current_optional["fields"][$this->last_key] = $field;
668 }
669 }
670
671 public function getForm(): Form\Standard
672 {
673 $ctrl = $this->ctrl;
674
675 if (is_null($this->form)) {
676 $async = ($this->async_mode !== self::ASYNC_NONE);
677 $action = "";
678 if (!is_null($this->class_path)) {
679 $action = $ctrl->getLinkTargetByClass($this->class_path, $this->cmd, "", $async);
680 }
681 $inputs = [];
682 foreach ($this->sections as $sec_key => $section) {
683 if ($sec_key === self::DEFAULT_SECTION) {
684 foreach ($this->sections[$sec_key]["fields"] as $f_key) {
685 $inputs[$f_key] = $this->getFieldForKey($f_key);
686 }
687 } elseif (count($this->sections[$sec_key]["fields"]) > 0) {
688 $sec_inputs = [];
689 foreach ($this->sections[$sec_key]["fields"] as $f_key) {
690 $sec_inputs[$f_key] = $this->getFieldForKey($f_key);
691 }
692 $inputs[$sec_key] = $this->ui->factory()->input()->field()->section(
693 $sec_inputs,
694 $section["title"],
695 $section["description"]
696 );
697 }
698 }
699 $this->form = $this->ui->factory()->input()->container()->form()->standard(
700 $action,
701 $inputs
702 );
703 if ($this->submit_caption !== "") {
704 $this->form = $this->form->withSubmitLabel($this->submit_caption);
705 }
706 }
707 return $this->form;
708 }
709
710 public function getSubmitLabel(): string
711 {
712 return $this->getForm()->getSubmitLabel() ?? $this->lng->txt("save");
713 }
714
715 protected function _getData(): void
716 {
717 if (is_null($this->raw_data)) {
718 $request = $this->http->request();
719 $this->form = $this->getForm()->withRequest($request);
720 $this->raw_data = $this->form->getData();
721 }
722 }
723
724 public function isValid(): bool
725 {
726 $this->_getData();
727 return !(is_null($this->raw_data));
728 }
729
733 public function getData(string $key): mixed
734 {
735 $this->_getData();
736
737 if (!isset($this->fields[$key])) {
738 return null;
739 }
740
741 if (isset($this->disable[$key])) {
742 return $this->values[$key];
743 }
744
745 $value = $this->raw_data;
746 foreach ($this->field_path[$key] as $path_key) {
747 if (!isset($value[$path_key])) {
748 return null;
749 }
750 $value = $value[$path_key];
751 }
752
753 $field = $this->getFieldForKey($key);
754
755 if ($field instanceof \ILIAS\UI\Component\Input\Field\DateTime) {
757 $value = $this->getDateTimeData($value, $field->getUseTime());
758 }
759
760 if ($field instanceof \ILIAS\UI\Component\Input\Field\Duration) {
762 $value = [
763 $this->getDateTimeData($value["start"], $field->getUseTime()),
764 $this->getDateTimeData($value["end"], $field->getUseTime()),
765 ];
766 }
767
768 if ($field instanceof \ILIAS\UI\Component\Input\Field\OptionalGroup) {
769 $value = is_array($value);
770 }
771
772 return $value;
773 }
774
775 public function render(): string
776 {
777 if ($this->async_mode === self::ASYNC_NONE && !$this->ctrl->isAsynch()) {
778 $html = $this->ui->renderer()->render($this->getForm());
779 } else {
780 $html = $this->ui->renderer()->renderAsync($this->getForm()) . "<script>" . $this->getOnLoadCode() . "</script>";
781 }
782 return $html;
783 }
784}
Builds data types.
Definition: Factory.php:36
radio(string $key, string $title, string $description="", ?string $value=null)
date(string $key, string $title, string $description="", ?\ilDate $value=null)
optional(string $key, string $title, string $description="", ?bool $value=null)
checkbox(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