Skip to content
Snippets Groups Projects
Select Git revision
  • ac88ca6e61d1f5a628ef2c50ebb63794756f3f85
  • main default protected
  • studip-rector
  • ci-opt
  • course-members-export-as-word
  • data-vue-app
  • pipeline-improvements
  • webpack-optimizations
  • rector
  • icon-renewal
  • http-client-and-factories
  • jsonapi-atomic-operations
  • vueify-messages
  • tic-2341
  • 135-translatable-study-areas
  • extensible-sorm-action-parameters
  • sorm-configuration-trait
  • jsonapi-mvv-routes
  • docblocks-for-magic-methods
19 results

file.php

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    file.php 94.07 KiB
    <?php
    /**
     * file.php - controller to display files in a course
     *
     * This controller contains actions related to single files.
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License as
     * published by the Free Software Foundation; either version 2 of
     * the License, or (at your option) any later version.
     *
     * @author      Moritz Strohm <strohm@data-quest.de>
     * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
     * @category    Stud.IP
     * @since       4.0
     */
    class FileController extends AuthenticatedController
    {
        protected $allow_nobody = true;
    
        function validate_args(&$args, $types = NULL)
        {
            reset($args);
        }
    
        /**
         * This is a helper method that decides where a redirect shall be made
         * in case of error or success after an action was executed.
         */
        public function redirectToFolder($folder)
        {
            switch ($folder->range_type) {
                case 'course':
                case 'institute':
                    $this->relocate($folder->range_type . '/files/index/' . $folder->getId(), ['cid' => $folder->range_id]);
                   break;
                case 'user':
                    $this->relocate('files/index/' . $folder->getId(), ['cid' => null]);
                    break;
                case 'Resource':
                    $this->relocate(
                        'resources/resource/files/'
                      . $folder->range_id . '/'
                      . $folder->getId()
                    );
                    break;
                default:
                    //Plugins should not be available in the flat view.
                    $this->relocate('files/system/' . $folder->range_type . '/' . $folder->getId(), ['cid' => null]);
                    break;
            }
        }
    
    
        public function upload_window_action()
        {
            // just send the template
        }
    
        public function upload_action($folder_id)
        {
            if (Request::get("from_plugin")) {
                $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/upload/") + strlen("dispatch.php/file/upload/"));
                if (strpos($folder_id, "?") !== false) {
                    $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $folder = $plugin->getFolder($folder_id);
            } else {
                $folder = FileManager::getTypedFolder($folder_id);
            }
    
            URLHelper::addLinkParam('from_plugin', Request::get('from_plugin'));
            URLHelper::addLinkParam('to_plugin', Request::get('to_plugin'));
    
            if (!$folder || !$folder->isWritable($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
            if (Request::isPost()) {
                if (is_array($_FILES['file'])) {
                    $validatedFiles = FileManager::handleFileUpload(
                        $_FILES['file'],
                        $folder,
                        $GLOBALS['user']->id
                    );
    
                    if (count($validatedFiles['error']) > 0) {
                        $this->response->add_header(
                            'X-Filesystem-Changes',
                            json_encode(['message' => null])
                        );
                        // error during upload: display error message:
                        $this->render_json([
                            'message' => (string) MessageBox::error(
                                _('Beim Hochladen ist ein Fehler aufgetreten '),
                                array_map('htmlready', $validatedFiles['error'])
                            ),
                        ]);
    
                        return;
                    }
    
                    //all files were uploaded successfully:
                    if (count($validatedFiles['files']) > 0) {
                        PageLayout::postSuccess(
                            sprintf(
                                _('Es wurden %s Dateien hochgeladen'),
                                count($validatedFiles['files'])
                            ),
                            array_map(function ($file) {
                                return htmlReady($file->getFilename());
                            }, $validatedFiles['files']),
                            true
                        );
                    }
                } else {
                    $this->response->add_header('X-Filesystem-Changes', json_encode(['message' => null]));
                    $this->render_json([
                        'message' => (string) MessageBox::error(
                            _('Ein Systemfehler ist beim Upload aufgetreten.')
                        )
                    ]);
                    return;
                }
    
                if (Request::isXhr()) {
                    $changes = ['added_files' => null];
                    $output  = ['added_files' => []];
    
                    if (count($validatedFiles['files']) === 1
                        && strtolower(substr($validatedFiles['files'][0]->getFilename(), -4)) === '.zip'
                        && ($folder->range_id === $GLOBALS['user']->id || Seminar_Perm::get()->have_studip_perm('tutor', $folder->range_id)))
                    {
                        $ref_ids = [];
                        foreach ($validatedFiles['files'] as $file) {
                            $ref_ids[] = $file->getId();
                        }
                        $changes['redirect'] = $this->url_for('file/unzipquestion', [
                            'file_refs' => $ref_ids
                        ]);
                    } elseif (in_array($folder->range_type, ['course', 'institute', 'user'])) {
                        $ref_ids = [];
                        foreach ($validatedFiles['files'] as $file) {
                            $ref_ids[] = $file->getId();
                        }
                        $changes['redirect'] = $this->url_for("file/edit_license/{$folder->getId()}", [
                            'file_refs' => $ref_ids,
                        ]);
                    } else {
                        $changes['close_dialog'] = true;
                    }
    
                    $this->current_folder = $folder;
                    foreach ($validatedFiles['files'] as $file) {
                        $output['added_files'][] = FilesystemVueDataManager::getFileVueData($file, $folder);
                    }
    
                    $this->response->add_header(
                        'X-Filesystem-Changes',
                        json_encode($changes)
                    );
                    $this->render_json($output);
                }
            }
    
            $this->folder_id = $folder_id;
        }
    
    
        public function unzipquestion_action()
        {
            $this->to_plugin      = Request::get('to_plugin');
            URLHelper::addLinkParam('to_plugin', $this->to_plugin);
    
            $this->files      = [];
            if ($this->to_plugin) {
                //Plugin file area.
                $plugin = PluginManager::getInstance()->getPlugin($this->to_plugin);
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                if (!($plugin instanceof FilesystemPlugin)) {
                    throw new Trails_Exception(400, _('Das Plugin ist kein Dateibereich-Plugin.'));
                }
                $file_ids = Request::getArray('file_refs');
                foreach ($file_ids as $file_id) {
                    $file = $plugin->getPreparedFile($file_id);
                    if ($file instanceof FileType) {
                        $this->files[] = $file;
                    }
                }
            } else {
                //Stud.IP file area.
                $file_refs = FileRef::findMany(Request::getArray('file_refs'));
                foreach ($file_refs as $file_ref) {
                    $this->files[] = $file_ref->getFileType();
                }
            }
            $this->first_file     = $this->files[0];
            $this->current_folder = $this->first_file->getFolderType();
    
            if (Request::isPost()) {
                $changes = [];
    
                if (Request::submitted('unzip')) {
                    //unzip!
                    $this->files = FileArchiveManager::extractArchiveFileToFolder(
                        $this->first_file,
                        $this->current_folder,
                        $GLOBALS['user']->id
                    );
    
                    $ref_ids = [];
    
                    foreach ($this->files as $file) {
                        $ref_ids[] = $file->getId();
                    }
    
                    //Delete the original zip file:
                    $changes['removed_files'] = [$this->first_file->getId()];
                    $this->first_file->delete();
                } else {
                    $ref_ids = [$this->first_file->getId()];
                }
    
                $this->flash->set('file_refs', $ref_ids);
    
                if (Request::isXhr()) {
                    $topFolder = null;
    
                    $changes['redirect'] = $this->url_for("file/edit_license/{$this->current_folder->getId()}");
                    $changes['added_files'] = null;
                    $changes['added_folders'] = null;
    
                    $payload = [
                        'add_files'   => [],
                        'add_folders' => [],
                    ];
                    $added_folders = [];
                    foreach ($this->files as $file) {
                        $folder = $file->getFolderType();
                        if ($folder && $folder->getId() === $this->current_folder->getId()) {
                            $payload['added_files'][] = FilesystemVueDataManager::getFileVueData($file, $this->current_folder);
                        } elseif (
                            $folder->getParent() &&
                            $folder->getParent()->getId() === $this->current_folder->getId()
                            && !in_array($folder->getId(), $added_folders)
                        ) {
                            if ($topFolder === null) {
                                $topFolder = $this->current_folder;
                                while ($topFolder->getParent() !== null) {
                                    $topFolder = $topFolder->getParent();
                                }
                            }
    
                            $payload['added_folders'][] = FilesystemVueDataManager::getFolderVueData($folder, $this->current_folder);
    
                            $added_folders[] = $folder->getId();
                        }
                    }
    
                    $this->response->add_header(
                        'X-Filesystem-Changes',
                        json_encode($changes)
                    );
                    $this->render_json($payload);
                } else {
                    $this->redirect("file/edit_license/{$this->current_folder->getId()}");
                }
            }
        }
    
        /**
         * Displays details about a file or a folder.
         *
         * @param string $file_area_object_id A file area object like a Folder or a FileRef.
         */
        public function details_action($file_area_object_id = null)
        {
            $this->include_navigation = Request::get('file_navigation', false);
            //check if the file area object is a FileRef:
            $this->from_plugin = Request::get("from_plugin");
            if ($this->from_plugin) {
                $file_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/details/") + strlen("dispatch.php/file/details/"));
                if (strpos($file_id, "?") !== false) {
                    $file_id = substr($file_id, 0, strpos($file_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin($this->from_plugin);
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $this->file = $plugin->getPreparedFile($file_id);
            } else {
                $file_ref = FileRef::find($file_area_object_id);
                if ($file_ref) {
                    $this->file = $file_ref->getFileType();
                }
            }
    
            if ($this->file) {
                //file system object is a FileRef
                PageLayout::setTitle($this->file->getFilename());
    
                //Check if file is downloadable for the current user:
                $this->show_preview    = false;
                $this->is_downloadable = false;
    
                $this->is_standard_file = get_class($this->file) === StandardFile::class;
    
                // NOTE: The following can only work properly for folders which are
                // stored in the database, since remote folders
                // (for example owncloud/nextcloud folders) are not stored in the database.
                $folder = $this->file->getFolderType();
                if (!$folder->isVisible(User::findCurrent()->id)) {
                    throw new AccessDeniedException();
                }
                $this->is_downloadable = $this->file->isDownloadable(User::findCurrent()->id);
                $this->is_editable     = $this->file->isEditable(User::findCurrent()->id);
                $this->file_info_template = $this->file->getInfoTemplate($this->is_downloadable);
    
                //load the previous and next file in the folder,
                //if the folder is of type FolderType.
                $this->previous_file_ref_id = false;
                $this->next_file_ref_id     = false;
                if ($this->include_navigation && $folder->isReadable(User::findCurrent()->id)) {
                    $current_file_ref_id = null;
                    foreach ($folder->getFiles() as $folder_file) {
                        $last_file_ref_id = $current_file_ref_id;
                        $current_file_ref_id = $folder_file->getId();
    
                        if ($folder_file->getId() === $this->file->getId()) {
                            $this->previous_file_ref_id = $last_file_ref_id;
                        }
    
                        if ($last_file_ref_id === $this->file->getId()) {
                            $this->next_file_ref_id = $folder_file->getId();
                            //at this point we have the ID of the previous
                            //and the next file ref so that we can exit
                            //the foreach loop:
                            break;
                        }
                    }
                }
                $this->fullpath = FileManager::getFullPath($folder);
    
                $this->render_action('file_details');
            } else {
                //file area object is not a FileRef: maybe it's a folder:
                if ($this->from_plugin) {
                    $this->folder = $plugin->getFolder($file_id);
                } else {
                    $this->folder = FileManager::getTypedFolder($file_area_object_id);
                }
                if (!$this->folder || !$this->folder->isVisible($GLOBALS['user']->id)) {
                    throw new AccessDeniedException();
                }
    
                //The file system object is a folder.
                //Calculate the files and the folder size:
                list($this->folder_size, $this->folder_file_amount) = $this->getFolderSize($this->folder);
                PageLayout::setTitle($this->folder->name);
                $this->render_action('folder_details');
            }
        }
    
        /**
         * The action for editing a file reference.
         */
        public function edit_action($file_ref_id)
        {
            if (Request::get("from_plugin")) {
                $file_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/edit/") + strlen("dispatch.php/file/edit/"));
                if (strpos($file_id, "?") !== false) {
                    $file_id = substr($file_id, 0, strpos($file_id, "?"));
                }
                $file_ref_id = $file_id;
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
    
                $this->file = $plugin->getPreparedFile($file_id);
                $this->from_plugin = Request::get("from_plugin");
    
            } else {
                $this->file_ref = FileRef::find($file_ref_id);
                $this->file = $this->file_ref->getFileType();
            }
    
            $this->folder = $this->file->getFoldertype();
    
            if (!$this->folder || !$this->folder->isFileEditable($this->file->getId(), $GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            $this->content_terms_of_use_entries = ContentTermsOfUse::findAll();
            $this->show_force_button = false;
    
            if (Request::isPost()) {
                //form was sent
                CSRFProtection::verifyUnsafeRequest();
                $this->errors = [];
    
                $force_save = Request::submitted('force_save');
                $this->name = trim(Request::get('name'));
                $this->description = Request::get('description');
                $this->store_accessibility_flag($this->file);
    
                $this->content_terms_of_use_id = Request::get('content_terms_of_use_id');
    
                //Check if the FileRef is unmodified:
                if (($this->name == $this->file_ref->name) &&
                    ($this->description == $this->file_ref->description) &&
                    ($this->content_terms_of_use_id == $this->file_ref->content_terms_of_use_id)) {
                    $this->redirectToFolder($this->folder);
                    return;
                }
                //Check if the file extension has changed:
                $old_file_extension = pathinfo($this->file_ref->name, PATHINFO_EXTENSION);
                $new_file_extension = pathinfo($this->name, PATHINFO_EXTENSION);
                if ($old_file_extension !== $new_file_extension && !$force_save) {
                    if (!$new_file_extension) {
                        PageLayout::postWarning(
                            sprintf(
                                _('Die Dateiendung "%1$s" wird entfernt. Soll die Datei trotzdem gespeichert werden?'),
                                htmlReady($old_file_extension)
                            )
                        );
                    } elseif (!$old_file_extension) {
                        PageLayout::postWarning(
                            sprintf(
                                _('Die Dateiendung wird auf "%1$s" gesetzt. Soll die Datei trotzdem gespeichert werden?'),
                                htmlReady($new_file_extension)
                            )
                        );
                    } else {
                        PageLayout::postWarning(
                            sprintf(
                                _('Die Dateiendung wird von "%1$s" auf "%2$s" geändert. Soll die Datei trotzdem gespeichert werden?'),
                                htmlReady($old_file_extension),
                                htmlReady($new_file_extension)
                            )
                        );
                    }
                    $this->show_force_button = true;
                    return;
                }
    
                if (Request::get("from_plugin")) {
                    $result = $this->folder->editFile(
                        $file_ref_id,
                        $this->name,
                        $this->description,
                        $this->content_terms_of_use_id
                    );
                } else {
                    $result = FileManager::editFileRef(
                        $this->file_ref,
                        User::findCurrent(),
                        $this->name,
                        $this->description,
                        $this->content_terms_of_use_id
                    );
                }
    
                if (!$result instanceof FileRef) {
                    $this->errors = array_merge($this->errors, $result);
                }
    
    
                if ($this->errors) {
                    PageLayout::postError(
                        sprintf(
                            _('Fehler beim Ändern der Datei %s!'),
                            htmlReady($this->file_ref->name)
                        ),
                        $this->errors
                    );
                } else {
                    PageLayout::postSuccess(_('Änderungen gespeichert!'));
                    $this->redirectToFolder($this->folder);
                }
            }
    
            $this->name = $this->file->getFilename();
            $this->description = $this->file->getDescription();
            $this->content_terms_of_use = $this->file->getTermsOfUse();
        }
    
        public function oer_post_upload_action($file_ref_id)
        {
            $this->file_ref_id = $file_ref_id;
            PageLayout::setTitle(_('Datei für OER-Campus bereitstellen'));
    
            $this->semester_ende = date('d.m.Y',  Semester::findCurrent()->ende);
    
            if (Request::isPost()) {
                CSRFProtection::verifyUnsafeRequest();
                $oer_share = Request::int('oer_upload');
                $redirect = Request::get('redirect_to_files');
    
                if ($oer_share === 1) {
                    // share now
                    return $this->share_oer_action($this->file_ref_id, $redirect);
                } else if ($oer_share === 2) {
                    // save and send a reminder to share later
                    $oer_post_upload = new OERPostUpload();
                    $oer_post_upload->file_ref_id = $this->file_ref_id;
                    $oer_post_upload->user_id = $GLOBALS['user']->id;
                    $oer_post_upload->reminder_date = Semester::findCurrent()->ende;
                    $oer_post_upload->store();
                    $this->response->add_header('X-Dialog-Close', '1');
                    $this->render_nothing();
                    PageLayout::postSuccess(_('Erinnerung wurde gespeichert.'));
                } else {
                    $this->response->add_header('X-Dialog-Close', '1');
                }
            }
        }
    
        /**
         * The action for sharing a file on the oer campus
         */
        public function share_oer_action($file_ref_id, $redirect = null)
        {
            $this->redirect = $redirect;
            $this->file_ref = FileRef::find($file_ref_id);
            $this->file = $this->file_ref->getFileType();
    
            $this->folder = $this->file->getFoldertype();
    
            if (
                !$this->folder
                || !$this->folder->isFileEditable($this->file->getId(), $GLOBALS['user']->id)
                || !$GLOBALS['perm']->have_perm(Config::get()->OER_PUBLIC_STATUS)
            ) {
                throw new AccessDeniedException();
            }
    
            $_SESSION['NEW_OER'] = [
                'name' => $this->file->getFilename(),
                'filename' => $this->file->getFilename(),
                'description' => $this->file->getDescription(),
                'player_url' => null,
                'tags' => [],
                'tmp_name' => $this->file->getPath(),
                'content_type' => $this->file->getMimeType(),
                'image_tmp_name' => null
            ];
    
            // only if you were in Dateibereich
            if ($this->redirect === 'redirect_to_files') {
                $_SESSION['NEW_OER']['redirect_url'] = 'files';
                $_SESSION['NEW_OER']['dir'] = $this->folder->getId();
                $_SESSION['NEW_OER']['cid'] = $this->folder->range_id;
            }
    
            $this->redirect('oer/mymaterial/edit');
        }
    
        /**
         * The action for suggesting a file for the oer campus to the file owner
         */
        public function suggest_oer_action($file_ref_id)
        {
            $this->file_ref_id = $file_ref_id;
            $file_ref = FileRef::find($file_ref_id);
            $filetype = $file_ref->getFileType();
            $this->file = $filetype->convertToStandardFile();
            $this->icon_shape = $this->file->getIcon(Icon::ROLE_INFO)->getShape();
    
            $this->author = $file_ref->owner->username;
            $this->author_fullname = $file_ref->owner->getFullName('no_title');
            $this->link_to_share = URLHelper::getURL("dispatch.php/file/share_oer/" . $file_ref_id);
            $this->linktext = _('Klicken Sie hier, um das Material im OER Campus zu veröffentlichen.');
            $this->formatted_link = '['. $this->linktext .']' . $this->link_to_share;
            $additional_text = htmlReady(Request::get('additional_text'));
    
            $oer_suggestion_message = sprintf(_("Ihre hochgeladene Datei wurde zur Veröffentlichung im
                OER Campus vorgeschlagen:\n\n"
                . "Dateiname: %s \n"
                . "Beschreibung: %s \n\n"
                . "%s \n\n"
                . "Zusätzliche Info: \n %s"),
                $this->file->getFilename(),
                $this->file->getDescription(),
                $this->formatted_link,
                $additional_text
            );
    
            if (Request::isPost()) {
                CSRFProtection::verifyUnsafeRequest();
    
                // send a private message to the file author
                $messaging = new messaging();
    
                $messaging->insert_message(
                    $oer_suggestion_message,
                    $this->author,
                    '____%system%____',
                    '',
                    Request::option('message_id'),
                    '',
                    null,
                    _('Vorschlag zur Veröffentlichung einer Datei im OER Campus')
                );
                $this->response->add_header('X-Dialog-Close', '1');
                $this->render_nothing();
    
                PageLayout::postSuccess(_('Vorschlag wurde eingereicht.'));
    
            }
    
        }
    
        public function edit_urlfile_action($file_ref_id)
        {
            $this->file_ref = FileRef::find($file_ref_id);
            $this->file = $this->file_ref->getFileType();
            $this->folder = $this->file_ref->foldertype;
    
            if (!$this->folder || !$this->folder->isFileEditable($this->file_ref->id, $GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            $this->content_terms_of_use_entries = ContentTermsOfUse::findAll();
            $this->show_force_button = false;
    
            if (Request::isPost()) {
                //form was sent
                CSRFProtection::verifyUnsafeRequest();
                $this->file_ref['name'] = trim(Request::get('name'));
                $this->file_ref['description'] = trim(Request::get('description'));
                $this->file_ref['content_terms_of_use_id'] = Request::get('content_terms_of_use_id');
                $this->file_ref->file['metadata']['url'] = Request::get('url');
                $this->file_ref->file['metadata']['access_type'] = Request::get('access_type');
                $this->file_ref->file->store();
                $this->file_ref->store();
    
                PageLayout::postSuccess(_('Änderungen gespeichert!'));
                $this->redirectToFolder($this->folder);
            }
    
            $this->name = $this->file_ref->name;
            $this->url = $this->file_ref->file['metadata']['url'];
            $this->description = $this->file_ref->description;
            $this->content_terms_of_use_id = $this->file_ref->content_terms_of_use_id;
        }
    
        /**
         * This action is responsible for updating a file reference.
         */
        public function update_action($file_ref_id)
        {
            if (Request::get("from_plugin")) {
                $file_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/update/") + strlen("dispatch.php/file/update/"));
                if (strpos($file_id, "?") !== false) {
                    $file_id = substr($file_id, 0, strpos($file_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $this->file = $plugin->getPreparedFile($file_id);
                $this->from_plugin = Request::get("from_plugin");
            } else {
                $this->file_ref = FileRef::find($file_ref_id);
                $this->file = $this->file_ref->getFileType();
            }
            $this->folder = $this->file->getFolderType();
    
            if (!$this->file->isEditable($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            $this->errors = [];
    
            if (Request::submitted('confirm')) {
                $update_filename = (bool) Request::get('update_filename', false);
                $update_all_instances = (bool) Request::get('update_all_instances', false);
                CSRFProtection::verifyUnsafeRequest();
    
                //Form was sent
                if (Request::isPost() && is_array($_FILES['file'])) {
    
                    if ($this->file_ref) {
                        $result = FileManager::updateFileRef(
                            $this->file_ref,
                            User::findCurrent(),
                            $_FILES['file'],
                            $update_filename,
                            $update_all_instances
                        );
                    } else {
    
                    }
    
                    if (!$result instanceof FileRef) {
                        $this->errors = array_merge($this->errors, $result);
                    }
    
                } else {
                    $this->errors[] = _('Es wurde keine neue Dateiversion gewählt!');
                }
    
                if ($this->errors) {
                    PageLayout::postError(
                        sprintf(
                            _('Fehler beim Aktualisieren der Datei %s!'),
                            htmlReady($this->file_ref->name)
                        ),
                        $this->errors
                    );
                } else {
                    PageLayout::postSuccess(
                        sprintf(
                            _('Datei %s wurde aktualisiert!'),
                            htmlReady($this->file_ref->name)
                        )
                    );
                }
                $this->redirectToFolder($this->folder);
            }
        }
    
        public function choose_destination_action($copymode, $fileref_id = null)
        {
            PageLayout::setTitle(_('Ziel wählen'));
    
            $this->hidden = false; //This is used in the view.
    
            if (empty($fileref_id)) {
                $fileref_id = Request::getArray('fileref_id');
            } elseif ($fileref_id === 'bulk') {
                $fileref_id = Request::getArray('ids');
            }
            $this->copymode = $copymode;
            $this->fileref_id = $fileref_id;
            $this->is_folder = false;
    
            if (Request::get("from_plugin")) {
                if (is_array($fileref_id)) {
                    $file_id = $fileref_id[0];
                } else {
                    $file_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/choose_destination/".$copymode."/") + strlen("dispatch.php/file/choose_destination/".$copymode."/"));
                    if (strpos($file_id, "?") !== false) {
                        $file_id = substr($file_id, 0, strpos($file_id, "?"));
                    }
                    $fileref_id = [$file_id];
                }
                $file_id = $fileref_id[0];
                $this->fileref_id = $fileref_id;
    
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
    
                $this->file_ref = $plugin->getPreparedFile($file_id);
                if (!$this->file_ref) {
                    //Maybe it is a folder:
                    $folder = $plugin->getFolder($file_id);
                    if ($folder instanceof FolderType) {
                        $this->parent_folder = $folder->getParent();
                        $this->is_folder = true;
                    }
                }
            } else {
                if (is_array($fileref_id)) {
                    $this->file_ref = FileRef::find($fileref_id[0]);
                } else {
                    $this->file_ref = FileRef::find($fileref_id);
    
                    $this->fileref_id = [$fileref_id];
                }
            }
    
            if ($this->file_ref && Request::submitted("from_plugin")) {
                $this->parent_folder = $this->file_ref->getFoldertype();
            } elseif ($this->file_ref) {
                $this->parent_folder = Folder::find($this->file_ref->folder_id);
                $this->parent_folder = $this->parent_folder->getTypedFolder();
            } elseif (!Request::submitted("from_plugin")) {
                $folder = Folder::find(is_array($fileref_id) ? $fileref_id[0] : $fileref_id);
                if ($folder) {
                    $this->parent_folder = Folder::find($folder->parent_id);
                    $this->parent_folder = $this->parent_folder->getTypedFolder();
                    $this->is_folder = true;
                }
            } elseif (!$this->parent_folder) {
                throw new AccessDeniedException();
            }
    
            $this->plugin = Request::get('from_plugin');
        }
    
    
        public function download_folder_action($folder_id)
        {
            $user = User::findCurrent();
    
            if (Request::get("from_plugin")) {
                $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/download_folder/") + strlen("dispatch.php/file/download_folder/"));
    
                if (strpos($folder_id, "?") !== false) {
                    $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $foldertype = $plugin->getFolder($folder_id);
    
            } else {
                $folder = Folder::find($folder_id);
                if ($folder) {
                    $foldertype = $folder->getTypedFolder();
                }
            }
            if ($foldertype) {
                $tmp_file = tempnam($GLOBALS['TMP_PATH'], 'doc');
    
                $result = FileArchiveManager::createArchive(
                    [$foldertype],
                    $user->id,
                    $tmp_file,
                    true,
                    true,
                    false,
                    'UTF-8',
                    true
                );
    
                if ($result) {
                    $filename = $folder ? $folder->name : basename($tmp_file);
    
                    //ZIP file was created successfully
                    $this->redirect(FileManager::getDownloadURLForTemporaryFile(
                        basename($tmp_file),
                        FileManager::cleanFileName("{$filename}.zip")
                    ));
                } else {
                    throw new Exception('Error while creating ZIP archive!');
                }
            } else {
                throw new Exception('Folder not found in database!');
            }
        }
    
        public function choose_folder_from_course_action()
        {
            PageLayout::setTitle(_('Zielordner von Veranstaltung wählen'));
    
            if (Request::get('course_id')) {
                $folder = Folder::findTopFolder(Request::get("course_id"));
                $this->redirect($this->url_for(
                    'file/choose_folder/' . $folder->getId(), [
                        'from_plugin'  => Request::get('from_plugin'),
                        'fileref_id' => Request::getArray('fileref_id'),
                        'copymode'   => Request::get('copymode'),
                        'isfolder'   => Request::get('isfolder')
                    ]
                ));
                return;
            }
    
            $this->plugin = Request::get('from_plugin');
            if (!$GLOBALS['perm']->have_perm("admin")) {
                $query = "SELECT seminare.*, MAX(`beginn`) as sorter
                          FROM seminare
                          INNER JOIN seminar_user ON (seminar_user.Seminar_id = seminare.Seminar_id)
                          LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id)
                          LEFT JOIN semester_data ON (semester_courses.semester_id = semester_data.semester_id)
                          WHERE seminar_user.user_id = :user_id
                          GROUP BY seminare.Seminar_id
                          ";
                if (Config::get()->DEPUTIES_ENABLE) {
                    $query .= " UNION
                        SELECT `seminare`.*, MAX(`beginn`) as sorter
                        FROM `seminare`
                        INNER JOIN `deputies` ON (`deputies`.`range_id` = `seminare`.`Seminar_id`)
                        LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id)
                        LEFT JOIN semester_data ON (semester_courses.semester_id = semester_data.semester_id)
                        WHERE `deputies`.`user_id` = :user_id
                        GROUP BY seminare.Seminar_id";
                }
                $query .= " ORDER BY sorter DESC, Name ASC";
                $statement = DBManager::get()->prepare($query);
                $statement->execute([':user_id' => $GLOBALS['user']->id]);
                $this->courses = [];
    
                foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $coursedata) {
                    $this->courses[] = Course::buildExisting($coursedata);
                }
            }
        }
    
        public function choose_folder_from_institute_action()
        {
            PageLayout::setTitle(_('Zielordner von Einrichtung wählen'));
    
            if (Request::get('Institut_id')) {
                $folder = Folder::findTopFolder(Request::get("Institut_id"));
                $this->redirect($this->url_for(
                    'file/choose_folder/' . $folder->getId(), [
                        'from_plugin'  => Request::get('from_plugin'),
                        'fileref_id' => Request::getArray('fileref_id'),
                        'copymode'   => Request::get('copymode'),
                        'isfolder'   => Request::get('isfolder'),
                    ]
                ));
                return;
            }
    
            if ($GLOBALS['perm']->have_perm('root')) {
                $sql = "SELECT DISTINCT Institute.Institut_id, Institute.Name
                        FROM Institute
                        LEFT JOIN range_tree ON (range_tree.item_id = Institute.Institut_id)
                        WHERE Institute.Name LIKE :input
                           OR Institute.Strasse LIKE :input
                           OR Institute.email LIKE :input
                           OR range_tree.name LIKE :input
                        ORDER BY Institute.Name";
            } else {
                $quoted_user_id = DBManager::get()->quote($GLOBALS['user']->id);
                $sql = "SELECT DISTINCT Institute.Institut_id, Institute.Name
                        FROM Institute
                        LEFT JOIN range_tree ON (range_tree.item_id = Institute.Institut_id)
                        LEFT JOIN user_inst ON (user_inst.Institut_id = Institute.Institut_id)
                        WHERE user_inst.user_id = {$quoted_user_id}
                          AND (
                              Institute.Name LIKE :input
                              OR Institute.Strasse LIKE :input
                              OR Institute.email LIKE :input
                              OR range_tree.name LIKE :input
                          )
                        ORDER BY Institute.Name";
            }
    
            $this->instsearch = SQLSearch::get($sql, _('Einrichtung suchen'), 'Institut_id');
            $this->plugin = Request::get('from_plugin');
        }
    
        public function choose_folder_action($folder_id = null)
        {
            PageLayout::setTitle(_('Zielordner wählen'));
    
            if (Request::isPost()) {
                //copy
                if (Request::get('to_plugin')) {
                    $plugin = PluginManager::getInstance()->getPlugin(Request::get('to_plugin'));
                    //$file = $plugin->getPreparedFile(Request::get("file_id"));
                } else {
                    $folder = new Folder($folder_id);
                    $this->to_folder_type = new StandardFolder($folder);
                }
            }
            $this->filesystemplugin = null;
            if (Request::get('to_plugin')) {
                $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/choose_folder") + strlen("dispatch.php/file/choose_folder"));
                if (strpos($folder_id, "?") !== false) {
                    $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                }
                if ($folder_id[0] === "/") {
                    $folder_id = substr($folder_id, 1);
                }
    
                $this->filesystemplugin = PluginManager::getInstance()->getPlugin(Request::get('to_plugin'));
                if (Request::get('search') && $this->filesystemplugin->hasSearch()) {
                    $this->top_folder = $this->filesystemplugin->search(
                        Request::get('search'),
                        Request::getArray('parameter')
                    );
                } else {
                    $this->top_folder = $this->filesystemplugin->getFolder($folder_id, true);
                    if (is_a($this->top_folder, 'Flexi_Template')) {
                        $this->top_folder->select    = true;
                        $this->top_folder->to_folder = $this->to_folder;
                        $this->render_text($this->top_folder);
                    }
                }
            } else {
                $this->top_folder = new StandardFolder(new Folder($folder_id));
                if (!$this->top_folder->isReadable($GLOBALS['user']->id)) {
                    throw new AccessDeniedException();
                }
            }
    
            $this->top_folder_name = _('Hauptordner');
    
            //A top folder can have its parent-ID set to an emtpy string
            //or its folder_type is set to 'RootFolder'.
            if ($this->top_folder->parent_id == ''
                or $this->top_folder->folder_type == 'RootFolder') {
                //We have a top folder. Now we check if its range-ID
                //references a Stud.IP object and set the displayed folder name
                //to the name of that object.
                if ($this->top_folder->range_id) {
                    $range_type = Folder::findRangeTypeById($this->top_folder->range_id);
    
                    switch ($range_type) {
                        case 'course':
                            $course = Course::find($this->top_folder->range_id);
                            if ($course) {
                                $this->top_folder_name = $course->getFullName();
                            }
                            break;
                        case 'institute':
                            $institute = Institute::find($this->top_folder->range_id);
                            if ($institute) {
                                $this->top_folder_name = $institute->getFullName();
                            }
                            break;
                        case 'user':
                            $user = User::find($this->top_folder->range_id);
                            if ($user) {
                                $this->top_folder_name = $user->getFullName();
                            }
                            break;
                        case 'message':
                            $message = Message::find($this->top_folder->range_id);
                            if ($message) {
                                $this->top_folder_name = $message->subject;
                            }
                            break;
                        case 'resource': {
                            $resource = Resource::find($this->top_folder->range_id);
                            if ($resource) {
                                $resource = $resource->getDerivedClassInstance();
                                if ($resource) {
                                    $this->top_folder_name = $resource->getFullName();
                                }
                            }
                        }
                    }
    
                }
            }else {
                //$top_folder is not a top folder. We can use its name directly.
                $this->top_folder_name = $this->top_folder->name;
            }
        }
    
    
        public function add_from_library_action($folder_id = null)
        {
            PageLayout::setTitle(_('Suche im Bibliothekskatalog'));
            if (!Config::get()->LITERATURE_ENABLE) {
                throw new AccessDeniedException(_('Die Literaturverwaltung ist ausgeschaltet!'));
            }
    
            $this->top_folder = new StandardFolder(new Folder($folder_id));
            if (!$this->top_folder->isReadable($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            $course = $this->top_folder->getRangeObject();
            if (!($course instanceof Course) || !$GLOBALS['perm']->have_studip_perm('tutor', $course->id)) {
                throw new AccessDeniedException();
            }
    
            if (!LibrarySearchManager::catalogsConfigured()) {
                PageLayout::postError(
                    _('In dieser Stud.IP-Installation sind keine Bibliothekskataloge aktiviert!')
                );
                return;
            }
    
            $this->folder_id = $folder_id;
    
            $plugin_manager = PluginManager::getInstance();
            $this->page_size = 30;
            $this->limit = 100; //the limit for items from each catalog
            $this->next_page = 0;
            $this->page = 0;
            $this->order_by = LibrarySearch::ORDER_BY_RELEVANCE;
            $this->global_stylesheet = $GLOBALS['LIBRARY_STYLESHEET_ID'];
    
            if (Request::isPost()) {
                CSRFProtection::verifyUnsafeRequest();
    
                if (Request::submitted('search')) {
                    $this->title = Request::get('title');
                    $this->author = Request::get('author');
                    $this->year = Request::get('year');
                    $this->number = Request::get('number');
                    $this->publication = Request::get('publication');
                    $this->signature = Request::get('signature');
                    $this->order_by = Request::get('order_by');
    
                    if (!$this->title && !$this->author && !$this->year &&
                        !$this->number && !$this->publication && !$this->signature) {
                        PageLayout::postError(
                            _('Es muss mindestens ein Suchkriterium angegeben werden!')
                        );
                        return;
                    }
    
                    $this->library_plugins = $plugin_manager->getPlugins('LibraryPlugin');
    
                    //Build the query parameter array:
                    $search_parameters = [];
                    if ($this->title) {
                        $search_parameters[LibrarySearch::TITLE] = $this->title;
                    }
                    if ($this->author) {
                        $search_parameters[LibrarySearch::AUTHOR] = $this->author;
                    }
                    if ($this->year) {
                        $search_parameters[LibrarySearch::YEAR] = $this->year;
                    }
                    if ($this->number) {
                        $search_parameters[LibrarySearch::NUMBER] = $this->number;
                    }
                    if ($this->publication) {
                        $search_parameters[LibrarySearch::PUBLICATION] = $this->publication;
                    }
                    if ($this->signature) {
                        $search_parameters[LibrarySearch::SIGNATURE] = $this->signature;
                    }
    
                    $this->search_id = md5(json_encode($search_parameters));
    
                    $cache = StudipCacheFactory::getCache();
    
                    $merged_results = LibrarySearchManager::search(
                        $search_parameters,
                        $this->order_by,
                        $this->limit
                    );
                    $this->total_results = count($merged_results);
                    $cache_data = [
                        'search_params' => $search_parameters,
                        'results' => $merged_results
                    ];
                    $cache->write($this->search_id, $cache_data);
                    if (count($merged_results) > $this->page_size) {
                        $this->next_page = 2;
                    }
                    $this->result_set = array_slice($merged_results, 0, $this->page_size);
                    $this->pagination_link_closure = function($page_id) {
                        return URLHelper::getLink(
                            'dispatch.php/file/add_from_library/' . $this->top_folder->getId(),
                            [
                                'search_id' => $this->search_id,
                                'page' => $page_id,
                            ]
                        );
                    };
                    return;
                } elseif (Request::submitted('add_to_file_area')) {
                    $search_id = Request::get('search_id');
                    $result_id = Request::get('result_id');
                    $this->redirect(
                        $this->url_for(
                            'file/create_library_file/' . $this->top_folder->getId(),
                            [
                                'search_and_item_id' => $search_id . '_' . $result_id,
                                'create_only' => '1'
                            ]
                        )
                    );
                } elseif (Request::submitted('create_library_request')) {
                    $search_id = Request::get('search_id');
                    $result_id = Request::get('result_id');
                    $plugin_id = Request::get('plugin_id');
                    $this->redirect(
                        $this->url_for(
                            'file/create_library_file/' . $this->top_folder->getId(),
                            [
                                'search_and_item_id' => $search_id . '_' . $result_id,
                                'plugin_id' => $plugin_id
                            ]
                        )
                    );
                }
            } elseif (Request::get('search_id')) {
                $this->library_plugins = $plugin_manager->getPlugins('LibraryPlugin');
    
                $this->search_id = Request::get('search_id');
                $this->page = Request::get('page');
    
                $cache = StudipCacheFactory::getCache();
                $cache_data = $cache->read($this->search_id);
                $results = $cache_data['results'];
                $this->total_results = count($results);
                $search_parameters = $cache_data['search_params'];
                $this->title = $search_parameters[LibrarySearch::TITLE];
                $this->author = $search_parameters[LibrarySearch::AUTHOR];
                $this->year = $search_parameters[LibrarySearch::YEAR];
                $this->number = $search_parameters[LibrarySearch::NUMBER];
                $this->publication = $search_parameters[LibrarySearch::PUBLICATION];
                $this->signature = $search_parameters[LibrarySearch::SIGNATURE];
                $offset = $this->page_size * $this->page;
                $this->result_set = array_slice($results, $offset, $this->page_size);
                $this->pagination_link_closure = function($page_id) {
                    return URLHelper::getLink(
                        'dispatch.php/file/add_from_library/' . $this->top_folder->getId(),
                        [
                            'search_id' => $this->search_id,
                            'page' => $page_id,
                        ]
                    );
                };
            }
        }
    
    
        public function create_library_file_action($folder_id = null)
        {
            PageLayout::setTitle(_('Bibliothekseintrag erstellen'));
            if (!Config::get()->LITERATURE_ENABLE) {
                throw new AccessDeniedException(_('Die Literaturverwaltung ist ausgeschaltet!'));
            }
    
            $this->top_folder = new StandardFolder(new Folder($folder_id));
            if (!$this->top_folder->isReadable($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            $course = $this->top_folder->getRangeObject();
            if (!($course instanceof Course) || !$GLOBALS['perm']->have_studip_perm('tutor', $course->id)) {
                throw new AccessDeniedException();
            }
            $create_only = Request::submitted('create_only');
            $plugin_id = Request::get('plugin_id');
            $search_and_item_id = Request::get('search_and_item_id');
            if (!$search_and_item_id) {
                PageLayout::postError(_('Es wurde kein Suchergebnis ausgewählt!'));
                return;
            }
            if (!$plugin_id && !$create_only) {
                throw new Exception('No plugin ID has been provided!');
            }
            $search_and_item_id = explode('_', $search_and_item_id);
            $search_id = $search_and_item_id[0];
            $item_id = $search_and_item_id[1];
            if (!$search_id) {
                throw new Exception('No search_id provided!');
            }
    
            if ($item_id) {
                $cache = StudipCacheFactory::getCache();
                $documents = $cache->read($search_id);
                $document = $documents['results'][$item_id];
                if (!($document instanceof LibraryDocument)) {
                    throw new Exception('Library file not found in result cache!');
                }
                $file = LibraryFile::createFromLibraryDocument($document, $folder_id);
            } else {
                $cache = StudipCacheFactory::getCache();
                $search = $cache->read($search_id);
                if (!$search) {
                    throw new Exception('Search not found in cache!');
                }
                $search_params = $search['search_params'];
                $document = new LibraryDocument();
                $document->search_params = $search_params;
                $file = LibraryFile::createFromLibraryDocument($document, $folder_id);
            }
    
            if ($create_only) {
                $this->redirect($this->url_for('file/edit_license/' . $this->top_folder->getId(), [
                    'file_refs' => [$file->getFileRef()->getId()],
                    're_location' => $this->url_for($this->top_folder->range_type . '/files/index/' . $this->top_folder->getId(), ['cid' => $this->top_folder->range_id])
                ]));
                return;
            }
    
            if ($plugin_id) {
                $plugin_manager = PluginManager::getInstance();
                $plugin = $plugin_manager->getPluginById($plugin_id);
                if (!($plugin instanceof LibraryPlugin)) {
                    throw new Exception(sprintf('The plugin with the ID %s is not a LibraryPlugin!', $plugin_id));
                }
    
                if ($file instanceof LibraryFile) {
                    //Redirect to the request page of the plugin.
                    $this->redirect($plugin->getRequestURL($file->getId()));
                } else {
                    throw new Exception('Library file could not be stored!');
                }
            }
        }
    
    
        public function getFolders_action()
        {
            $rangeId   = Request::get('range');
            $folders   = Folder::findBySQL('range_id = ?', [$rangeId]);
            $folderray = [];
            $pathes    = [];
            foreach ($folders as $folder) {
                $pathes[] = $folder->getPath();
                $folderray[][$folder->getPath()] = $folder->id;
            }
            array_multisort($pathes, SORT_ASC, SORT_STRING, $folderray);
    
            if (Request::isXhr()) {
                $this->render_json($folderray);
            } else {
                $this->render_nothing();
            }
        }
    
    
        /**
         * The action for deleting a file reference.
         */
        public function delete_action($file_ref_id)
        {
            CSRFProtection::verifyUnsafeRequest();
    
            if (Request::get("from_plugin")) {
                $file_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/delete/") + strlen("dispatch.php/file/delete/"));
                if (strpos($file_id, "?") !== false) {
                    $file_id = substr($file_id, 0, strpos($file_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $filetype = $plugin->getPreparedFile($file_id);
                $folder = $filetype->getFolderType();
            } else {
                $file_ref = FileRef::find($file_ref_id);
                $folder = $file_ref->foldertype;
                $filetype = $file_ref->getFileType();
            }
            if (!$filetype) {
                throw new Trails_Exception(404, _('Datei nicht gefunden.'));
            }
    
            if (!$filetype->isWritable($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            if ($filetype->delete()) {
                PageLayout::postSuccess(_('Datei wurde gelöscht.'));
            } else {
                PageLayout::postError(_('Datei konnte nicht gelöscht werden.'));
            }
            if (Request::submitted('from_flat_view')) {
                $this->redirectToFlatView($folder);
            } else {
                $this->redirectToFolder($folder);
            }
        }
    
        public function add_files_window_action($folder_id)
        {
            $this->folder_id   = $folder_id;
    
            $this->range = Context::getType();
            $this->upload_type = FileManager::getUploadTypeConfig(
                Context::getId(), $GLOBALS['user']->id
            );
            $config = Config::get();
            $this->show_library_functions = $config->LITERATURE_ENABLE;
            if ($this->show_library_functions) {
                $this->library_search_description = $config->LIBRARY_ADD_ITEM_ACTION_DESCRIPTION;
            }
    
            $this->plugin = Request::get('to_plugin');
        }
    
        public function choose_file_from_course_action($folder_id)
        {
            if (Request::get('course_id')) {
                $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/choose_file_from_course/") + strlen("dispatch.php/file/choose_file_from_course/"));
                if (strpos($folder_id, "?") !== false) {
                    $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                }
                $folder = Folder::findTopFolder(Request::get('course_id'));
                $this->redirect($this->url_for(
                    'file/choose_file/' . $folder->getId(), [
                        'to_plugin'    => Request::get('to_plugin'),
                        'to_folder_id' => $folder_id
                    ]
                ));
                return;
            }
    
            $this->folder_id = $folder_id;
            $this->plugin = Request::get('to_plugin');
            if (!$GLOBALS['perm']->have_perm('admin')) {
                $query = "SELECT seminare.*, MAX(semester_data.`beginn`) as sorter
                          FROM seminare
                          INNER JOIN seminar_user ON (seminar_user.Seminar_id = seminare.Seminar_id)
                          LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id)
                          LEFT JOIN semester_data ON (semester_courses.semester_id = semester_data.semester_id)
                          WHERE seminar_user.user_id = :user_id
                          GROUP BY seminare.Seminar_id";
                if (Config::get()->DEPUTIES_ENABLE) {
                    $query .= " UNION
                        SELECT `seminare`.*, MAX(semester_data.`beginn`) as sorter
                        FROM `seminare`
                        INNER JOIN `deputies` ON (`deputies`.`range_id` = `seminare`.`Seminar_id`)
                        LEFT JOIN semester_courses ON (semester_courses.course_id = seminare.Seminar_id)
                        LEFT JOIN semester_data ON (semester_courses.semester_id = semester_data.semester_id)
                        WHERE `deputies`.`user_id` = :user_id
                        GROUP BY seminare.Seminar_id";
                }
                $query .= " ORDER BY sorter DESC, Name ASC";
                $statement = DBManager::get()->prepare($query);
                $statement->execute(['user_id' => $GLOBALS['user']->id]);
    
                $this->courses = [];
                foreach ($statement->fetchAll(PDO::FETCH_ASSOC) as $coursedata) {
                    $this->courses[] = Course::buildExisting($coursedata);
                }
            }
        }
    
        public function choose_file_action($folder_id = null)
        {
            $this->filesystemplugin = null;
            if (Request::get('to_plugin')) {
                $to_plugin = PluginManager::getInstance()->getPlugin(Request::get('to_plugin'));
                $this->to_folder_type = $to_plugin->getFolder(Request::get('to_folder_id', ''));
            } else {
                if (!Request::get('to_folder_id')) {
                    throw new Exception('target folder_id must be set.');
                }
                $folder = new Folder(Request::option('to_folder_id', ''));
                $this->to_folder_type = $folder->getTypedFolder();
            }
    
            if (Request::isPost()) {
                //copy
                if (Request::get('from_plugin')) {
                    $plugin = PluginManager::getInstance()->getPlugin(Request::get('from_plugin'));
                    $file = $plugin->getPreparedFile(Request::get('file_id'), true);
                } else {
                    $from_file_ref = FileRef::find(Request::get('file_id'));
                    $file = $from_file_ref->getFileType();
                }
    
                $newfile = FileManager::copyFile(
                    $file,
                    $this->to_folder_type,
                    User::findCurrent()
                );
    
                if (is_array($newfile)) {
                    PageLayout::postError(
                        _('Beim Kopieren ist ein Fehler aufgetreten'),
                        array_map('htmlReady', $newfile)
                    );
                    $this->redirectToFolder($this->to_folder_type);
                    return;
                }
    
                if (Request::isXhr()) {
                    $this->current_folder = $this->to_folder_type;
                    $this->marked_element_ids = [];
    
                    $plugins = PluginManager::getInstance()->getPlugins('FileUploadHook');
    
                    $redirects = [];
                    foreach ($plugins as $plugin) {
                        $url = $plugin->getAdditionalUploadWizardPage($newfile);
                        if ($url) {
                            $redirects[] = $url;
                        }
                    }
                    $payload = [
                        'html'     => FilesystemVueDataManager::getFileVueData($newfile, $this->current_folder),
                        'redirect' => $redirects[0],
                        'url'      => $this->generateFilesUrl($this->current_folder, $newfile),
                    ];
    
                    $this->response->add_header(
                        'X-Dialog-Execute',
                        'STUDIP.Files.addFile'
                    );
                    $this->render_json($payload);
                    return;
                } else {
                    PageLayout::postSuccess(_('Datei wurde hinzugefügt.'));
                    $this->redirectToFolder($this->to_folder_type);
                    return;
                }
            }
    
            if (Request::get('from_plugin')) {
                $this->filesystemplugin = PluginManager::getInstance()->getPlugin(Request::get('from_plugin'));
                PageLayout::setTitle(sprintf(
                    _('Dokument hinzufügen von %s'),
                    $this->filesystemplugin->getPluginName()
                ));
    
                if (Request::get('search') && $this->filesystemplugin->hasSearch()) {
                    $this->top_folder = $this->filesystemplugin->search(Request::get('search'), Request::getArray('parameter'));
                } else {
                    $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/choose_file/") + strlen("dispatch.php/file/choose_file/"));
                    if (strpos($folder_id, "?") !== false) {
                        $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                    }
                    $this->top_folder = $this->filesystemplugin->getFolder($folder_id, true);
                    if (is_a($this->top_folder, 'Flexi_Template')) {
                        $this->top_folder->select    = true;
                        $this->top_folder->to_folder = $this->to_folder;
                        $this->render_text($this->top_folder->render());
                    }
                }
            } else {
                //Load the folder by its ID.
                $folder = new Folder($folder_id);
                $folder_type = $folder->folder_type;
                //Check if the specified folder type is a FolderType implementation.
                if (is_a($folder_type, 'FolderType', true)) {
                    //Get an instance of the FolderType implementation
                    //and use it in the code below this point.
                    $this->top_folder = new $folder_type($folder);
                    if (!$this->top_folder->isReadable($GLOBALS['user']->id)) {
                        throw new AccessDeniedException();
                    }
                }
            }
    
            $this->to_folder_name = _('Hauptordner');
    
            //A top folder can have its parent-ID set to an empty string
            //or its folder_type set to 'RootFolder'.
            if ($this->to_folder_type->parent_id == ''
                or $this->to_folder_type->folder_type == 'RootFolder') {
                //We have a top folder. Now we check if its range-ID
                //references a Stud.IP object and set the displayed folder name
                //to the name of that object.
                if ($this->to_folder_type->range_id) {
                    $range_type = Folder::findRangeTypeById($this->to_folder_type->range_id);
    
                    switch ($range_type) {
                        case 'course': {
                            $course = Course::find($this->to_folder_type->range_id);
                            if ($course) {
                                $this->to_folder_name = $course->getFullName();
                            }
                            break;
                        }
                        case 'institute': {
                            $institute = Institute::find($this->to_folder_type->range_id);
                            if ($institute) {
                                $this->to_folder_name = $institute->getFullName();
                            }
                            break;
                        }
                        case 'user': {
                            $user = User::find($this->to_folder_type->range_id);
                            if ($user) {
                                $this->to_folder_name = $user->getFullName();
                            }
                            break;
                        }
                        case 'message': {
                            $message = Message::find($this->to_folder_type->range_id);
                            if ($message) {
                                $this->to_folder_name = $message->subject;
                            }
                            break;
                        }
                    }
                }
            } else {
                //The folder is not a top folder. We can use its name directly.
                $this->to_folder_name = $this->to_folder_type->name;
            }
        }
    
    
        protected function loadFiles($param = 'files', $plugin = null, $with_blob = false)
        {
            $result = [];
            $file_ids = Request::getArray($param);
            if (!$file_ids) {
                //In case the file ref IDs are not set in the request
                //they may still be set in the flash object of the controller:
                $file_ids = $this->flash->get($param);
            }
            if ($plugin instanceof FilesystemPlugin) {
                foreach ($file_ids as $file_id) {
                    $file = $plugin->getPreparedFile($file_id);
                    if ($file instanceof FileType) {
                        $result[] = $file;
                    }
                }
            } else {
                //Stud.IP core file system:
                $file_refs = FileRef::findMany($file_ids);
                foreach ($file_refs as $file_ref) {
                    $file = $file_ref->getFileType();
                    if ($file instanceof FileType) {
                        $result[] = $file;
                    }
                }
            }
            return $result;
        }
    
        public function edit_license_action($folder_id = null)
        {
            $this->re_location = Request::get('re_location');
            $this->files = [];
            $this->file = null;
            $this->file_ref = null;
            $this->plugin = null;
            if (Request::submitted('to_plugin')) {
                $this->plugin = PluginManager::getInstance()->getPlugin(Request::get('to_plugin'));
            }
            $this->files = $this->loadFiles('file_refs', $this->plugin);
            $this->folder = $this->files[0]->getFolderType();
            $this->show_description_field = Config::get()->ENABLE_DESCRIPTION_ENTRY_ON_UPLOAD;
            if ($folder_id == 'bulk') {
                $this->show_description_field = false;
            }
    
            if (Request::isPost()) {
                CSRFProtection::verifyUnsafeRequest();
    
                if (count($this->files) === 1) {
                    // store flag if file is an accessible file
                    $this->store_accessibility_flag($this->files[0]);
                }
    
                if (($folder_id == 'bulk') && !Request::submitted('accept')) {
                    $this->files = $this->loadFiles('ids', $this->plugin);
                } else {
                    $description = Request::get('description');
                    $success_files = [];
                    $error_files = [];
                    foreach ($this->files as $file) {
                        //Check if the user may change the license of the file:
                        $folder = $file->getFolderType();
                        if (!$folder) {
                            //We have no way of determining whether the user may change
                            //the license.
                            $error_files[] = sprintf(_('Die Datei "%s" ist ungültig!'), $file['name']);
                            continue;
                        }
                        if ($file instanceof StandardFile) {
                            //Due to missing methods in the FileType interface,
                            //terms of use and the description can only be set
                            //for StandardFile instances.
                            $file_ref = $file->getFileRef();
                            $file_ref->content_terms_of_use_id = Request::option('content_terms_of_use_id');
                            if ($this->show_description_field && $description) {
                                $file_ref->description = $description;
                            }
                            if ($file_ref->store()) {
                                $success_files[] = $file->getFilename();
                            } else {
                                $error_files[] = sprintf(_('Fehler beim Speichern der Datei "%s"!'), $file['name']);
                            }
                        }
    
                        $this->file = $file;
                        if ($file instanceof StandardFile) {
                            $this->file_ref = $file->getFileRef();
                        }
                        $this->current_folder = $folder;
                        $this->marked_element_ids = [];
                        $payload['html'][] = FilesystemVueDataManager::getFileVueData($this->file, $this->current_folder);
                    }
                    if (Request::isXhr() && !$this->re_location) {
                        $payload = ['html' => []];
                        foreach ($this->files as $file) {
                            $folder = $file->getFolderType();
    
                            // Skip files not in current folder (during archive extract)
                            if ($folder_id && $folder_id !== $folder->getId()) {
                                continue;
                            }
    
                            $payload['html'][] = FilesystemVueDataManager::getFileVueData(
                                $file,
                                $file->getFolderType()
                            );
                        }
    
                        $plugins = PluginManager::getInstance()->getPlugins('FileUploadHook');
                        $redirect = null;
                        foreach ($plugins as $upload_hook_plugin) {
                            $url = $upload_hook_plugin->getAdditionalUploadWizardPage($file_ref);
                            if ($url) {
                                $redirect = $url;
                                break;
                            }
                        }
    
                        if (count($this->files) === 1) {
                            if (Config::get()->OERCAMPUS_ENABLED
                                && Config::get()->OER_ENABLE_POST_UPLOAD
                                && $GLOBALS['perm']->have_perm('tutor')
                            ) {
                                if ($this->file instanceof StandardFile) {
                                    $file_ref = $this->file->getFileRef();
                                    if ($file_ref['content_terms_of_use_id'] === 'SELFMADE_NONPUB'
                                        || $file_ref['content_terms_of_use_id'] === 'FREE_LICENSE'
                                    ) {
                                        $this->redirect('file/oer_post_upload/' . $file_ref['id']);
                                        return;
                                    }
                                }
                            }
                        }
    
                        if ($redirect) {
                            $this->redirect($redirect);
                            return;
                        }
    
                        $payload['url'] = $this->generateFilesUrl(
                            $this->folder,
                            $this->file
                        );
    
                        if ($folder_id == 'bulk' && $this->files) {
                            if ($success_files) {
                                if (count($success_files) == 1) {
                                    PageLayout::postSuccess(sprintf(
                                        _('Die Lizenz der Datei "%s" wurde geändert.'),
                                        htmlReady($this->files[0]->getName())
                                    ));
                                } else {
                                    sort($success_files);
                                    PageLayout::postSuccess(
                                        _('Die Lizenzen der folgenden Dateien wurden geändert:'),
                                        array_map('htmlReady', $success_files)
                                    );
                                }
                            }
                            if ($error_files) {
                                if (count($error_files) == 1) {
                                    PageLayout::postError(sprintf(
                                        _('Die Lizenz der Datei "%s" konnte nicht geändert werden!'),
                                        htmlReady($this->files[0]->getName())
                                    ));
                                } else {
                                    PageLayout::postError(
                                        _('Die Lizenzen der folgenden Dateien konnten nicht geändert werden:'),
                                        array_map('htmlReady', $error_files)
                                    );
                                }
                            }
                        }
    
                        $this->response->add_header(
                            'X-Dialog-Execute',
                            'STUDIP.Files.addFile'
                        );
                        $this->render_json($payload);
                        return;
                    } else {
                        PageLayout::postSuccess(_('Datei wurde bearbeitet.'));
                        if ($this->re_location) {
                            return $this->relocate(URLHelper::getURL($this->re_location));;
                        } else {
                            return $this->redirectToFolder($this->folder);
                        }
                    }
                }
            }
    
            PageLayout::setTitle(sprintf(
                ngettext(
                    'Zusatzangaben und Lizenz wählen',
                    'Zusatzangaben und Lizenz auswählen: %s Dateien',
                    count($this->files)
                ),
                count($this->files)
            ));
    
            $this->licenses = ContentTermsOfUse::findBySQL("1 ORDER BY position ASC, id ASC");
        }
    
        public function add_url_action($folder_id)
        {
            $this->content_terms_of_use_entries = ContentTermsOfUse::findAll();
            $this->content_terms_of_use_id = Request::get('content_terms_of_use_id');
            if (Request::get("to_plugin")) {
                $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/add_url/") + strlen("dispatch.php/file/add_url/"));
                if (strpos($folder_id, "?") !== false) {
                    $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("to_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $this->top_folder = $plugin->getFolder($folder_id);
            } else {
                $this->top_folder = FileManager::getTypedFolder($folder_id);
            }
            URLHelper::addLinkParam('to_plugin', Request::get('to_plugin'));
            if (!$this->top_folder || !$this->top_folder->isWritable($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            if (Request::submitted('store')) {
                CSRFProtection::verifyUnsafeRequest();
                $url = trim(Request::get('url'));
                $url_parts = parse_url($url);
                if (filter_var($url, FILTER_VALIDATE_URL) !== false && in_array($url_parts['scheme'], ['http', 'https','ftp'])) {
                    $this->file = $this->top_folder->addFile(URLFile::create([
                        'name' => Request::get('name'),
                        'url' => $url,
                        'access_type' => Request::get('access_type', "redirect"),
                        'content_terms_of_use_id' => Request::get('content_terms_of_use_id')
                    ]));
    
                    if ($this->file) {
                        $payload = [];
    
                        $payload['html'][] = FilesystemVueDataManager::getFileVueData($this->file, $this->top_folder);
    
                        $plugins = PluginManager::getInstance()->getPlugins('FileUploadHook');
    
                        $redirects = [];
                        foreach ($plugins as $plugin) {
                            $url = $plugin->getAdditionalUploadWizardPage($this->file);
                            if ($url) {
                                $redirects[] = $url;
                            }
                        }
                        if (count($redirects) > 0) {
                            $payload['html'] = $redirects[0];
                        }
    
                        $this->response->add_header(
                            'X-Dialog-Execute',
                            'STUDIP.Files.addFile'
                        );
                        $this->render_json($payload);
                    }
                } else {
                    PageLayout::postError(_('Die angegebene URL ist ungültig.'));
                }
            }
        }
    
        /**
         * Action for creating a new folder.
         */
        public function new_folder_action($folder_id)
        {
            if (Request::get("from_plugin")) {
                $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/new_folder/") + strlen("dispatch.php/file/new_folder/"));
                if (strpos($folder_id, "?") !== false) {
                    $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $parent_folder = $plugin->getFolder($folder_id);
            } else {
                $parent_folder = FileManager::getTypedFolder($folder_id);
            }
    
            URLHelper::addLinkParam('from_plugin', Request::get('from_plugin'));
            if (!$parent_folder || !$parent_folder->isSubfolderAllowed($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            $this->parent_folder_id = $parent_folder->getId();
    
            $folder_types = FileManager::getAvailableFolderTypes($parent_folder->range_id, $GLOBALS['user']->id);
    
            $this->name = Request::get('name');
            $this->description = Request::get('description');
            $this->folder_types = [];
            $this->show_confirmation_button = false;
    
            foreach ($folder_types as $folder_type) {
                $folder_type_instance = new $folder_type(
                    ['range_id' => $parent_folder->range_id,
                     'range_type' => $parent_folder->range_type,
                     'parent_id' => $parent_folder->getId()]
                );
                $this->folder_types[] = [
                    'class'    => $folder_type,
                    'instance' => $folder_type_instance,
                    'name'     => $folder_type::getTypeName(),
                    'icon'     => $folder_type_instance->getIcon('clickable')
                ];
            }
    
            $new_folder = null;
            if (Request::submitted('create') || Request::submitted('force_creation')) {
                CSRFProtection::verifyUnsafeRequest();
    
                $force_creation = Request::submitted('force_creation');
    
                // Get class name of folder type and check if the class
                // is a subclass of FolderType before initialising it:
                $folder_type = Request::get('folder_type', 'StandardFolder');
                if (!is_subclass_of($folder_type, 'FolderType')) {
                    throw new Exception(
                        _('Der gewünschte Ordnertyp ist ungültig!')
                    );
                }
                $request = Request::getInstance();
                $request->offsetSet('parent_id', $folder_id);
                $new_folder = new $folder_type(
                    ['range_id' => $parent_folder->range_id,
                     'range_type' => $parent_folder->range_type,
                     'parent_id' => $parent_folder->getId()]
                );
                $result = $new_folder->setDataFromEditTemplate($request);
    
                if ($result instanceof FolderType) {
                    $new_folder->user_id = User::findCurrent()->id;
                    if ($result instanceof CourseDateFolder && !$force_creation) {
                        // Check if there is already a folder for the
                        // selected course date:
                        $course_date = $result->getDate();
                        if ($course_date instanceof CourseDate
                            && count($course_date->folders) > 0
                        ) {
                            PageLayout::postWarning(sprintf(
                                _('Für den Termin am %s existiert bereits ein Sitzungs-Ordner. Möchten Sie trotzdem einen weiteren Sitzungs-Ordner erstellen?'),
                                htmlReady($course_date->getFullname())
                            ));
                            $this->show_confirmation_button = true;
                            $this->folder = $new_folder ?: new StandardFolder();
                            return;
                        }
                    }
                    if ($parent_folder->createSubfolder($new_folder)) {
                        PageLayout::postSuccess(_('Der Ordner wurde angelegt.'));
                        $this->response->add_header('X-Dialog-Close', '1');
                        $this->render_nothing();
                    } else {
                        PageLayout::postError(
                            _('Fehler beim Anlegen des Ordners!')
                        );
                    }
                } else {
                    PageLayout::postMessage($result);
                }
            }
            $this->folder = $new_folder ?: new StandardFolder();
        }
    
        /**
         * Action for editing an existing folder, referenced by its ID.
         *
         * @param $folder_id string The ID of the folder that shall be edited.
         */
        public function edit_folder_action($folder_id)
        {
            if (Request::get("from_plugin")) {
                $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/edit_folder/") + strlen("dispatch.php/file/edit_folder/"));
                if (strpos($folder_id, "?") !== false) {
                    $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $folder = $plugin->getFolder($folder_id);
            } else {
                $folder = FileManager::getTypedFolder($folder_id);
            }
            URLHelper::addLinkParam('from_plugin', Request::get('from_plugin'));
            if (!$folder || !$folder->isEditable($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
            $parent_folder = $folder->getParent();
            $folder_types = FileManager::getAvailableFolderTypes(
                $parent_folder ? $parent_folder->range_id : null,
                $GLOBALS['user']->id
            );
            $this->name = Request::get('name', $folder->name);
            $this->description = Request::get('description', $folder->description);
    
            $this->folder = $folder;
            $this->folder_template = $folder->getEditTemplate();
    
            $this->folder_types = [];
    
            if (!is_a($folder, 'VirtualFolderType') && $parent_folder) {
                foreach ($folder_types as $folder_type) {
                    $folder_type_instance = new $folder_type(
                        [
                            'range_id' => $parent_folder->range_id,
                            'range_type' => $parent_folder->range_type,
                            'parent_id' => $parent_folder->getId()
                        ]
                    );
                    $this->folder_types[] = [
                        'class' => $folder_type,
                        'instance' => $folder_type_instance,
                        'name' => $folder_type::getTypeName(),
                        'icon' => $folder_type_instance->getIcon('clickable')
                    ];
                }
            } elseif (!$parent_folder) {
                $this->folder_types[] = [
                    'class' => get_class($folder),
                    'instance' => $folder,
                    'name' => $folder::getTypeName(),
                    'icon' => $folder->getIcon('clickable')
                ];
            }
    
            if (Request::submitted('edit')) {
                CSRFProtection::verifyUnsafeRequest();
                if (!is_a($folder, 'VirtualFolderType')) {
                    $folder_type = Request::get('folder_type', get_class($folder));
                    if (!is_subclass_of($folder_type, 'FolderType') || !class_exists($folder_type)) {
                        throw new InvalidArgumentException(_('Unbekannter Ordnertyp!'));
                    }
                    if ($folder_type !== get_class($folder)) {
                        $folder = new $folder_type($folder);
                    }
                }
                $request = Request::getInstance();
                if ($folder->getParent()) {
                    $request->offsetSet('parent_id', $folder->getParent()->getId());
                }
                $result = $folder->setDataFromEditTemplate($request);
                if ($result instanceof FolderType) {
                    if ($folder->store()) {
                        PageLayout::postSuccess(_('Der Ordner wurde bearbeitet.'));
                    }
                    $this->response->add_header('X-Dialog-Close', '1');
                    $this->render_nothing();
                } else {
                    PageLayout::postMessage($result);
                }
            }
            list($this->folder_size, $this->folder_file_amount) = $this->getFolderSize($folder);
        }
    
        public function delete_folder_action($folder_id)
        {
            CSRFProtection::verifyUnsafeRequest();
    
            if (Request::get("from_plugin")) {
                $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/delete_folder/") + strlen("dispatch.php/file/delete_folder/"));
                if (strpos($folder_id, "?") !== false) {
                    $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $folder = $plugin->getFolder($folder_id);
            } else {
                $folder = FileManager::getTypedFolder($folder_id);
            }
            URLHelper::addLinkParam('from_plugin', Request::get('from_plugin'));
            if (!$folder || !$folder->isEditable($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            $parent_folder = $folder->getParent();
    
            if ($folder->delete()) {
                PageLayout::postSuccess(_('Ordner wurde gelöscht!'));
            } else {
                PageLayout::postError(_('Ordner konnte nicht gelöscht werden!'));
            }
            $this->redirectToFolder($parent_folder);
        }
    
        /**
         * This action allows downloading, copying, moving and deleting files and folders in bulk.
         */
        public function bulk_action($folder_id)
        {
            CSRFProtection::verifyUnsafeRequest();
    
            if (Request::get("from_plugin")) {
                $folder_id = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "dispatch.php/file/bulk/") + strlen("dispatch.php/file/bulk/"));
                if (strpos($folder_id, "?") !== false) {
                    $folder_id = substr($folder_id, 0, strpos($folder_id, "?"));
                }
                $plugin = PluginManager::getInstance()->getPlugin(Request::get("from_plugin"));
                if (!$plugin) {
                    throw new Trails_Exception(404, _('Plugin existiert nicht.'));
                }
                $parent_folder = $plugin->getFolder($folder_id);
            } else {
                $parent_folder = FileManager::getTypedFolder($folder_id);
            }
    
            URLHelper::addLinkParam('from_plugin', Request::get('from_plugin'));
            if (!$parent_folder || !$parent_folder->isReadable($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
    
            //check, if at least one ID was given:
            $ids = Request::getArray('ids');
    
            if (empty($ids)) {
                $this->redirectToFolder($parent_folder);
                return;
            }
    
            //check, which action was chosen:
    
            if (Request::submitted('download')) {
                //bulk downloading:
                $tmp_file = tempnam($GLOBALS['TMP_PATH'], 'doc');
                $user = User::findCurrent();
                $use_dos_encoding = strpos($_SERVER['HTTP_USER_AGENT'], 'Windows') !== false;
    
                //collect file area objects by looking at their IDs:
                $file_area_objects = [];
                foreach ($ids as $id) {
    
                    if (Request::get("from_plugin")) {
                        $fa_object = $plugin->getFolder($id);
                        if (!$fa_object) {
                            $fa_object = $plugin->getPreparedFile($id, true);
                        }
                        if ($fa_object) {
                            $file_area_objects[] = $fa_object;
                        }
                    } else {
                    //check if the ID references a FileRef:
                        $filesystem_item = FileRef::find($id);
                        if (!$filesystem_item) {
                            //check if the ID references a Folder:
                            $filesystem_item = Folder::find($id);
                            if ($filesystem_item) {
                                $file_area_objects[] = $filesystem_item->getTypedFolder();
                            }
                        } else {
                            $file_area_objects[] = $filesystem_item;
                        }
                    }
                }
    
                if (count($file_area_objects) === 1 && is_a($file_area_objects[0], 'FileRef')) {
                    //we have only one file to deliver, so no need for zipping it:
                    $this->redirect($file_area_objects[0]->getDownloadURL('force_download'));
                    return;
                }
    
                //create a ZIP archive:
                try {
                    $result = FileArchiveManager::createArchive(
                        $file_area_objects,
                        $user->id,
                        $tmp_file,
                        true,
                        true,
                        false,
                        $use_dos_encoding ? 'CP850' : 'UTF-8',
                        true
                    );
                }  catch (FileArchiveManagerException $fame) {
                    PageLayout::postError(_('Es ist ein Fehler aufgetreten.'), [$fame->getMessage()]);
                    $this->redirectToFolder($parent_folder);
                    return;
                }
    
                if ($result) {
                    if (count($file_area_objects) === 1 && $file_area_objects[0] instanceof FolderType) {
                        $zip_file_name = $file_area_objects[0]->name;
                    } else {
                        $zip_file_name = $parent_folder->name;
                    }
                    //ZIP file was created successfully
                    $this->redirect(FileManager::getDownloadURLForTemporaryFile(
                        basename($tmp_file),
                        ($zip_file_name ?: basename($tmp_file)) . '.zip'
                    ));
                } else {
                    throw new Exception('Error while creating ZIP archive!');
                }
            } elseif (Request::submitted('copy')) {
                //bulk copying
                $this->flash['fileref_id'] = Request::getArray('ids');
                $this->redirect($this->url_for('file/choose_destination/copy/flash'));
            } elseif (Request::submitted('move')) {
                //bulk moving
                $this->flash['fileref_id'] = Request::getArray('ids');
                $this->redirect($this->url_for('file/choose_destination/move/flash'));
            } elseif (Request::submitted('delete')) {
                //bulk deleting
                $errors = [];
                $count_files = 0;
                $count_folders = 0;
    
                $user = User::findCurrent();
                $selected_elements = Request::getArray('ids');
                foreach ($selected_elements as $element) {
    
                    if (Request::get("from_plugin")) {
                        $foldertype = $plugin->getFolder($element);
                        if (!$foldertype) {
                            $file_ref = $plugin->getPreparedFile($element, true);
                        }
                    } else {
                        $file_ref = FileRef::find($element);
                        if(!$file_ref) {
                            $foldertype = FileManager::getTypedFolder($element);
                        }
                    }
    
                    if ($file_ref) {
                        $current_folder = $file_ref->getFolderType();
                        $result = $current_folder ? $current_folder->deleteFile($element) : false;
                        if ($result && !is_array($result)) {
                            $count_files += 1;
                        }
                    } elseif ($foldertype) {
                        $folder_files = count($foldertype->getFiles());
                        $folder_subfolders = count($foldertype->getSubfolders());
                        $result = FileManager::deleteFolder($foldertype, $user);
                        if (!is_array($result)) {
                            $count_folders += 1;
                            $count_files += $folder_files;
                            $count_folders += $folder_subfolders;
                        }
                    }
                    if (is_array($result)) {
                        $errors = array_merge($errors, $result);
                    }
                }
    
                if (empty($errors) || $count_files > 0 || $count_folders > 0) {
                    if ($count_files == 1 || $count_folders == 1) {
                        if ($count_folders) {
                            PageLayout::postSuccess(_('Der Ordner wurde gelöscht!'));
                        } else {
                            PageLayout::postSuccess(_('Die Datei wurde gelöscht!'));
                        }
                    } elseif ($count_files > 0 && $count_folders > 0) {
                        PageLayout::postSuccess(sprintf(_('Es wurden %s Ordner und %s Dateien gelöscht!'), $count_folders, $count_files));
                    } elseif ($count_files > 0) {
                        PageLayout::postSuccess(sprintf(_('Es wurden  %s Dateien gelöscht!'), $count_files));
                    } else {
                        PageLayout::postSuccess(sprintf(_('Es wurden %s Ordner gelöscht!'), $count_folders));
                    }
                } else {
                    PageLayout::postError(_('Es ist ein Fehler aufgetreten.'), array_map('htmlReady', $errors));
                }
    
                $this->redirectToFolder($parent_folder);
            }
        }
    
        public function open_folder_action($folder_id)
        {
            $folder = FileManager::getTypedFolder($folder_id, Request::get('from_plugin'));
            URLHelper::addLinkParam('from_plugin', Request::get('from_plugin'));
            if (!$folder || !$folder->isVisible($GLOBALS['user']->id)) {
                throw new AccessDeniedException();
            }
            $this->redirectToFolder($folder);
        }
    
        private function generateFilesUrl($folder, $fileRef)
        {
            require_once 'app/controllers/files.php';
    
            return \FilesController::getRangeLink($folder) . '#fileref_' . $fileRef->getId();
        }
    
        private function getFolderSize($folder): array
        {
            $folder_size = 0;
            $folder_file_amount = 0;
            foreach ($folder->getFiles() as $file) {
                $folder_size += $file->getSize();
                $folder_file_amount++;
            }
            return [$folder_size, $folder_file_amount];
        }
    
        private function store_accessibility_flag(FileType $file)
        {
            if ($file instanceof StandardFile) {
                $file_ref = $file->getFileRef();
                if ($file_ref) {
                    $file_ref->file['is_accessible'] = Request::get('is_accessible');
                    $file_ref->file->store();
                }
            }
        }
    }