1<?php
2/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4use ILIAS\FileUpload\DTO\ProcessingStatus;
5
6/**
7 * GUI class for file objects.
8 *
9 * @author       Sascha Hofmann <shofmann@databay.de>
10 * @author       Stefan Born <stefan.born@phzh.ch>
11 * @version      $Id$
12 *
13 * @ilCtrl_Calls ilObjFileGUI: ilObjectMetaDataGUI, ilInfoScreenGUI, ilPermissionGUI, ilObjectCopyGUI
14 * @ilCtrl_Calls ilObjFileGUI: ilExportGUI, ilWorkspaceAccessGUI, ilPortfolioPageGUI, ilCommonActionDispatcherGUI
15 * @ilCtrl_Calls ilObjFileGUI: ilLearningProgressGUI, ilFileVersionsGUI
16 *
17 * @ingroup      ModulesFile
18 */
19class ilObjFileGUI extends ilObject2GUI
20{
21    const CMD_EDIT = "edit";
22    const CMD_VERSIONS = "versions";
23    /**
24     * @var \ilObjFile
25     */
26    public $object;
27    public $lng;
28    protected $log = null;
29    protected $obj_service;
30
31
32    /**
33     * Constructor
34     *
35     * @param int $a_id
36     * @param int $a_id_type
37     * @param int $a_parent_node_id
38     */
39    public function __construct($a_id = 0, $a_id_type = self::REPOSITORY_NODE_ID, $a_parent_node_id = 0)
40    {
41        global $DIC;
42        $this->lng = $DIC->language();
43        $this->log = ilLoggerFactory::getLogger('file');
44        parent::__construct($a_id, $a_id_type, $a_parent_node_id);
45        $this->obj_service = $DIC->object();
46        $this->lng->loadLanguageModule("file");
47    }
48
49
50    public function getType()
51    {
52        return "file";
53    }
54
55
56    public function executeCommand()
57    {
58        global $DIC;
59        $ilNavigationHistory = $DIC['ilNavigationHistory'];
60        $ilCtrl = $DIC['ilCtrl'];
61        $ilUser = $DIC['ilUser'];
62        $ilTabs = $DIC['ilTabs'];
63        $ilAccess = $DIC['ilAccess'];
64        $ilErr = $DIC['ilErr'];
65
66        $next_class = $this->ctrl->getNextClass($this);
67        $cmd = $this->ctrl->getCmd();
68
69        if ($this->id_type == self::WORKSPACE_NODE_ID) {
70            ilFileInputGUI::setPersonalWorkspaceQuotaCheck(true);
71        }
72
73        if (!$this->getCreationMode()) {
74            if ($this->id_type == self::REPOSITORY_NODE_ID
75                && $this->checkPermissionBool("read")
76            ) {
77                $ilCtrl->setParameterByClass("ilrepositorygui", "ref_id", $this->node_id);
78                $link = $ilCtrl->getLinkTargetByClass("ilrepositorygui", "infoScreen");
79                $ilCtrl->setParameterByClass("ilrepositorygui", "ref_id", $_GET["ref_id"]);
80
81                // add entry to navigation history
82                $ilNavigationHistory->addItem(
83                    $this->node_id,
84                    $link,
85                    "file"
86                );
87            }
88        }
89
90        $this->prepareOutput();
91
92        switch ($next_class) {
93            case "ilinfoscreengui":
94                $this->infoScreenForward();    // forwards command
95                break;
96
97            case 'ilobjectmetadatagui':
98                if (!$this->checkPermissionBool("write")) {
99                    $ilErr->raiseError($this->lng->txt('permission_denied'), $ilErr->WARNING);
100                }
101
102                $ilTabs->activateTab("id_meta");
103
104                $md_gui = new ilObjectMetaDataGUI($this->object);
105
106                // todo: make this work
107                // $md_gui->addMDObserver($this->object,'MDUpdateListener','Technical');
108
109                $this->ctrl->forwardCommand($md_gui);
110                break;
111
112            // repository permissions
113            case 'ilpermissiongui':
114                $ilTabs->activateTab("id_permissions");
115                $perm_gui = new ilPermissionGUI($this);
116                $ret = $this->ctrl->forwardCommand($perm_gui);
117                break;
118
119            case "ilexportgui":
120                $ilTabs->activateTab("export");
121                $exp_gui = new ilExportGUI($this);
122                $exp_gui->addFormat("xml");
123                $ret = $this->ctrl->forwardCommand($exp_gui);
124                break;
125
126            case 'ilobjectcopygui':
127                $cp = new ilObjectCopyGUI($this);
128                $cp->setType('file');
129                $this->ctrl->forwardCommand($cp);
130                break;
131
132            // personal workspace permissions
133            case "ilworkspaceaccessgui":
134                $ilTabs->activateTab("id_permissions");
135                $wspacc = new ilWorkspaceAccessGUI($this->node_id, $this->getAccessHandler());
136                $this->ctrl->forwardCommand($wspacc);
137                break;
138
139            case "ilcommonactiondispatchergui":
140                $gui = ilCommonActionDispatcherGUI::getInstanceFromAjaxCall();
141                $this->ctrl->forwardCommand($gui);
142                break;
143
144            case "illearningprogressgui":
145                $ilTabs->activateTab('learning_progress');
146                $new_gui = new ilLearningProgressGUI(
147                    ilLearningProgressGUI::LP_CONTEXT_REPOSITORY,
148                    $this->object->getRefId(),
149                    $_GET['user_id'] ? $_GET['user_id'] : $ilUser->getId()
150                );
151                $this->ctrl->forwardCommand($new_gui);
152                $this->tabs_gui->setTabActive('learning_progress');
153                break;
154            case strtolower(ilFileVersionsGUI::class):
155                $this->tabs_gui->activateTab("id_versions");
156
157                if (!$this->checkPermissionBool("write")) {
158                    $this->ilErr->raiseError($this->lng->txt("permission_denied"), $this->ilErr->MESSAGE);
159                }
160                $this->ctrl->forwardCommand(new ilFileVersionsGUI($this->object));
161                break;
162            default:
163                // in personal workspace use object2gui
164                if ($this->id_type == self::WORKSPACE_NODE_ID) {
165                    $this->addHeaderAction();
166
167                    // coming from goto we need default command
168                    if (empty($cmd)) {
169                        $ilCtrl->setCmd("infoScreen");
170                    }
171                    $ilTabs->clearTargets();
172
173                    return parent::executeCommand();
174                }
175
176                if (empty($cmd)) {
177                    $cmd = "infoScreen";
178                }
179
180                $this->$cmd();
181                break;
182        }
183
184        $this->addHeaderAction();
185    }
186
187
188    /**
189     * @param string $a_new_type
190     */
191    protected function initCreationForms($a_new_type)
192    {
193        $forms = array();
194
195        if ($this->id_type == self::WORKSPACE_NODE_ID) {
196            if (!ilDiskQuotaHandler::isUploadPossible()) {
197                ilUtil::sendFailure($this->lng->txt("personal_resources_quota_exceeded_warning"), true);
198                $this->ctrl->redirect($this, "cancel");
199            }
200        }
201
202        // use drag-and-drop upload if configured
203        if (ilFileUploadSettings::isDragAndDropUploadEnabled()) {
204            $forms[] = $this->initMultiUploadForm();
205        } else {
206            $forms[] = $this->initSingleUploadForm();
207            $forms[] = $this->initZipUploadForm();
208        }
209
210        // repository only
211        if ($this->id_type != self::WORKSPACE_NODE_ID) {
212            $forms[self::CFORM_IMPORT] = $this->initImportForm('file');
213            $forms[self::CFORM_CLONE] = $this->fillCloneTemplate(null, "file");
214        }
215
216        return $forms;
217    }
218
219
220    /**
221     * FORM: Init single upload form.
222     */
223    public function initSingleUploadForm()
224    {
225        global $DIC;
226        $lng = $DIC['lng'];
227
228        include_once("Services/Form/classes/class.ilPropertyFormGUI.php");
229        $single_form_gui = new ilPropertyFormGUI();
230        $single_form_gui->setMultipart(true);
231
232        // File Title
233        $in_title = new ilTextInputGUI($lng->txt("title"), "title");
234        $in_title->setInfo($this->lng->txt("if_no_title_then_filename"));
235        $in_title->setSize(min(40, ilObject::TITLE_LENGTH));
236        $in_title->setMaxLength(ilObject::TITLE_LENGTH);
237        $single_form_gui->addItem($in_title);
238
239        // File Description
240        $in_descr = new ilTextAreaInputGUI($lng->txt("description"), "description");
241        $single_form_gui->addItem($in_descr);
242
243        // File
244        $in_file = new ilFileInputGUI($lng->txt("file"), "upload_file");
245        $in_file->setRequired(true);
246        $single_form_gui->addItem($in_file);
247
248        $single_form_gui->addCommandButton("save", $this->lng->txt($this->type . "_add"));
249        $single_form_gui->addCommandButton("saveAndMeta", $this->lng->txt("file_add_and_metadata"));
250        $single_form_gui->addCommandButton("cancel", $lng->txt("cancel"));
251
252        $single_form_gui->setTableWidth("600px");
253        $single_form_gui->setTarget($this->getTargetFrame("save"));
254        $single_form_gui->setTitle($this->lng->txt($this->type . "_new"));
255        $single_form_gui->setTitleIcon(ilUtil::getImagePath('icon_file.svg'), $this->lng->txt('obj_file'));
256
257        $this->ctrl->setParameter($this, "new_type", "file");
258
259        $single_form_gui->setFormAction($this->ctrl->getFormAction($this, "save"));
260
261        return $single_form_gui;
262    }
263
264
265    /**
266     * save object
267     *
268     * @access    public
269     */
270    public function save()
271    {
272        global $DIC;
273        $ilUser = $DIC->user();
274
275        if (!$this->checkPermissionBool("create", "", "file")) {
276            $this->ilErr->raiseError($this->lng->txt("permission_denied"), $this->ilErr->MESSAGE);
277        }
278
279        $single_form_gui = $this->initSingleUploadForm();
280
281        if ($single_form_gui->checkInput()) {
282            $title = $single_form_gui->getInput("title");
283            $description = $single_form_gui->getInput("description");
284            $upload_file = $single_form_gui->getInput("upload_file");
285
286            if (trim($title) == "") {
287                $title = $upload_file["name"];
288            } else {
289                // BEGIN WebDAV: Ensure that object title ends with the filename extension
290                $fileExtension = ilObjFileAccess::_getFileExtension($upload_file["name"]);
291                $titleExtension = ilObjFileAccess::_getFileExtension($title);
292                if ($titleExtension != $fileExtension && strlen($fileExtension) > 0) {
293                    $title .= '.' . $fileExtension;
294                }
295                // END WebDAV: Ensure that object title ends with the filename extension
296            }
297
298            // create and insert file in grp_tree
299
300            $fileObj = new ilObjFile();
301            $fileObj->setTitle($title);
302            $fileObj->setDescription($description);
303            $fileObj->setFileName($upload_file["name"]);
304
305            $fileObj->setFileType(ilMimeTypeUtil::getMimeType(
306                "",
307                $upload_file["name"],
308                $upload_file["type"]
309            ));
310            $fileObj->setFileSize($upload_file["size"]);
311            $this->object_id = $fileObj->create();
312
313            $this->putObjectInTree($fileObj, $this->parent_id);
314
315            // upload file to filesystem
316            $fileObj->createDirectory();
317            if ($result = $fileObj->getUploadFile($upload_file["tmp_name"], $upload_file["name"])) {
318                $fileObj->setFileName($result->getName());
319            }
320
321            $this->handleAutoRating($fileObj);
322
323            // BEGIN ChangeEvent: Record write event.
324            ilChangeEvent::_recordWriteEvent($fileObj->getId(), $ilUser->getId(), 'create');
325            // END ChangeEvent: Record write event.
326
327            ilUtil::sendSuccess($this->lng->txt("file_added"), true);
328
329            if ($this->ctrl->getCmd() == "saveAndMeta") {
330                $this->ctrl->setParameter($this, "new_type", "");
331                $target = $this->ctrl->getLinkTargetByClass(array("ilobjectmetadatagui", "ilmdeditorgui"), "listSection", "", false, false);
332                ilUtil::redirect($target);
333            } else {
334                $this->ctrl->returnToParent($this);
335            }
336        } else {
337            $single_form_gui->setValuesByPost();
338            $this->tpl->setContent($single_form_gui->getHTML());
339        }
340    }
341
342
343    /**
344     * save object
345     *
346     * @access    public
347     */
348    public function saveAndMeta()
349    {
350        $this->save();
351    }
352
353
354    /**
355     * FORM: Init zip upload form.
356     */
357    public function initZipUploadForm($a_mode = "create")
358    {
359        global $DIC;
360        $lng = $DIC['lng'];
361
362        include_once("Services/Form/classes/class.ilPropertyFormGUI.php");
363        $zip_form_gui = new ilPropertyFormGUI();
364        $zip_form_gui->setMultipart(true);
365
366        // File
367        $in_file = new ilFileInputGUI($lng->txt("file"), "zip_file");
368        $in_file->setRequired(true);
369        $in_file->setSuffixes(array("zip"));
370        $zip_form_gui->addItem($in_file);
371
372        // Take over structure
373        $in_str = new ilCheckboxInputGUI($this->lng->txt("take_over_structure"), "adopt_structure");
374        $in_str->setInfo($this->lng->txt("take_over_structure_info"));
375        $zip_form_gui->addItem($in_str);
376
377        $zip_form_gui->addCommandButton("saveUnzip", $this->lng->txt($this->type . "_add"));
378        $zip_form_gui->addCommandButton("cancel", $lng->txt("cancel"));
379
380        $zip_form_gui->setTableWidth("600px");
381        $zip_form_gui->setTarget($this->getTargetFrame("save"));
382        $zip_form_gui->setTitle($this->lng->txt("header_zip"));
383        $zip_form_gui->setTitleIcon(ilUtil::getImagePath('icon_file.svg'), $this->lng->txt('obj_file'));
384
385        $this->ctrl->setParameter($this, "new_type", "file");
386
387        $zip_form_gui->setFormAction($this->ctrl->getFormAction($this, "saveUnzip"));
388
389        return $zip_form_gui;
390    }
391
392
393    /**
394     * saveUnzip object
395     *
396     * @access    public
397     */
398    public function saveUnzip()
399    {
400        $zip_form_gui = $this->initZipUploadForm();
401
402        if ($this->checkPermissionBool("create", "", "file")) {
403            if ($zip_form_gui->checkInput()) {
404                $zip_file = $zip_form_gui->getInput("zip_file");
405                $adopt_structure = $zip_form_gui->getInput("adopt_structure");
406
407                include_once("Services/Utilities/classes/class.ilFileUtils.php");
408
409                // Create unzip-directory
410                $newDir = ilUtil::ilTempnam();
411                ilUtil::makeDir($newDir);
412
413                // Check if permission is granted for creation of object, if necessary
414                if ($this->id_type != self::WORKSPACE_NODE_ID) {
415                    $type = ilObject::_lookupType((int) $this->parent_id, true);
416                } else {
417                    $type = ilObject::_lookupType($this->tree->lookupObjectId($this->parent_id), false);
418                }
419
420                $tree = $access_handler = null;
421                switch ($type) {
422                    // workspace structure
423                    case 'wfld':
424                    case 'wsrt':
425                        $permission = $this->checkPermissionBool("create", "", "wfld");
426                        $containerType = "WorkspaceFolder";
427                        $tree = $this->tree;
428                        $access_handler = $this->getAccessHandler();
429                        break;
430
431                    // use categories as structure
432                    case 'cat':
433                    case 'root':
434                        $permission = $this->checkPermissionBool("create", "", "cat");
435                        $containerType = "Category";
436                        break;
437
438                    // use folders as structure (in courses)
439                    default:
440                        $permission = $this->checkPermissionBool("create", "", "fold");
441                        $containerType = "Folder";
442                        break;
443                }
444                // 	processZipFile (
445                //		Dir to unzip,
446                //		Path to uploaded file,
447                //		should a structure be created (+ permission check)?
448                //		ref_id of parent
449                //		object that contains files (folder or category)
450                //		should sendInfo be persistent?)
451                try {
452                    $processDone = ilFileUtils::processZipFile(
453                        $newDir,
454                        $zip_file["tmp_name"],
455                        ($adopt_structure && $permission),
456                        $this->parent_id,
457                        $containerType,
458                        $tree,
459                        $access_handler
460                    );
461                    ilUtil::sendSuccess($this->lng->txt("file_added"), true);
462                } catch (ilFileUtilsException $e) {
463                    ilUtil::sendFailure($e->getMessage(), true);
464                }
465
466                ilUtil::delDir($newDir);
467                $this->ctrl->returnToParent($this);
468            } else {
469                $zip_form_gui->setValuesByPost();
470                $this->tpl->setContent($zip_form_gui->getHTML());
471            }
472        } else {
473            $this->ilErr->raiseError($this->lng->txt("permission_denied"), $this->ilErr->MESSAGE);
474        }
475    }
476
477
478    /**
479     * updates object entry in object_data
480     *
481     * @access    public
482     */
483    public function update()
484    {
485        global $DIC;
486        $ilTabs = $DIC['ilTabs'];
487
488        $form = $this->initPropertiesForm();
489        if (!$form->checkInput()) {
490            $ilTabs->activateTab("settings");
491            $form->setValuesByPost();
492            $this->tpl->setContent($form->getHTML());
493
494            return false;
495        }
496
497        $title = $form->getInput('title');
498        // bugfix mantis 26045:
499        $filename = empty($data["name"]) ? $this->object->getFileName() : $data["name"];
500        if (strlen(trim($title)) == 0) {
501            $title = $filename;
502        } else {
503            $title = $this->object->checkFileExtension($filename, $title);
504        }
505        $this->object->setTitle($title);
506        $this->object->setDescription($form->getInput('description'));
507        $this->object->setRating($form->getInput('rating'));
508
509        $this->update = $this->object->update();
510        $this->obj_service->commonSettings()->legacyForm($form, $this->object)->saveTileImage();
511
512        // BEGIN ChangeEvent: Record update event.
513        if (!empty($data["name"])) {
514            global $DIC;
515            $ilUser = $DIC['ilUser'];
516            ilChangeEvent::_recordWriteEvent($this->object->getId(), $ilUser->getId(), 'update');
517            ilChangeEvent::_catchupWriteEvents($this->object->getId(), $ilUser->getId());
518        }
519        // END ChangeEvent: Record update event.
520
521        // Update ecs export settings
522        $ecs = new ilECSFileSettings($this->object);
523        $ecs->handleSettingsUpdate();
524
525        ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
526        ilUtil::redirect($this->ctrl->getLinkTarget($this, self::CMD_EDIT, '', false, false));
527    }
528
529
530    /**
531     * edit object
532     *
533     * @access    public
534     */
535    public function edit()
536    {
537        global $DIC;
538        $ilTabs = $DIC['ilTabs'];
539        $ilErr = $DIC['ilErr'];
540
541        if (!$this->checkPermissionBool("write")) {
542            $ilErr->raiseError($this->lng->txt("msg_no_perm_write"));
543        }
544
545        $ilTabs->activateTab("settings");
546
547        $form = $this->initPropertiesForm(self::CMD_EDIT);
548
549        $val = array();
550        $val['title'] = $this->object->getTitle();
551        $val['description'] = $this->object->getLongDescription();
552        $val['rating'] = $this->object->hasRating();
553        $form->setValuesByArray($val);
554
555        // Edit ecs export settings
556        include_once 'Modules/File/classes/class.ilECSFileSettings.php';
557        $ecs = new ilECSFileSettings($this->object);
558        $ecs->addSettingsToForm($form, 'file');
559
560        $this->tpl->setContent($form->getHTML());
561
562        return true;
563    }
564
565
566    /**
567     *
568     * @param
569     *
570     * @return
571     */
572    protected function initPropertiesForm($mode = "create")
573    {
574        $form = new ilPropertyFormGUI();
575        $form->setFormAction($this->ctrl->getFormAction($this, 'update'));
576
577        $form->setTitle($this->lng->txt('file_edit'));
578        $form->addCommandButton('update', $this->lng->txt('save'));
579        $form->addCommandButton('cancel', $this->lng->txt('cancel'));
580
581        $title = new ilTextInputGUI($this->lng->txt('title'), 'title');
582        $title->setValue($this->object->getTitle());
583        $title->setInfo($this->lng->txt("if_no_title_then_filename"));
584        $form->addItem($title);
585
586        if ($mode === 'create') {
587            $upload_possible = true;
588            if ($this->id_type == self::WORKSPACE_NODE_ID) {
589                $upload_possible = ilDiskQuotaHandler::isUploadPossible();
590            }
591
592            if ($upload_possible) {
593                $file = new ilFileStandardDropzoneInputGUI(
594                    'cancel',
595                    $this->lng->txt('obj_file'),
596                    'file'
597                );
598                $file->setRequired(false);
599                $form->addItem($file);
600
601                $group = new ilRadioGroupInputGUI('', 'replace');
602                $group->setValue(0);
603
604                $replace = new ilRadioOption($this->lng->txt('replace_file'), 1);
605                $replace->setInfo($this->lng->txt('replace_file_info'));
606                $group->addOption($replace);
607
608                $keep = new ilRadioOption($this->lng->txt('file_new_version'), 0);
609                $keep->setInfo($this->lng->txt('file_new_version_info'));
610                $group->addOption($keep);
611
612                $file->addSubItem($group);
613            } elseif ($mode == 'create') {
614                $file = new ilNonEditableValueGUI($this->lng->txt('obj_file'));
615                $file->setValue($this->lng->txt("personal_resources_quota_exceeded_warning"));
616                $form->addItem($file);
617            }
618        } else {
619            $o = new ilNonEditableValueGUI($this->lng->txt('upload_info'));
620            $o->setValue($this->lng->txt('upload_info_desc'));
621            $form->addItem($o);
622        }
623        $desc = new ilTextAreaInputGUI($this->lng->txt('description'), 'description');
624        $desc->setRows(3);
625        $form->addItem($desc);
626
627        if ($this->id_type == self::REPOSITORY_NODE_ID) {
628            $this->lng->loadLanguageModule('rating');
629            $rate = new ilCheckboxInputGUI($this->lng->txt('rating_activate_rating'), 'rating');
630            $rate->setInfo($this->lng->txt('rating_activate_rating_info'));
631            $form->addItem($rate);
632        }
633
634        $presentationHeader = new ilFormSectionHeaderGUI();
635        $presentationHeader->setTitle($this->lng->txt('settings_presentation_header'));
636        $form->addItem($presentationHeader);
637        $this->obj_service->commonSettings()->legacyForm($form, $this->object)->addTileImage();
638
639        return $form;
640    }
641
642
643    public function sendFile()
644    {
645        global $DIC;
646
647        try {
648            if (ANONYMOUS_USER_ID == $DIC->user()->getId() && isset($_GET['transaction'])) {
649                $a_hist_entry_id = isset($_GET["hist_id"]) ? $_GET["hist_id"] : null;
650                $this->object->sendFile($a_hist_entry_id);
651            }
652
653            if ($this->checkPermissionBool("read")) {
654                // BEGIN ChangeEvent: Record read event.
655                require_once('Services/Tracking/classes/class.ilChangeEvent.php');
656
657                // Record read event and catchup with write events
658                ilChangeEvent::_recordReadEvent(
659                    $this->object->getType(),
660                    $this->object->getRefId(),
661                    $this->object->getId(),
662                    $DIC->user()->getId()
663                );
664                // END ChangeEvent: Record read event.
665
666                require_once 'Services/Tracking/classes/class.ilLPStatusWrapper.php';
667                ilLPStatusWrapper::_updateStatus($this->object->getId(), $DIC->user()->getId());
668
669                $a_hist_entry_id = isset($_GET["hist_id"]) ? $_GET["hist_id"] : null;
670                $this->object->sendFile($a_hist_entry_id);
671            } else {
672                $this->ilErr->raiseError($this->lng->txt("permission_denied"), $this->ilErr->MESSAGE);
673            }
674        } catch (\ILIAS\Filesystem\Exception\FileNotFoundException $e) {
675            $this->ilErr->raiseError($e->getMessage(), $this->ilErr->MESSAGE);
676        }
677
678        return true;
679    }
680
681
682    /**
683     * @deprecated
684     */
685    public function versions()
686    {
687        $this->ctrl->redirectByClass(ilFileVersionsGUI::class);
688    }
689
690
691    /**
692     * this one is called from the info button in the repository
693     * not very nice to set cmdClass/Cmd manually, if everything
694     * works through ilCtrl in the future this may be changed
695     */
696    public function infoScreen()
697    {
698        $this->ctrl->setCmd("showSummary");
699        $this->ctrl->setCmdClass("ilinfoscreengui");
700        $this->infoScreenForward();
701    }
702
703
704    /**
705     * show information screen
706     */
707    public function infoScreenForward()
708    {
709        global $DIC;
710        $ilTabs = $DIC['ilTabs'];
711        $ilErr = $DIC['ilErr'];
712        $ilToolbar = $DIC['ilToolbar'];
713
714        $ilTabs->activateTab("id_info");
715
716        if (!$this->checkPermissionBool("visible") && !$this->checkPermissionBool("read")) {
717            $ilErr->raiseError($this->lng->txt("msg_no_perm_read"));
718        }
719
720        include_once("./Services/InfoScreen/classes/class.ilInfoScreenGUI.php");
721        $info = new ilInfoScreenGUI($this);
722
723        if ($this->checkPermissionBool("read", "sendfile")) {
724            // #14378
725            include_once "Services/UIComponent/Button/classes/class.ilLinkButton.php";
726            $button = ilLinkButton::getInstance();
727            $button->setCaption("file_download");
728            $button->setPrimary(true);
729
730            // get permanent download link for repository
731            if ($this->id_type == self::REPOSITORY_NODE_ID) {
732                $button->setUrl(ilObjFileAccess::_getPermanentDownloadLink($this->node_id));
733            } else {
734                $button->setUrl($this->ctrl->getLinkTarget($this, "sendfile"));
735            }
736
737            $ilToolbar->addButtonInstance($button);
738        }
739
740        $info->enablePrivateNotes();
741
742        if ($this->checkPermissionBool("read")) {
743            $info->enableNews();
744        }
745
746        // no news editing for files, just notifications
747        $info->enableNewsEditing(false);
748        if ($this->checkPermissionBool("write")) {
749            $news_set = new ilSetting("news");
750            $enable_internal_rss = $news_set->get("enable_rss_for_internal");
751
752            if ($enable_internal_rss) {
753                $info->setBlockProperty("news", "settings", true);
754                $info->setBlockProperty("news", "public_notifications_option", true);
755            }
756        }
757
758        // standard meta data
759        $info->addMetaDataSections($this->object->getId(), 0, $this->object->getType());
760
761        // File Info
762        $info->addSection($this->lng->txt("file_info"));
763        $info->addProperty($this->lng->txt("filename"), $this->object->getFileName());
764        $info->addProperty($this->lng->txt("type"), $this->object->guessFileType());
765
766        $info->addProperty($this->lng->txt("size"), ilUtil::formatSize(ilObjFile::_lookupFileSize($this->object->getId()), 'long'));
767        $info->addProperty($this->lng->txt("version"), $this->object->getVersion());
768
769        if ($this->object->getPageCount() > 0) {
770            $info->addProperty($this->lng->txt("page_count"), $this->object->getPageCount());
771        }
772
773        // using getVersions function instead of ilHistory direct
774        $uploader = $this->object->getVersions();
775        $uploader = array_shift($uploader);
776        $uploader = $uploader["user_id"];
777
778        include_once "Services/User/classes/class.ilUserUtil.php";
779        $info->addProperty($this->lng->txt("file_uploaded_by"), ilUserUtil::getNamePresentation($uploader));
780
781        // download link added in repository
782        if ($this->id_type == self::REPOSITORY_NODE_ID && $this->checkPermissionBool("read", "sendfile")) {
783            $tpl = new ilTemplate("tpl.download_link.html", true, true, "Modules/File");
784            $tpl->setVariable("LINK", ilObjFileAccess::_getPermanentDownloadLink($this->node_id));
785            $info->addProperty($this->lng->txt("download_link"), $tpl->get());
786        }
787
788        if ($this->id_type == self::WORKSPACE_NODE_ID) {
789            $info->addProperty($this->lng->txt("perma_link"), $this->getPermanentLinkWidget());
790        }
791
792        // display previews
793        include_once("./Services/Preview/classes/class.ilPreview.php");
794        if (!$this->ctrl->isAsynch()
795            && ilPreview::hasPreview($this->object->getId(), $this->object->getType())
796            && $this->checkPermissionBool("read")
797        ) {
798            include_once("./Services/Preview/classes/class.ilPreviewGUI.php");
799
800            // get context for access checks later on
801            $context;
802            switch ($this->id_type) {
803                case self::WORKSPACE_NODE_ID:
804                case self::WORKSPACE_OBJECT_ID:
805                    $context = ilPreviewGUI::CONTEXT_WORKSPACE;
806                    break;
807
808                default:
809                    $context = ilPreviewGUI::CONTEXT_REPOSITORY;
810                    break;
811            }
812
813            $preview = new ilPreviewGUI($this->node_id, $context, $this->object->getId(), $this->access_handler);
814            $info->addProperty($this->lng->txt("preview"), $preview->getInlineHTML());
815        }
816
817        // forward the command
818        // $this->ctrl->setCmd("showSummary");
819        // $this->ctrl->setCmdClass("ilinfoscreengui");
820        $this->ctrl->forwardCommand($info);
821    }
822
823
824    // get tabs
825    public function setTabs()
826    {
827        global $DIC;
828        $ilTabs = $DIC['ilTabs'];
829        $lng = $DIC['lng'];
830        $ilHelp = $DIC['ilHelp'];
831
832        $ilHelp->setScreenIdComponent("file");
833
834        $this->ctrl->setParameter($this, "ref_id", $this->node_id);
835
836        if ($this->checkPermissionBool("write")) {
837            $ilTabs->addTab(
838                "id_versions",
839                $lng->txt(self::CMD_VERSIONS),
840                $this->ctrl->getLinkTargetByClass(ilFileVersionsGUI::class, ilFileVersionsGUI::CMD_DEFAULT)
841            );
842        }
843
844        if ($this->checkPermissionBool("visible") || $this->checkPermissionBool("read")) {
845            $ilTabs->addTab(
846                "id_info",
847                $lng->txt("info_short"),
848                $this->ctrl->getLinkTargetByClass(array("ilobjfilegui", "ilinfoscreengui"), "showSummary")
849            );
850        }
851
852        if ($this->checkPermissionBool("write")) {
853            $ilTabs->addTab(
854                "settings",
855                $lng->txt("settings"),
856                $this->ctrl->getLinkTarget($this, self::CMD_EDIT)
857            );
858        }
859
860        if (ilLearningProgressAccess::checkAccess($this->object->getRefId())) {
861            $ilTabs->addTab(
862                'learning_progress',
863                $lng->txt('learning_progress'),
864                $this->ctrl->getLinkTargetByClass(array(__CLASS__, 'illearningprogressgui'), '')
865            );
866        }
867
868        // meta data
869        if ($this->checkPermissionBool("write")) {
870            $mdgui = new ilObjectMetaDataGUI($this->object);
871            $mdtab = $mdgui->getTab();
872            if ($mdtab) {
873                $ilTabs->addTab(
874                    "id_meta",
875                    $lng->txt("meta_data"),
876                    $mdtab
877                );
878            }
879        }
880
881        // export
882        if ($this->checkPermissionBool("write")) {
883            $ilTabs->addTab(
884                "export",
885                $lng->txt("export"),
886                $this->ctrl->getLinkTargetByClass("ilexportgui", "")
887            );
888        }
889
890        // will add permission tab if needed
891        parent::setTabs();
892    }
893
894
895    public static function _goto($a_target, $a_additional = null)
896    {
897        global $DIC;
898        $ilErr = $DIC['ilErr'];
899        $lng = $DIC['lng'];
900        $ilAccess = $DIC['ilAccess'];
901
902        if ($a_additional && substr($a_additional, -3) == "wsp") {
903            $_GET["baseClass"] = "ilsharedresourceGUI";
904            $_GET["wsp_id"] = $a_target;
905            include("ilias.php");
906            exit;
907        }
908
909        // added support for direct download goto links
910        if ($a_additional && substr($a_additional, -8) == "download") {
911            ilObjectGUI::_gotoRepositoryNode($a_target, "sendfile");
912        }
913
914        // static method, no workspace support yet
915
916        if ($ilAccess->checkAccess("visible", "", $a_target)
917            || $ilAccess->checkAccess("read", "", $a_target)
918        ) {
919            ilObjectGUI::_gotoRepositoryNode($a_target, "infoScreen");
920        } else {
921            if ($ilAccess->checkAccess("read", "", ROOT_FOLDER_ID)) {
922                ilUtil::sendFailure(sprintf(
923                    $lng->txt("msg_no_perm_read_item"),
924                    ilObject::_lookupTitle(ilObject::_lookupObjId($a_target))
925                ), true);
926                ilObjectGUI::_gotoRepositoryRoot();
927            }
928        }
929
930        $ilErr->raiseError($lng->txt("msg_no_perm_read"), $ilErr->FATAL);
931    }
932
933
934    /**
935     *
936     */
937    public function addLocatorItems()
938    {
939        global $DIC;
940        $ilLocator = $DIC['ilLocator'];
941
942        if (is_object($this->object)) {
943            $ilLocator->addItem($this->object->getTitle(), $this->ctrl->getLinkTarget($this, ""), "", $this->node_id);
944        }
945    }
946
947
948    /**
949     * Initializes the upload form for multiple files.
950     *
951     * @return object The created property form.
952     */
953    public function initMultiUploadForm()
954    {
955        include_once("Services/Form/classes/class.ilPropertyFormGUI.php");
956        $dnd_form_gui = new ilPropertyFormGUI();
957        $dnd_form_gui->setMultipart(true);
958        $dnd_form_gui->setHideLabels();
959
960        // file input
961        include_once("Services/Form/classes/class.ilDragDropFileInputGUI.php");
962        $dnd_input = new ilDragDropFileInputGUI($this->lng->txt("files"), "upload_files");
963        $dnd_input->setArchiveSuffixes(array("zip"));
964        $dnd_input->setCommandButtonNames("uploadFiles", "cancel");
965        $dnd_form_gui->addItem($dnd_input);
966
967        // add commands
968        $dnd_form_gui->addCommandButton("uploadFiles", $this->lng->txt("upload_files"));
969        $dnd_form_gui->addCommandButton("cancel", $this->lng->txt("cancel"));
970
971        $dnd_form_gui->setTableWidth("100%");
972        $dnd_form_gui->setTarget($this->getTargetFrame("save"));
973        $dnd_form_gui->setTitle($this->lng->txt("upload_files_title"));
974        $dnd_form_gui->setTitleIcon(ilUtil::getImagePath('icon_file.gif'), $this->lng->txt('obj_file'));
975
976        $this->ctrl->setParameter($this, "new_type", "file");
977        $dnd_form_gui->setFormAction($this->ctrl->getFormAction($this, "uploadFiles"));
978
979        return $dnd_form_gui;
980    }
981
982
983    /**
984     * Called after a file was uploaded.
985     */
986    public function uploadFiles()
987    {
988        global $DIC;
989
990        include_once("./Services/JSON/classes/class.ilJsonUtil.php");
991
992        $response = new stdClass();
993        $response->error = null;
994        $response->debug = null;
995
996        $files = $_FILES;
997
998        // #14249 - race conditions because of concurrent uploads
999        $after_creation_callback = (int) $_REQUEST["crtcb"];
1000        if ($after_creation_callback) {
1001            $this->after_creation_callback_objects = array();
1002            unset($_REQUEST["crtcb"]);
1003        }
1004
1005        // load form
1006        $dnd_form_gui = $this->initMultiUploadForm();
1007        if ($dnd_form_gui->checkInput()) {
1008            try {
1009                if (!$this->checkPermissionBool("create", "", "file")) {
1010                    $response->error = $this->lng->txt("permission_denied");
1011                } else {
1012                    // handle the file
1013                    $inp = $dnd_form_gui->getInput("upload_files");
1014                    $this->log->debug("ilObjFileGUI::uploadFiles " . print_r($_POST, true));
1015                    $this->log->debug("ilObjFileGUI::uploadFiles " . print_r($_FILES, true));
1016                    $fileresult = $this->handleFileUpload($inp);
1017                    if ($fileresult) {
1018                        $response = (object) array_merge((array) $response, (array) $fileresult);
1019                    }
1020                }
1021            } catch (Exception $ex) {
1022                $response->error = $this->lng->txt('general_upload_error_occured');
1023            }
1024        } else {
1025            $dnd_input = $dnd_form_gui->getItemByPostVar("upload_files");
1026            $response->error = $dnd_input->getAlert();
1027        }
1028
1029        if ($after_creation_callback
1030            && sizeof($this->after_creation_callback_objects)
1031        ) {
1032            foreach ($this->after_creation_callback_objects as $new_file_obj) {
1033                ilObject2GUI::handleAfterSaveCallback($new_file_obj, $after_creation_callback);
1034            }
1035            unset($this->after_creation_callback_objects);
1036        }
1037
1038        // send response object (don't use 'application/json' as IE wants to download it!)
1039        header('Vary: Accept');
1040        header('Content-type: text/plain');
1041
1042        if ($DIC->upload()->hasBeenProcessed()) {
1043            foreach ($DIC->upload()->getResults() as $result) {
1044                if (!ilFileUtils::hasValidExtension($result->getName()) && $result->getStatus()->getCode() == ProcessingStatus::OK) {
1045                    ilUtil::sendInfo(
1046                        $this->lng->txt('file_upload_info_file_with_critical_extension'),
1047                        true
1048                    );
1049                }
1050            }
1051        }
1052        echo json_encode($response);
1053        // no further processing!
1054        exit;
1055    }
1056
1057
1058    /**
1059     * Handles the upload of a single file and adds it to the parent object.
1060     *
1061     * @param array $file_upload An array containing the file upload parameters.
1062     *
1063     * @return object The response object.
1064     */
1065    protected function handleFileUpload($file_upload)
1066    {
1067        global $DIC;
1068        $ilUser = $DIC['ilUser'];
1069
1070        if ($DIC->upload()->hasBeenProcessed() !== true) {
1071            if (PATH_TO_GHOSTSCRIPT !== "") {
1072                $DIC->upload()->register(new ilCountPDFPagesPreProcessors());
1073            }
1074        }
1075
1076        $DIC->upload()->process();
1077        /**
1078         * @var $item \ILIAS\FileUpload\DTO\UploadResult
1079         */
1080        $item = reset($DIC->upload()->getResults());
1081
1082        // file upload params
1083
1084        $file_upload['name'] = $item->getName();
1085
1086        $filename = ilUtil::stripSlashes($item->getName());
1087        $type = ilUtil::stripSlashes($item->getMimeType());
1088        $size = ilUtil::stripSlashes($item->getSize());
1089        $temp_name = $item->getPath(); // currently used
1090
1091        // additional params
1092        $title = ilUtil::stripSlashes($file_upload["title"]);
1093        $description = ilUtil::stripSlashes($file_upload["description"]);
1094        $extract = ilUtil::stripSlashes($file_upload["extract"]);
1095        $keep_structure = ilUtil::stripSlashes($file_upload["keep_structure"]);
1096
1097        // create answer object
1098        $response = new stdClass();
1099        $response->fileName = $filename;
1100        $response->fileSize = intval($size);
1101        $response->fileType = $type;
1102        $response->fileUnzipped = $extract;
1103        $response->error = null;
1104
1105        // extract archive?
1106        if ($extract) {
1107            $zip_file = $filename;
1108            $adopt_structure = $keep_structure;
1109
1110            include_once("Services/Utilities/classes/class.ilFileUtils.php");
1111
1112            // Create unzip-directory
1113            $newDir = ilUtil::ilTempnam();
1114            ilUtil::makeDir($newDir);
1115
1116            // Check if permission is granted for creation of object, if necessary
1117            if ($this->id_type != self::WORKSPACE_NODE_ID) {
1118                $type = ilObject::_lookupType((int) $this->parent_id, true);
1119            } else {
1120                $type = ilObject::_lookupType($this->tree->lookupObjectId($this->parent_id), false);
1121            }
1122
1123            $tree = $access_handler = null;
1124            switch ($type) {
1125                // workspace structure
1126                case 'wfld':
1127                case 'wsrt':
1128                    $permission = $this->checkPermissionBool("create", "", "wfld");
1129                    $containerType = "WorkspaceFolder";
1130                    $tree = $this->tree;
1131                    $access_handler = $this->getAccessHandler();
1132                    break;
1133
1134                // use categories as structure
1135                case 'cat':
1136                case 'root':
1137                    $permission = $this->checkPermissionBool("create", "", "cat");
1138                    $containerType = "Category";
1139                    break;
1140
1141                // use folders as structure (in courses)
1142                default:
1143                    $permission = $this->checkPermissionBool("create", "", "fold");
1144                    $containerType = "Folder";
1145                    break;
1146            }
1147
1148            try {
1149                // 	processZipFile (
1150                //		Dir to unzip,
1151                //		Path to uploaded file,
1152                //		should a structure be created (+ permission check)?
1153                //		ref_id of parent
1154                //		object that contains files (folder or category)
1155                //		should sendInfo be persistent?)
1156                ilFileUtils::processZipFile(
1157                    $newDir,
1158                    $temp_name,
1159                    ($adopt_structure && $permission),
1160                    $this->parent_id,
1161                    $containerType,
1162                    $tree,
1163                    $access_handler
1164                );
1165            } catch (ilFileUtilsException $e) {
1166                $response->error = $e->getMessage();
1167            } catch (Exception $ex) {
1168                $response->error = $this->lng->txt('general_upload_error_occured');
1169            }
1170
1171            ilUtil::delDir($newDir);
1172
1173            // #15404
1174            if ($this->id_type != self::WORKSPACE_NODE_ID) {
1175                foreach (ilFileUtils::getNewObjects() as $parent_ref_id => $objects) {
1176                    if ($parent_ref_id != $this->parent_id) {
1177                        continue;
1178                    }
1179
1180                    foreach ($objects as $object) {
1181                        $this->after_creation_callback_objects[] = $object;
1182                    }
1183                }
1184            }
1185        } else {
1186            // create and insert file in grp_tree
1187            $fileObj = new ilObjFile();
1188            // bugfix mantis 0026043
1189            if (strlen(trim($title)) == 0) {
1190                $title = $filename;
1191            } else {
1192                $title = $fileObj->checkFileExtension($filename, $title);
1193            }
1194            $fileObj->setTitle($title);
1195            $fileObj->setDescription($description);
1196            $fileObj->setFileName($filename);
1197            $fileObj->setFileType($type);
1198            $fileObj->setFileSize($size);
1199            $this->object_id = $fileObj->create();
1200            $this->putObjectInTree($fileObj, $this->parent_id);
1201
1202            // see uploadFiles()
1203            if (is_array($this->after_creation_callback_objects)) {
1204                $this->after_creation_callback_objects[] = $fileObj;
1205            }
1206
1207            // upload file to filesystem
1208            $fileObj->createDirectory();
1209            $fileObj->raiseUploadError(true);
1210
1211            $result = $fileObj->getUploadFile($temp_name, $filename);
1212
1213            if ($result) {
1214                //if no title for the file was set use the filename as title
1215                if (empty($fileObj->getTitle())) {
1216                    $fileObj->setTitle($filename);
1217                }
1218                $fileObj->setFileName($filename);
1219            }
1220            $fileObj->update();
1221            $this->handleAutoRating($fileObj);
1222
1223            ilChangeEvent::_recordWriteEvent($fileObj->getId(), $ilUser->getId(), 'create');
1224        }
1225
1226        return $response;
1227    }
1228
1229
1230    protected function initHeaderAction($a_sub_type = null, $a_sub_id = null)
1231    {
1232        $lg = parent::initHeaderAction($a_sub_type, $a_sub_id);
1233        if (is_object($lg)) {
1234            if ($this->object->hasRating()) {
1235                $lg->enableRating(
1236                    true,
1237                    null,
1238                    false,
1239                    array("ilcommonactiondispatchergui", "ilratinggui")
1240                );
1241            }
1242        }
1243
1244        return $lg;
1245    }
1246}
1247