diff --git a/app/controllers/file.php b/app/controllers/file.php index f30404f3f62a37b53ee4ddd3833a5f572195ac16..15bca3dbe084517ca15d248e984d913966cfcb0b 100644 --- a/app/controllers/file.php +++ b/app/controllers/file.php @@ -74,6 +74,7 @@ class FileController extends AuthenticatedController } 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(); @@ -171,32 +172,58 @@ class FileController extends AuthenticatedController public function unzipquestion_action() { - $this->file_refs = FileRef::findMany(Request::getArray('file_refs')); - $this->file_ref = $this->file_refs[0]; - $this->current_folder = $this->file_ref->folder->getTypedFolder(); + $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->file_refs = FileArchiveManager::extractArchiveFileToFolder( - $this->file_ref, + $this->files = FileArchiveManager::extractArchiveFileToFolder( + $this->first_file, $this->current_folder, $GLOBALS['user']->id ); $ref_ids = []; - foreach ($this->file_refs as $file_ref) { - $ref_ids[] = $file_ref->id; + foreach ($this->files as $file) { + $ref_ids[] = $file->getId(); } //Delete the original zip file: - $changes['removed_files'] = [$this->file_ref->id]; - $this->file_ref->delete(); + $changes['removed_files'] = [$this->first_file->getId()]; + $this->first_file->delete(); } else { - $ref_ids = [$this->file_ref->getId()]; + $ref_ids = [$this->first_file->getId()]; } $this->flash->set('file_refs', $ref_ids); @@ -213,23 +240,25 @@ class FileController extends AuthenticatedController 'add_folders' => [], ]; $added_folders = []; - foreach ($this->file_refs as $fileref) { - if ($fileref->folder->id === $this->current_folder->id) { - $payload['added_files'][] = FilesystemVueDataManager::getFileVueData($fileref->getFileType(), $this->current_folder); + 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 ( - $fileref->folder->parentfolder->id === $this->current_folder->id - && !in_array($fileref->folder->id, $added_folders) + $folder->getParent() && + $folder->getParent()->getId() === $this->current_folder->getId() + && !in_array($folder->getId(), $added_folders) ) { if ($topFolder === null) { $topFolder = $this->current_folder; - while ($topFolder->parentfolder !== null) { - $topFolder = $topFolder->parentFolder; + while ($topFolder->getParent() !== null) { + $topFolder = $topFolder->getParent(); } } - $payload['added_folders'][] = FilesystemVueDataManager::getFolderVueData($fileref->getFolderType(), $this->current_folder); + $payload['added_folders'][] = FilesystemVueDataManager::getFolderVueData($folder, $this->current_folder); - $added_folders[] = $fileref->folder->id; + $added_folders[] = $folder->getId(); } } @@ -378,7 +407,7 @@ class FileController extends AuthenticatedController $force_save = Request::submitted('force_save'); $this->name = trim(Request::get('name')); $this->description = Request::get('description'); - $this->store_accessibility_flag($file_ref_id); + $this->store_accessibility_flag($this->file); $this->content_terms_of_use_id = Request::get('content_terms_of_use_id'); @@ -1570,17 +1599,48 @@ class FileController extends AuthenticatedController } } - public function edit_license_action($folder_id = null) + + protected function loadFiles($param = 'files', $plugin = null, $with_blob = false) { - $this->re_location = Request::get('re_location'); - $file_ref_ids = Request::getArray('file_refs'); - if (!$file_ref_ids) { + $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_ref_ids = $this->flash->get('file_refs'); + $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; + } + } } - $this->file_refs = FileRef::findMany($file_ref_ids); - $this->folder = $this->file_refs[0]->folder; + 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; @@ -1589,51 +1649,54 @@ class FileController extends AuthenticatedController if (Request::isPost()) { CSRFProtection::verifyUnsafeRequest(); - if (count($file_ref_ids) === 1) { + if (count($this->files) === 1) { // store flag if file is an accessible file - $this->store_accessibility_flag($file_ref_ids[0]); + $this->store_accessibility_flag($this->files[0]); } if (($folder_id == 'bulk') && !Request::submitted('accept')) { - $file_ref_ids = Request::getArray('ids'); - $this->file_refs = FileRef::findMany($file_ref_ids); + $this->files = $this->loadFiles('ids', $this->plugin); } else { $description = Request::get('description'); $success_files = []; $error_files = []; - foreach ($this->file_refs as $file_ref) { + foreach ($this->files as $file) { //Check if the user may change the license of the file: - $folder = $file_ref['folder']; + $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_ref['name']); + $error_files[] = sprintf(_('Die Datei "%s" ist ungültig!'), $file['name']); continue; } - - $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->isDirty()) { + 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_ref['name']; + $success_files[] = $file->getFilename(); } else { - $error_files[] = sprintf(_('Fehler beim Speichern der Datei "%s"!'), $file_ref['name']); + $error_files[] = sprintf(_('Fehler beim Speichern der Datei "%s"!'), $file['name']); } - } else { - $success_files[] = $file_ref['name']; } - $this->file = $file_ref->getFileType(); - $this->current_folder = $file_ref->folder->getTypedFolder(); + $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->file_refs as $file_ref) { - $folder = $file_ref->folder->getTypedFolder(); + foreach ($this->files as $file) { + $folder = $file->getFolderType(); // Skip files not in current folder (during archive extract) if ($folder_id && $folder_id !== $folder->getId()) { @@ -1641,31 +1704,34 @@ class FileController extends AuthenticatedController } $payload['html'][] = FilesystemVueDataManager::getFileVueData( - $file_ref->getFileType(), - $file_ref->folder->getTypedFolder() + $file, + $file->getFolderType() ); } $plugins = PluginManager::getInstance()->getPlugins('FileUploadHook'); $redirect = null; - foreach ($plugins as $plugin) { - $url = $plugin->getAdditionalUploadWizardPage($file_ref); + foreach ($plugins as $upload_hook_plugin) { + $url = $upload_hook_plugin->getAdditionalUploadWizardPage($file_ref); if ($url) { $redirect = $url; break; } } - if (count($file_ref_ids) === 1) { + if (count($this->files) === 1) { if (Config::get()->OERCAMPUS_ENABLED && Config::get()->OER_ENABLE_POST_UPLOAD && $GLOBALS['perm']->have_perm('tutor') ) { - 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 ($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; + } } } } @@ -1677,15 +1743,15 @@ class FileController extends AuthenticatedController $payload['url'] = $this->generateFilesUrl( $this->folder, - $file_ref + $this->file ); - if ($folder_id == 'bulk' && $this->file_refs) { + 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->file_refs[0]->name) + htmlReady($this->files[0]->getName()) )); } else { sort($success_files); @@ -1699,7 +1765,7 @@ class FileController extends AuthenticatedController if (count($error_files) == 1) { PageLayout::postError(sprintf( _('Die Lizenz der Datei "%s" konnte nicht geändert werden!'), - htmlReady($this->file_refs[0]->name) + htmlReady($this->files[0]->getName()) )); } else { PageLayout::postError( @@ -1731,9 +1797,9 @@ class FileController extends AuthenticatedController ngettext( 'Zusatzangaben und Lizenz wählen', 'Zusatzangaben und Lizenz auswählen: %s Dateien', - count($this->file_refs) + count($this->files) ), - count($this->file_refs) + count($this->files) )); $this->licenses = ContentTermsOfUse::findBySQL("1 ORDER BY position ASC, id ASC"); @@ -2224,7 +2290,7 @@ class FileController extends AuthenticatedController { require_once 'app/controllers/files.php'; - return \FilesController::getRangeLink($folder) . '#fileref_' . $fileRef->id; + return \FilesController::getRangeLink($folder) . '#fileref_' . $fileRef->getId(); } private function getFolderSize($folder): array @@ -2238,10 +2304,14 @@ class FileController extends AuthenticatedController return [$folder_size, $folder_file_amount]; } - private function store_accessibility_flag($file_ref_id) + private function store_accessibility_flag(FileType $file) { - $file_ref = FileRef::find($file_ref_id); - $file_ref->file['is_accessible'] = Request::get('is_accessible'); - $file_ref->file->store(); + if ($file instanceof StandardFile) { + $file_ref = $file->getFileRef(); + if ($file_ref) { + $file_ref->file['is_accessible'] = Request::get('is_accessible'); + $file_ref->file->store(); + } + } } } diff --git a/app/views/file/edit_license.php b/app/views/file/edit_license.php index ddd031d153c6b1733c1a482e0cf0ebbb6794dc43..a9cf94e0f334ac641fb1e6e1fdd735380e2e285c 100644 --- a/app/views/file/edit_license.php +++ b/app/views/file/edit_license.php @@ -1,8 +1,9 @@ <form action="<?= $controller->link_for('file/edit_license', $origin_folder_id ?? null) ?>" method="post" class="default" data-dialog="reload-on-close"> <input type="hidden" name="re_location" value="<?= htmlReady($re_location) ?>"> -<? foreach ($file_refs as $file_ref) : ?> - <input type="hidden" name="file_refs[]" value="<?= htmlReady($file_ref->id) ?>"> + <input type="hidden" name="to_plugin" value="<?= $plugin ? $plugin->getPluginName() : '' ?>"> +<? foreach ($files as $file) : ?> + <input type="hidden" name="file_refs[]" value="<?= htmlReady($file->getId()) ?>"> <? endforeach ?> @@ -17,7 +18,7 @@ <? endif ?> - <? if (count($file_refs) === 1) : ?> + <? if (count($files) === 1) : ?> <fieldset> <legend><?= _('Barrierefreiheit') ?></legend> <label> @@ -30,7 +31,7 @@ <?= $this->render_partial('file/_terms_of_use_select.php', [ 'content_terms_of_use_entries' => $licenses, - 'selected_terms_of_use_id' => $file_ref->content_terms_of_use_id + 'selected_terms_of_use_id' => $file_ref->content_terms_of_use_id ?? '' ]) ?> <footer data-dialog-button> diff --git a/app/views/file/unzipquestion.php b/app/views/file/unzipquestion.php index a7e82b1b2ee6538fb60bff3e3749cbd96b91cbef..361ae63e4000aa0f0dd64a3db0aa0eb3d0a76ad9 100644 --- a/app/views/file/unzipquestion.php +++ b/app/views/file/unzipquestion.php @@ -1,7 +1,7 @@ <form action="<?= $controller->url_for('file/unzipquestion') ?>" method="post" data-dialog> -<? foreach ($file_refs as $file_ref): ?> - <input type="hidden" name="file_refs[]" value="<?= htmlReady($file_ref->id) ?>"> +<? foreach ($files as $file): ?> + <input type="hidden" name="file_refs[]" value="<?= htmlReady($file->getId()) ?>"> <? endforeach ?> <?= Icon::create('unit-test', Icon::ROLE_INACTIVE)->asImg(120, ['style' => 'display: block; margin-left: auto; margin-right: auto;']) ?> diff --git a/lib/filesystem/FileArchiveManager.class.php b/lib/filesystem/FileArchiveManager.class.php index e7a0d40581c9e6c830c0ee9dec11db06a14b92f3..498bb5814d09ebc7336c5434ed24baeb502e1482 100644 --- a/lib/filesystem/FileArchiveManager.class.php +++ b/lib/filesystem/FileArchiveManager.class.php @@ -828,7 +828,7 @@ class FileArchiveManager * @param FolderType $target_folder The folder where the file shall be stored. * @param User $user The user who wishes to extract the file from the archive. * - * @return FileRef|null FileRef instance on success, null otherwise. + * @return FileType|null FileType instance on success, null otherwise. */ public static function extractFileFromArchive( Studip\ZipArchive $archive, @@ -844,59 +844,62 @@ class FileArchiveManager return null; } - $file = new File(); - $file->user_id = $user->id; - $file->name = $archive->convertArchiveFilename(basename($archive_path)); - $file->mime_type = get_mime_type($file->name); - $file->size = $file_info['size']; - $file->store(); + $studip_file = new File(); + $studip_file->user_id = $user->id; + $studip_file->name = $archive->convertArchiveFilename(basename($archive_path)); + $studip_file->mime_type = get_mime_type($studip_file->name); + $studip_file->size = $file_info['size']; + $studip_file->id = $studip_file->getNewId(); + //$file->store(); // Ok, we have a file object in the database. Now we must connect // it with the data file by extracting the data file into // the place, where the file's content has to be placed. - $file_path = pathinfo($file->getPath(), PATHINFO_DIRNAME); + $file_dir = pathinfo($studip_file->getPath(), PATHINFO_DIRNAME); + $file_path = $file_dir . '/' . $studip_file->id; // Create the directory for the file, if necessary: - if (!is_dir($file_path)) { - mkdir($file_path); + if (!is_dir($file_dir)) { + mkdir($file_dir); } // Ok, now we read all data from $file_resource and put it into // the file's path: - if (file_put_contents($file->getPath(), $file_resource) === false) { + if (file_put_contents($file_path, $file_resource) === false) { //Something went wrong: abort and clean up! - $file->delete(); + //$file->delete(); return null; } - // Ok, we now must create a FileRef: + // Ok, we now must create a File: $file_ref = new FileRef(); - $file_ref->file_id = $file->id; + $file_ref->file_id = $studip_file->id; $file_ref->folder_id = $target_folder->getId(); $file_ref->user_id = $user->id; - $file_ref->name = $file->name; - if ($file_ref->store()) { - return $file_ref; + $file_ref->name = $studip_file->name; + $file_ref->file = $studip_file; + $file = new StandardFile($file_ref); + if ($saved_file = $target_folder->addFile($file, $user->id)) { + return $saved_file; } - //Something went wrong: abort and clean up! - $file_ref->delete(); + //Something went wrong: return null; } /** * Extracts an archive into a folder inside the Stud.IP file area. * - * @param FileRef $archive_file_ref The archive file which shall be extracted. + * @param FileType $archive_file The archive file which shall be extracted. * @param FolderType $folder The folder where the archive shall be extracted. * @param string $user_id The ID of the user who wants to extract the archive. * - * @return FileRef[] Array with extracted files, represented as FileRef objects. + * @return FileType[] Array with extracted files, represented as FileRef objects. */ public static function extractArchiveFileToFolder( - FileRef $archive_file_ref, + FileType $archive_file, FolderType $folder, - $user_id = null + $user_id = null ) { $user = $user_id ? User::find($user_id) : User::findCurrent(); @@ -913,11 +916,16 @@ class FileArchiveManager $keep_hierarchy = $folder->isSubfolderAllowed($user->id); $archive = new Studip\ZipArchive(); - $archive->open($archive_file_ref->file->getPath()); + $standard_archive_file = $archive_file->convertToStandardFile(); + if (!($standard_archive_file instanceof StandardFile)) { + //Error converting the archive file. + return []; + } + $archive->open($standard_archive_file->getPath()); // loop over all entries in the zip archive and put each entry // in the current folder or one of its subfolders: - $file_refs = []; + $files = []; for ($i = 0; $i < $archive->numFiles; $i++) { $entry_info = $archive->statIndex($i); @@ -972,19 +980,19 @@ class FileArchiveManager //we extract one file: //$entry_info['name'] is necessary because we need the full path //to the entry inside the archive. - $file_ref = self::extractFileFromArchive( + $file = self::extractFileFromArchive( $archive, $entry_info['name'], $extracted_entry_destination_folder, $user ); - if ($file_ref instanceof FileRef) { - $file_refs[] = $file_ref; + if ($file instanceof FileType) { + $files[] = $file; } } } - return $file_refs; + return $files; } } diff --git a/lib/filesystem/StandardFile.php b/lib/filesystem/StandardFile.php index 4547d37c0f7af2e93da7bec74366d8a92d1f8582..5723ef48f659b29170e2ecc1b92dafe73538e2d2 100644 --- a/lib/filesystem/StandardFile.php +++ b/lib/filesystem/StandardFile.php @@ -39,7 +39,7 @@ class StandardFile implements FileType, ArrayAccess, StandardFileInterface $mime_type = $data['type'] ?: get_mime_type($data['name']); $filesize = $data['size'] ?: filesize($data['tmp_name']); $file_path = $data['tmp_name']; - $error_code = $data['error']; + $error_code = $data['error'] ?? ''; if ($error_code) { //error handling