ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
class.ilPropertyFormGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21use ILIAS\HTTP;
23
32{
33 private array $kept_uploads = [];
34 protected bool $required_text = false;
35 protected ilLanguage $lng;
36 protected ilCtrl $ctrl;
37 protected ilTemplate $tpl;
38 protected ?ilObjUser $user = null;
39 protected ?ilSetting $settings = null;
40 private array $buttons = array();
41 private array $items = array();
42 protected string $mode = "std";
43 protected bool $check_input_called = false;
44 protected bool $disable_standard_message = false;
45 protected string $top_anchor = "il_form_top";
46 protected string $title = '';
47 protected string $titleicon = "";
48 protected string $description = "";
49 protected string $tbl_width = "";
50 protected bool $show_top_buttons = true;
51 protected bool $hide_labels = false;
52 protected bool $force_top_buttons = false;
54 protected ?Refinery\Factory $refinery = null;
55
57 protected $onload_code = [];
58
59 public function __construct()
60 {
61 global $DIC;
62
63 $this->lng = $DIC->language();
64 $this->ctrl = $DIC->ctrl();
65
66 $this->user = null;
67 if (isset($DIC["ilUser"])) {
68 $this->user = $DIC["ilUser"];
69 }
70
71 $this->settings = null;
72 if (isset($DIC["ilSetting"])) {
73 $this->settings = $DIC["ilSetting"];
74 }
75
76 $lng = $DIC->language();
77
78 $lng->loadLanguageModule("form");
79
80 // avoid double submission
81 $this->setPreventDoubleSubmission(true);
82
83 // do it as early as possible
84 if (isset($DIC["http"])) {
85 $this->http = $DIC->http();
86 }
87 if (isset($DIC["refinery"])) {
88 $this->refinery = $DIC->refinery();
89 }
90 $this->rebuildUploadedFiles();
91 if (isset($DIC["tpl"])) { // some unit tests will fail otherwise
92 $this->global_tpl = $DIC['tpl'];
93 }
94 }
95
100 public function executeCommand()
101 {
102 $ilCtrl = $this->ctrl;
103
104 $next_class = $ilCtrl->getNextClass($this);
105
106 switch ($next_class) {
107 case 'ilformpropertydispatchgui':
108 $ilCtrl->saveParameter($this, 'postvar');
109 $form_prop_dispatch = new ilFormPropertyDispatchGUI();
110 $item = $this->getItemByPostVar($this->getRequestedPostVar());
111 $form_prop_dispatch->setItem($item);
112 return $ilCtrl->forwardCommand($form_prop_dispatch);
113 }
114 return false;
115 }
116
117 protected function getRequestedPostVar(): ?string
118 {
119 $t = $this->refinery->kindlyTo()->string();
120 $w = $this->http->wrapper();
121 if ($w->post()->has("postvar")) {
122 return $w->post()->retrieve("postvar", $t);
123 }
124 if ($w->query()->has("postvar")) {
125 return $w->query()->retrieve("postvar", $t);
126 }
127 return null;
128 }
129
130 final public function setTableWidth(string $a_width): void
131 {
132 $this->tbl_width = $a_width;
133 }
134
135 final public function getTableWidth(): string
136 {
137 return $this->tbl_width;
138 }
139
140 // Set Mode ('std', 'subform').
141 public function setMode(string $a_mode): void
142 {
143 $this->mode = $a_mode;
144 }
145
146 public function getMode(): string
147 {
148 return $this->mode;
149 }
150
151 public function setTitle(string $a_title): void
152 {
153 $this->title = $a_title;
154 }
155
156 public function getTitle(): string
157 {
158 return $this->title;
159 }
160
161 public function setTitleIcon(string $a_titleicon): void
162 {
163 $this->titleicon = $a_titleicon;
164 }
165
166 public function getTitleIcon(): string
167 {
168 return $this->titleicon;
169 }
170
171 public function setDescription(string $a_val): void
172 {
173 $this->description = $a_val;
174 }
175
176 public function getDescription(): string
177 {
178 return $this->description;
179 }
180
181 public function setTopAnchor(string $a_val): void
182 {
183 $this->top_anchor = $a_val;
184 }
185
186 public function getTopAnchor(): string
187 {
188 return $this->top_anchor;
189 }
190
191 public function setShowTopButtons(bool $a_val): void
192 {
193 $this->show_top_buttons = $a_val;
194 }
195
196 public function getShowTopButtons(): bool
197 {
199 }
200
201 public function setForceTopButtons(bool $a_val): void
202 {
203 $this->force_top_buttons = $a_val;
204 }
205
206 public function getForceTopButtons(): bool
207 {
209 }
210
214 public function addItem($a_item): void
215 {
216 $a_item->setParentForm($this);
217 $this->items[] = $a_item;
218 }
219
220 public function removeItemByPostVar(
221 string $a_post_var,
222 bool $a_remove_unused_headers = false
223 ): void {
224 foreach ($this->items as $key => $item) {
225 if (method_exists($item, "getPostVar") && $item->getPostVar() == $a_post_var) {
226 unset($this->items[$key]);
227 }
228 }
229
230 // remove section headers if they do not contain any items anymore
231 if ($a_remove_unused_headers) {
232 $unset_keys = array();
233 $last_item = null;
234 $last_key = null;
235 foreach ($this->items as $key => $item) {
236 if ($item instanceof ilFormSectionHeaderGUI && $last_item instanceof ilFormSectionHeaderGUI) {
237 $unset_keys[] = $last_key;
238 }
239 $last_item = $item;
240 $last_key = $key;
241 }
242 if ($last_item instanceof ilFormSectionHeaderGUI) {
243 $unset_keys[] = $last_key;
244 }
245 foreach ($unset_keys as $key) {
246 unset($this->items[$key]);
247 }
248 }
249 }
250
251 public function getItemByPostVar(string $a_post_var): ?ilFormPropertyGUI
252 {
253 foreach ($this->items as $item) {
254 if ($item->getType() != "section_header") {
255 //if ($item->getPostVar() == $a_post_var)
256 $ret = $item->getItemByPostVar($a_post_var);
257 if (is_object($ret)) {
258 return $ret;
259 }
260 }
261 }
262
263 return null;
264 }
265
266 public function setItems(array $a_items): void
267 {
268 $this->items = $a_items;
269 }
270
271 public function getItems(): array
272 {
273 return $this->items;
274 }
275
280 public function getInputItemsRecursive(): array
281 {
282 $inputItems = array();
283
284 foreach ($this->items as $item) {
285 if ($item->getType() == 'section_header') {
286 continue;
287 }
288
289 $inputItems[] = $item;
290
291 if ($item instanceof ilSubEnabledFormPropertyGUI) {
292 $inputItems = array_merge($inputItems, $item->getSubInputItemsRecursive());
293 }
294 }
295
296 return $inputItems;
297 }
298
299 public function setDisableStandardMessage(bool $a_val): void
300 {
301 $this->disable_standard_message = $a_val;
302 }
303
304 public function getDisableStandardMessage(): bool
305 {
306 return $this->disable_standard_message;
307 }
308
309 // Get a value indicating whether the labels should be hidden or not.
310 public function getHideLabels(): bool
311 {
312 return $this->hide_labels;
313 }
314
315 public function setHideLabels(bool $a_value = true): void
316 {
317 $this->hide_labels = $a_value;
318 }
319
320 public function setValuesByArray(
321 array $a_values,
322 bool $a_restrict_to_value_keys = false
323 ): void {
324 foreach ($this->items as $item) {
325 if (!($a_restrict_to_value_keys) ||
326 in_array($item->getPostVar(), array_keys($a_values))) {
327 $item->setValueByArray($a_values);
328 }
329 }
330 }
331
332 public function setValuesByPost()
333 {
334 global $DIC;
335
336 if (!isset($DIC["http"])) {
337 return null;
338 }
339
340 foreach ($this->items as $item) {
341 $item->setValueByArray($DIC->http()->request()->getParsedBody());
342 }
343 }
344
345 public function checkInput(): bool
346 {
347 global $DIC;
348
349 if ($this->check_input_called) {
350 die("Error: ilPropertyFormGUI->checkInput() called twice.");
351 }
352
353 $ok = true;
354 foreach ($this->items as $item) {
355 $item_ok = $item->checkInput();
356 if (!$item_ok) {
357 $ok = false;
358 }
359 }
360
361 // check if POST is missing completely (if post_max_size exceeded)
362 $post = $this->http->request()->getParsedBody();
363 if (count($this->items) > 0 && count($post) === 0) {
364 $ok = false;
365 }
366
367 $this->check_input_called = true;
368
369 // try to keep uploads for another try
370 $filehash = $this->getFileHash();
371 if (!$ok && !is_null($filehash) && $filehash && count($_FILES)) {
372 $hash = $filehash;
373
374 foreach ($_FILES as $field => $data) {
375 // only try to keep files that are ok
376 // see 25484: Wrong error handling when uploading icon instead of tile
377 $item = $this->getItemByPostVar($field);
378 if (is_null($item) || !$item->checkInput()) {
379 continue;
380 }
381 // we support up to 2 nesting levels (see test/assessment)
382 if (is_array($data["tmp_name"])) {
383 foreach ($data["tmp_name"] as $idx => $upload) {
384 if (is_array($upload)) {
385 foreach ($upload as $idx2 => $file) {
386 if ($file && is_uploaded_file($file)) {
387 $file_name = $data["name"][$idx][$idx2];
388 $file_type = $data["type"][$idx][$idx2];
389 $this->keepFileUpload($hash, $field, $file, $file_name, $file_type, (string) $idx, (string) $idx2);
390 }
391 }
392 } elseif ($upload && is_uploaded_file($upload)) {
393 $file_name = $data["name"][$idx];
394 $file_type = $data["type"][$idx];
395 $this->keepFileUpload($hash, $field, $upload, $file_name, $file_type, (string) $idx);
396 }
397 }
398 } else {
399 $this->keepFileUpload($hash, $field, $data["tmp_name"], $data["name"], $data["type"]);
400 }
401 }
402 }
403 $http = $DIC->http();
404 $txt = $DIC->language()->txt("form_input_not_valid");
405 switch ($http->request()->getHeaderLine('Accept')) {
406 // When JS asks for a valid JSON-Response, we send the success and message as JSON
407 case 'application/json':
408 $stream = \ILIAS\Filesystem\Stream\Streams::ofString(json_encode([
409 'success' => $ok,
410 'message' => $txt,
411 ]));
412 $http->saveResponse($http->response()->withBody($stream));
413
414 return $ok;
415
416 // Otherwise, we send it using ilUtil, and it will be rendered in the Template
417 default:
418
419 if (!$ok && !$this->getDisableStandardMessage()) {
420 $this->global_tpl->setOnScreenMessage('failure', $txt);
421 }
422
423 return $ok;
424 }
425 }
426
427 protected function getFileHash(): ?string
428 {
429 if (is_null($this->refinery)) {
430 return null;
431 }
432 // try to keep uploads for another try
433 $t = $this->refinery->kindlyTo()->string();
434 $w = $this->http->wrapper();
435 $filehash = null;
436 if ($w->post()->has("ilfilehash")) {
437 $filehash = $w->post()->retrieve("ilfilehash", $t);
438 }
439 return $filehash;
440 }
441
449 public function getInput(
450 string $a_post_var,
451 bool $ensureValidation = true
452 ) {
453 // this check ensures, that checkInput has been called (incl. stripSlashes())
454 if (!$this->check_input_called && $ensureValidation) {
455 throw new LogicException('Error: ilPropertyFormGUI->getInput() called without calling checkInput() first.');
456 }
457
458 $item = $this->getItemByPostVar($a_post_var);
459 if (is_object($item) && method_exists($item, "getInput")) {
460 return $item->getInput();
461 }
462
463 $post = $this->http->request()->getParsedBody();
464 return $post[$a_post_var] ?? '';
465 }
466
467 public function addCommandButton(
468 string $a_cmd,
469 string $a_text,
470 string $a_id = ""
471 ): void {
472 $this->buttons[] = array("cmd" => $a_cmd, "text" => $a_text, "id" => $a_id);
473 }
474
475
476 public function getCommandButtons(): array
477 {
478 return $this->buttons;
479 }
480
481 public function clearCommandButtons(): void
482 {
483 $this->buttons = array();
484 }
485
486 public function getContent(): string
487 {
488 global $DIC;
490 $tpl = $DIC["tpl"];
491 $ilSetting = $this->settings;
492
493 $tpl->addJavaScript("assets/js/Basic.js");
494 $tpl->addJavaScript("assets/js/Form.js");
495
496 $this->tpl = new ilTemplate("tpl.property_form.html", true, true, "components/ILIAS/Form");
497
498 // check if form has not title and first item is a section header
499 // -> use section header for title and remove section header
500 // -> command buttons are presented on top
501 $fi = $this->items[0] ?? null;
502 if ($this->getMode() == "std" &&
503 $this->getTitle() == "" &&
504 is_object($fi) && $fi->getType() == "section_header"
505 ) {
506 $this->setTitle($fi->getTitle());
507 unset($this->items[0]);
508 }
509
510
511 // title icon
512 if ($this->getTitleIcon() != "" && is_file($this->getTitleIcon())) {
513 $this->tpl->setCurrentBlock("title_icon");
514 $this->tpl->setVariable("IMG_ICON", $this->getTitleIcon());
515 $this->tpl->parseCurrentBlock();
516 }
517
518 // title
519 if ($this->getTitle() != "") {
520 // commands on top
521 if (count($this->buttons) > 0 && $this->getShowTopButtons() && (count($this->items) > 2 || $this->force_top_buttons)) {
522 // command buttons
523 foreach ($this->buttons as $button) {
524 $this->tpl->setCurrentBlock("cmd2");
525 $this->tpl->setVariable("CMD", $button["cmd"]);
526 $this->tpl->setVariable("CMD_TXT", $button["text"]);
527 if ($button["id"] != "") {
528 $this->tpl->setVariable("CMD2_ID", " id='" . $button["id"] . "_top'");
529 }
530 $this->tpl->parseCurrentBlock();
531 }
532 $this->tpl->setCurrentBlock("commands2");
533 $this->tpl->parseCurrentBlock();
534 }
535
536 // required top
537 $this->tpl->setCurrentBlock("header");
538 if ($this->checkForRequiredField()) {
539 $this->tpl->setCurrentBlock("required_text_top");
540 $this->tpl->setVariable("TXT_REQUIRED_TOP", $lng->txt("required_field"));
541 $this->tpl->parseCurrentBlock();
542 }
543
544 $this->tpl->setVariable("TXT_TITLE", $this->getTitle());
545 //$this->tpl->setVariable("LABEL", $this->getTopAnchor());
546 $this->tpl->setVariable("TXT_DESCRIPTION", $this->getDescription());
547 $this->tpl->parseCurrentBlock();
548 } elseif (!$this->required_text && $this->getMode() == "std") {
549 $this->tpl->setCurrentBlock("header");
550 // required top
551 $this->tpl->setCurrentBlock("required_text_top");
552 $this->tpl->setVariable("TXT_REQUIRED_TOP", $lng->txt("required_field"));
553 $this->tpl->parseCurrentBlock();
554 }
555 $this->tpl->touchBlock("item");
556
557 // properties
558 $this->required_text = false;
559 foreach ($this->items as $item) {
560 if ($item->getType() != "hidden") {
561 $this->insertItem($item);
562 }
563 }
564
565 // required
566 if ($this->required_text && $this->getMode() == "std") {
567 $this->tpl->setCurrentBlock("required_text");
568 $this->tpl->setVariable("TXT_REQUIRED", $lng->txt("required_field"));
569 $this->tpl->parseCurrentBlock();
570 }
571
572 // command buttons
573 foreach ($this->buttons as $button) {
574 $this->tpl->setCurrentBlock("cmd");
575 $this->tpl->setVariable("CMD", $button["cmd"]);
576 $this->tpl->setVariable("CMD_TXT", $button["text"]);
577
578 if ($button["id"] != "") {
579 $this->tpl->setVariable("CMD_ID", " id='" . $button["id"] . "'");
580 }
581
582 $this->tpl->parseCurrentBlock();
583 }
584
585 // #18808
586 if ($this->getMode() != "subform") {
587 // try to keep uploads even if checking input fails
588 if ($this->getMultipart()) {
589 $hash = $this->getFileHash() ?? null;
590 if (!$hash) {
591 $hash = md5(uniqid((string) mt_rand(), true));
592 }
593 $fhash = new ilHiddenInputGUI("ilfilehash");
594 $fhash->setValue($hash);
595 $this->addItem($fhash);
596 }
597 }
598
599 // hidden properties
600 $hidden_fields = false;
601 foreach ($this->items as $item) {
602 if ($item->getType() == "hidden") {
603 $item->insert($this->tpl);
604 $hidden_fields = true;
605 }
606 }
607
608 if ($this->required_text || count($this->buttons) > 0 || $hidden_fields) {
609 $this->tpl->setCurrentBlock("commands");
610 $this->tpl->parseCurrentBlock();
611 }
612
613
614 if ($this->getMode() == "subform") {
615 $this->tpl->touchBlock("sub_table");
616 } else {
617 $this->tpl->touchBlock("std_table");
618 $this->tpl->setVariable('STD_TABLE_WIDTH', $this->getTableWidth());
619 }
620
621 return $this->tpl->get();
622 }
623
624 protected function hideRequired(string $a_type): bool
625 {
626 // #15818
627 return $a_type == "non_editable_value";
628 }
629
633 public function insertItem(
634 $item,
635 bool $a_sub_item = false
636 ): void {
637 global $DIC;
638 $tpl = $DIC["tpl"];
640
641
642 //$cfg = array();
643
644 //if(method_exists($item, "getMulti") && $item->getMulti())
645 if ($item instanceof ilMultiValuesItem && $item->getMulti()) {
646 $tpl->addJavascript("assets/js/ServiceFormMulti.js");
647
648 $this->tpl->setCurrentBlock("multi_in");
649 $this->tpl->setVariable("ID", $item->getFieldId());
650 $this->tpl->parseCurrentBlock();
651
652 $this->tpl->touchBlock("multi_out");
653
654
655 // add hidden item to enable preset multi items
656 // not used yet, should replace hidden field stuff
657 $multi_values = $item->getMultiValues();
658 if (is_array($multi_values) && sizeof($multi_values) > 1) {
659 $multi_value = new ilHiddenInputGUI("ilMultiValues~" . $item->getPostVar());
660 $multi_value->setValue(base64_encode(json_encode($multi_values)));
661 $this->addItem($multi_value);
662 }
663 //$cfg["multi_values"] = $multi_values;
664 }
665
666 $item->insert($this->tpl);
667
668 if ($item->getType() == "file" || $item->getType() == "image_file") {
669 $this->setMultipart(true);
670 }
671
672 if ($item->getType() != "section_header") {
673 //$cfg["id"] = $item->getFieldId();
674
675 // info text
676 if ($item->getInfo() != "") {
677 $this->tpl->setCurrentBlock("description");
678 $this->tpl->setVariable(
679 "PROPERTY_DESCRIPTION",
680 $item->getInfo()
681 );
682 $this->tpl->setVariable(
683 "DESCRIPTION_FOR_ID",
684 $item->getFieldId()
685 );
686 $this->tpl->parseCurrentBlock();
687 }
688
689 if ($this->getMode() == "subform") {
690 // required
691 if (!$this->hideRequired($item->getType())) {
692 if ($item->getRequired()) {
693 $this->tpl->touchBlock("sub_required");
694 $this->required_text = true;
695 }
696 }
697
698 // hidden title (for accessibility, e.g. file upload)
699 if ($item->getHiddenTitle() != "") {
700 $this->tpl->setCurrentBlock("sub_hid_title");
701 $this->tpl->setVariable(
702 "SPHID_TITLE",
703 $item->getHiddenTitle()
704 );
705 $this->tpl->parseCurrentBlock();
706 }
707
708 $this->tpl->setCurrentBlock("sub_prop_start");
709 $this->tpl->setVariable("PROPERTY_TITLE", $item->getTitle());
710 $this->tpl->setVariable("PROPERTY_CLASS", "il_" . $item->getType());
711 if ($item->getType() != "non_editable_value" && $item->getFormLabelFor() != "") {
712 $this->tpl->setVariable("FOR_ID", ' for="' . $item->getFormLabelFor() . '" ');
713 }
714 $this->tpl->setVariable("LAB_ID", $item->getFieldId());
715 } else {
716 // required
717 if (!$this->hideRequired($item->getType())) {
718 if ($item->getRequired()) {
719 $this->tpl->touchBlock("required");
720 $this->required_text = true;
721 }
722 }
723
724 // hidden title (for accessibility, e.g. file upload)
725 if ($item->getHiddenTitle() != "") {
726 $this->tpl->setCurrentBlock("std_hid_title");
727 $this->tpl->setVariable(
728 "PHID_TITLE",
729 $item->getHiddenTitle()
730 );
731 $this->tpl->parseCurrentBlock();
732 }
733
734 $this->tpl->setCurrentBlock("std_prop_start");
735 $this->tpl->setVariable("PROPERTY_TITLE", $item->getTitle());
736 if ($item->getType() != "non_editable_value" && $item->getFormLabelFor() != "") {
737 $this->tpl->setVariable("FOR_ID", ' for="' . $item->getFormLabelFor() . '" ');
738 }
739 $this->tpl->setVariable("LAB_ID", $item->getFieldId());
740 if ($this->getHideLabels()) {
741 $this->tpl->setVariable("HIDE_LABELS_STYLE", " ilFormOptionHidden");
742 }
743 }
744 $this->tpl->parseCurrentBlock();
745
746 // alert
747 if ($item->getType() != "non_editable_value" && $item->getAlert() != "") {
748 $this->tpl->setCurrentBlock("alert");
749 $this->tpl->setVariable(
750 "IMG_ALERT",
751 ilUtil::getImagePath("standard/icon_alert.svg")
752 );
753 $this->tpl->setVariable(
754 "ALT_ALERT",
755 $lng->txt("alert")
756 );
757 $this->tpl->setVariable(
758 "TXT_ALERT",
759 $item->getAlert()
760 );
761 $this->tpl->setVariable(
762 "ALERT_FOR_ID",
763 $item->getFieldId()
764 );
765 $this->tpl->parseCurrentBlock();
766 }
767
768 // subitems
769 $sf = null;
770 if ($item->getType() != "non_editable_value" or 1) {
771 $sf = $item->getSubForm();
772 if ($item->hideSubForm() && is_object($sf)) {
773 if ($this->global_tpl) {
774 $dsfid = $item->getFieldId();
775 $this->global_tpl->addOnloadCode(
776 "il.Form.hideSubForm('subform_$dsfid');"
777 );
778 }
779 $this->addAsyncOnloadCode("il.Form.hideSubForm('subform_$dsfid');");
780 }
781 }
782
783 $sf_content = "";
784 if (is_object($sf)) {
785 $sf_content = $sf->getContent();
786 if ($sf->getMultipart()) {
787 $this->setMultipart(true);
788 }
789 $this->tpl->setCurrentBlock("sub_form");
790 $this->tpl->setVariable("PROP_SUB_FORM", $sf_content);
791 $this->tpl->setVariable("SFID", $item->getFieldId());
792 $this->tpl->parseCurrentBlock();
793 }
794
795 $this->tpl->setCurrentBlock("prop");
796 /* not used yet
797 $this->tpl->setVariable("ID", $item->getFieldId());
798 $this->tpl->setVariable("CFG", json_encode($cfg, JSON_THROW_ON_ERROR));*/
799 $this->tpl->parseCurrentBlock();
800 }
801
802
803 $this->tpl->touchBlock("item");
804 }
805
806 public function addAsyncOnloadCode(string $code): void
807 {
808 $this->onload_code[] = $code;
809 }
810
811 public function getHTML(): string
812 {
813 $html = parent::getHTML();
814
815 // #13531 - get content that has to reside outside of the parent form tag, e.g. panels/layers
816 foreach ($this->items as $item) {
817 // #13536 - ilFormSectionHeaderGUI does NOT extend ilFormPropertyGUI ?!
818 if (method_exists($item, "getContentOutsideFormTag")) {
819 $outside = $item->getContentOutsideFormTag();
820 if ($outside) {
821 $html .= $outside;
822 }
823 }
824 }
825 if ($this->ctrl->isAsynch()) {
826 $html = $this->appendOnloadCode($html);
827 }
828 return $html;
829 }
830
831 public function getHTMLAsync(): string
832 {
833 $html = $this->getHTML();
834 if (!$this->ctrl->isAsynch()) {
835 $html = $this->appendOnloadCode($html);
836 }
837 return $html;
838 }
839
840 protected function appendOnloadCode(string $html): string
841 {
842 if (count($this->onload_code) > 0) {
843 $html .= "<script>";
844 foreach ($this->onload_code as $code) {
845 $html .= $code . "\n";
846 }
847 $html .= "</script>";
848 }
849 return $html;
850 }
851
852 //
853 // UPLOAD HANDLING
854 //
855
868 protected function keepFileUpload(
869 string $a_hash,
870 string $a_field,
871 string $a_tmp_name,
872 string $a_name,
873 string $a_type,
874 ?string $a_index = null,
875 ?string $a_sub_index = null
876 ): void {
877 if (in_array($a_tmp_name, $this->kept_uploads)) {
878 return; // already kept
879 }
880
881 if (trim($a_tmp_name) == "") {
882 return;
883 }
884
885 $a_name = ilFileUtils::getASCIIFilename($a_name);
886
887 $tmp_file_name = implode("~~", array(session_id(),
888 $a_hash,
889 $a_field,
890 $a_index,
891 $a_sub_index,
892 str_replace("/", "~~", $a_type),
893 str_replace("~~", "_", $a_name)));
894
895 // make sure temp directory exists
896 $temp_path = ilFileUtils::getDataDir() . "/temp";
897 if (!is_dir($temp_path)) {
899 }
900
901 ilFileUtils::moveUploadedFile($a_tmp_name, $tmp_file_name, $temp_path . "/" . $tmp_file_name);
902
904 $file_input = $this->getItemByPostVar($a_field);
905 $file_input->setPending($a_name);
906 $this->kept_uploads[] = $a_tmp_name;
907 }
908
917 public function getFileUpload(
918 string $a_field,
919 ?string $a_index = null,
920 ?string $a_sub_index = null
921 ): array {
922 $res = array();
923 if ($a_index) {
924 if ($_FILES[$a_field]["tmp_name"][$a_index][$a_sub_index] ?? false) {
925 $res = array(
926 "tmp_name" => $_FILES[$a_field]["tmp_name"][$a_index][$a_sub_index],
927 "name" => $_FILES[$a_field]["name"][$a_index][$a_sub_index],
928 "type" => $_FILES[$a_field]["type"][$a_index][$a_sub_index],
929 "error" => $_FILES[$a_field]["error"][$a_index][$a_sub_index],
930 "size" => $_FILES[$a_field]["size"][$a_index][$a_sub_index],
931 "is_upload" => $_FILES[$a_field]["is_upload"][$a_index][$a_sub_index] ?? true
932 );
933 }
934 } elseif ($a_sub_index) {
935 if ($_FILES[$a_field]["tmp_name"][$a_index] ?? false) {
936 $res = array(
937 "tmp_name" => $_FILES[$a_field]["tmp_name"][$a_index],
938 "name" => $_FILES[$a_field]["name"][$a_index],
939 "type" => $_FILES[$a_field]["type"][$a_index],
940 "error" => $_FILES[$a_field]["error"][$a_index],
941 "size" => $_FILES[$a_field]["size"][$a_index],
942 "is_upload" => $_FILES[$a_field]["is_upload"][$a_index] ?? true
943 );
944 }
945 } else {
946 if ($_FILES[$a_field]["tmp_name"] ?? false) {
947 $res = array(
948 "tmp_name" => $_FILES[$a_field]["tmp_name"],
949 "name" => $_FILES[$a_field]["name"],
950 "type" => $_FILES[$a_field]["type"],
951 "error" => $_FILES[$a_field]["error"],
952 "size" => $_FILES[$a_field]["size"],
953 "is_upload" => $_FILES[$a_field]["is_upload"] ?? true
954 );
955 }
956 }
957 return $res;
958 }
959
960 public function hasFileUpload(
961 string $a_field,
962 ?string $a_index = null,
963 ?string $a_sub_index = null
964 ): bool {
965 $data = $this->getFileUpload($a_field, $a_index, $a_sub_index);
966 return (bool) ($data["tmp_name"] ?? false);
967 }
968
980 public function moveFileUpload(
981 string $a_target_directory,
982 string $a_field,
983 ?string $a_target_name = null,
984 ?string $a_index = null,
985 ?string $a_sub_index = null
986 ): string {
987 if (!is_dir($a_target_directory)) {
988 return "";
989 }
990
991 $data = $this->getFileUpload($a_field, $a_index, $a_sub_index);
992 if ($data["tmp_name"] && file_exists($data["tmp_name"])) {
993 if ($a_target_name) {
994 $data["name"] = $a_target_name;
995 }
996
997 $target_file = $a_target_directory . "/" . $data["name"];
998 $target_file = str_replace("//", "/", $target_file);
999
1000 if ($data["is_upload"]) {
1001 if (!ilFileUtils::moveUploadedFile($data["tmp_name"], $data["name"], $target_file)) {
1002 return "";
1003 }
1004 } else {
1005 if (!ilFileUtils::rename($data["tmp_name"], $target_file)) {
1006 return "";
1007 }
1008 }
1009
1010 return $target_file;
1011 }
1012 return "";
1013 }
1014
1015 protected function rebuildUploadedFiles(): void
1016 {
1017 $file_hash = (string) $this->getFileHash();
1018 if ($file_hash != "") {
1019 $temp_path = ilFileUtils::getDataDir() . "/temp";
1020 if (is_dir($temp_path)) {
1021 $temp_files = glob($temp_path . "/" . session_id() . "~~" . $file_hash . "~~*");
1022 if (is_array($temp_files)) {
1023 foreach ($temp_files as $full_file) {
1024 $file = explode("~~", basename($full_file));
1025 $field = $file[2];
1026 $idx = $file[3];
1027 $idx2 = $file[4];
1028 $type = $file[5] . "/" . $file[6];
1029 $name = $file[7];
1030
1031 if ($idx2 != "") {
1032 if (!isset($_FILES[$field]["tmp_name"][$idx][$idx2])) {
1033 $_FILES[$field]["tmp_name"][$idx][$idx2] = $full_file;
1034 $_FILES[$field]["name"][$idx][$idx2] = $name;
1035 $_FILES[$field]["type"][$idx][$idx2] = $type;
1036 $_FILES[$field]["error"][$idx][$idx2] = 0;
1037 $_FILES[$field]["size"][$idx][$idx2] = filesize($full_file);
1038 $_FILES[$field]["is_upload"][$idx][$idx2] = false;
1039 }
1040 } elseif ($idx != "") {
1041 if (!isset($_FILES[$field]["tmp_name"][$idx])) {
1042 $_FILES[$field]["tmp_name"][$idx] = $full_file;
1043 $_FILES[$field]["name"][$idx] = $name;
1044 $_FILES[$field]["type"][$idx] = $type;
1045 $_FILES[$field]["error"][$idx] = 0;
1046 $_FILES[$field]["size"][$idx] = filesize($full_file);
1047 $_FILES[$field]["is_upload"][$idx] = false;
1048 }
1049 } else {
1050 if (!isset($_FILES[$field]["tmp_name"])) {
1051 $_FILES[$field]["tmp_name"] = $full_file;
1052 $_FILES[$field]["name"] = $name;
1053 $_FILES[$field]["type"] = $type;
1054 $_FILES[$field]["error"] = 0;
1055 $_FILES[$field]["size"] = filesize($full_file);
1056 $_FILES[$field]["is_upload"] = false;
1057 }
1058 }
1059 }
1060 }
1061 }
1062 }
1063 }
1064
1065 protected function checkForRequiredField(): bool
1066 {
1067 foreach ($this->items as $item) {
1068 if ($item instanceof ilFormSectionHeaderGUI) {
1069 return false;
1070 } elseif ($item->getType() != "hidden") {
1071 if ($this->getMode() == "subform") {
1072 if (!$this->hideRequired($item->getType())) {
1073 if ($item->getRequired()) {
1074 return true;
1075 }
1076 }
1077 } elseif (!$this->hideRequired($item->getType())) {
1078 if ($item->getRequired()) {
1079 return true;
1080 }
1081 }
1082 }
1083 }
1084
1085 return false;
1086 }
1087}
static ofString(string $string)
Creates a new stream with an initial value.
Definition: Streams.php:41
Class ilCtrl provides processing control methods.
getNextClass($a_gui_class=null)
@inheritDoc
static getASCIIFilename(string $a_filename)
static rename(string $a_source, string $a_target)
static getDataDir()
get data directory (outside webspace)
static createDirectory(string $a_dir, int $a_mod=0755)
create directory
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
This class represents a form user interface.
setPreventDoubleSubmission(bool $a_val)
This class represents a property in a property form.
getItemByPostVar(string $a_post_var)
Get item by post var.
This class represents a section header in a property form.
This class represents a hidden form property in a property form.
language handling
loadLanguageModule(string $a_module)
Load language module.
User class.
This class represents a property form user interface.
setValuesByArray(array $a_values, bool $a_restrict_to_value_keys=false)
hasFileUpload(string $a_field, ?string $a_index=null, ?string $a_sub_index=null)
moveFileUpload(string $a_target_directory, string $a_field, ?string $a_target_name=null, ?string $a_index=null, ?string $a_sub_index=null)
Move upload to target directory.
setDisableStandardMessage(bool $a_val)
setTableWidth(string $a_width)
getFileUpload(string $a_field, ?string $a_index=null, ?string $a_sub_index=null)
Get file upload data.
ilGlobalTemplateInterface $global_tpl
insertItem( $item, bool $a_sub_item=false)
addCommandButton(string $a_cmd, string $a_text, string $a_id="")
getInput(string $a_post_var, bool $ensureValidation=true)
Returns the input of an item, if item provides getInput method and as fallback the value of the HTTP-...
removeItemByPostVar(string $a_post_var, bool $a_remove_unused_headers=false)
setTitleIcon(string $a_titleicon)
Refinery Factory $refinery
getItemByPostVar(string $a_post_var)
getInputItemsRecursive()
returns a flat array of all input items including the possibly existing subitems recursively
setHideLabels(bool $a_value=true)
ILIAS Setting 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)
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
$http
Definition: deliver.php:30
Interface for multi values support.
$res
Definition: ltiservices.php:69
$post
Definition: ltitoken.php:46
static http()
Fetches the global http state from ILIAS.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $lng
Definition: privfeed.php:31
global $ilSetting
Definition: privfeed.php:31
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26