aboutsummaryrefslogtreecommitdiff
path: root/lib/filesystem/FileArchiveManager.class.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/filesystem/FileArchiveManager.class.php')
-rw-r--r--lib/filesystem/FileArchiveManager.class.php998
1 files changed, 0 insertions, 998 deletions
diff --git a/lib/filesystem/FileArchiveManager.class.php b/lib/filesystem/FileArchiveManager.class.php
deleted file mode 100644
index 704bb44..0000000
--- a/lib/filesystem/FileArchiveManager.class.php
+++ /dev/null
@@ -1,998 +0,0 @@
-<?php
-/**
- * FileArchiveManager.class.php
- *
- * 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>
- * @copyright 2016 data-quest
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @category Stud.IP
- */
-
-
-/**
- * The FileArchiveManager class gives programmers a simple way to handle
- * file archives by providing different methods for packing and unpacking
- * file archives in a simple manner.
- */
-class FileArchiveManager
-{
-
- //ARCHIVE HELPER METHODS
-
-
- /**
- * Adds a file to an archive using its FileType object.
- *
- * @param ZipArchive $archive The Zip archive where the FileRef shall be added to.
- * @param FileType $file_type The FileType which shall be added to the zip archive.
- * @param string $user_id The user who wishes to add the FileRef to the archive.
- * @param string $archive_fs_path The path of the file inside the archive's file system.
- * @param bool $do_user_permission_checks Set to true if reading/downloading permissions
- * shall be checked. False otherwise. Default is true.
- * @param bool $ignore_user Set to true, if a file
- * which has no download restrictions shall be included
- * and the user-specific download condition check shall be ignored.
- * If this parameter is set to true, the user_id parameter is irrelevant.
- * The default for this parameter is false.
- * @return bool True on success, false on failure.
- *
- * @throws Exception|FileArchiveManagerException If an error occurs a general exception or a more
- * special exception is thrown.
- */
- public static function addFileTypeToArchive(
- ZipArchive $archive,
- FileType $file_type,
- $user_id = null,
- $archive_fs_path = '',
- $do_user_permission_checks = true,
- $ignore_user = false,
- &$file_list = null
- )
- {
- $archive_max_size = Config::get()->ZIP_DOWNLOAD_MAX_SIZE * 1024 * 1024;
- //For FileRef objects we first have to do permission checks
- //using the FileRef's folder object.
- $adding_allowed = false;
-
- if ($do_user_permission_checks) {
- $folder = $file_type->getFolderType();
- if (!$folder) {
- return false;
- }
-
- if ($folder->isReadable($user_id) && $file_type->isDownloadable($user_id)) {
- //FileRef is readable and downloadable for the user (identified by $user_id).
- $adding_allowed = true;
- }
- } elseif ($ignore_user) {
- //we have to check the download condition by looking at the
- //terms of use object of the FileType:
- $terms_of_use = $file_type->getTermsOfUse();
- if ($terms_of_use && $terms_of_use->download_condition == 0) {
- $adding_allowed = true;
- }
- } else {
- //Totally skip permission checks:
- $adding_allowed = true;
- }
-
- if ($adding_allowed) {
- //Adding the FileType is allowed:
- $file_contains_link = false;
- if ($file_type instanceof LibraryFile) {
- $file_contains_link = !$file_type->hasFileAttached();
- } else {
- $file_contains_link = $file_type instanceof URLFile;
- }
-
- // Increase download counter
- if ($file_type instanceof StandardFile) {
- $file_ref = $file_type->getFileRef();
- $file_ref->incrementDownloadCounter();
- }
-
- if ($file_contains_link) {
- //The FileType references a link:
- //Put the URL into a file ending with .url:
- $url = $file_type->getDownloadURL();
- if ($url) {
- //The URL has been fetched and we can put it
- //in a file in the archive:
- $archive->addFromString(
- $archive_fs_path . FileManager::cleanFileName($file_type->getFilename()) . '.url',
- "[InternetShortcut]\nURL={$url}\n"
- );
- //Check the file size of the archive:
- if (file_exists($archive->filename) && filesize($archive->filename) > $archive_max_size) {
- throw new FileArchiveManagerException(
- sprintf(
- _('Das ZIP-Archiv ist zu groß! Die maximal erlaubte Größe ist %s!'),
- relsize($archive_max_size)
- )
- );
- }
- if (is_array($file_list)) {
- $user = $file_type->getUser();
- $file_list[] = [
- 'name' => FileManager::cleanFileName($file_type->getFilename()),
- 'size' => $file_type->getSize(),
- 'first_name' => ($user instanceof User) ? $user->vorname : '',
- 'last_name' => ($user instanceof User) ? $user->nachname : '',
- 'downloads' => $file_type->getDownloads(),
- 'mkdate' => date('d.m.Y H:i', $file_type->getMakeDate()),
- 'path' => ($archive_fs_path . $file_type->getFilename())
- ];
- }
- return true;
- }
- } else {
- if (!($file_type instanceof StandardFile)) {
- $file_type = $file_type->convertToStandardFile();
- }
- if (!($file_type instanceof StandardFile)) {
- //The file type could not be converted to a standard file.
- //We cannot continue.
- return false;
- }
- //Get the file's path (if the file exists) and add the file to the archive:
- $path = $file_type->getPath();
- if ($path) {
- //It is a file in the file system:
- if (file_exists($path)) {
- $archive->addFile($path, $archive_fs_path . FileManager::cleanFileName($file_type->getFilename()));
- //Check the file size of the archive:
- if (file_exists($archive->filename) && filesize($archive->filename) > $archive_max_size) {
- throw new FileArchiveManagerException(
- sprintf(
- _('Das ZIP-Archiv ist zu groß! Die maximal erlaubte Größe ist %s!'),
- relsize($archive_max_size)
- )
- );
- }
- //Add the file to the file list (if available):
- if (is_array($file_list)) {
- $archive_max_num_files = Config::get()->ZIP_DOWNLOAD_MAX_FILES;
- $archive_max_size = Config::get()->ZIP_DOWNLOAD_MAX_SIZE * 1024 * 1024; //1048576 bytes = 1 Mebibyte
- $user = $file_type->getUser();
- $file_list[] = [
- 'name' => FileManager::cleanFileName($file_type->getFilename()),
- 'size' => $file_type->getSize(),
- 'first_name' => ($user instanceof User) ? $user->vorname : '',
- 'last_name' => ($user instanceof User) ? $user->nachname : '',
- 'downloads' => $file_type->getDownloads(),
- 'mkdate' => date('d.m.Y H:i', $file_type->getMakeDate()),
- 'path' => ($archive_fs_path . FileManager::cleanFileName($file_type->getFilename()))
- ];
- if (count($file_list) > $archive_max_num_files) {
- $archive->unchangeAll();
- unlink($archive->filename);
- throw new FileArchiveManagerException(
- sprintf(
- _('Das Archiv beinhaltet zu viele Dateibereich-Objekte! Die Obergrenze liegt bei %d Objekten!'),
- $archive_max_num_files
- )
- );
- }
- if (array_sum(array_column($file_list, 'size')) > $archive_max_size) {
- $archive->unchangeAll();
- unlink($archive->filename);
- throw new FileArchiveManagerException(
- sprintf(
- _('Das ZIP-Archiv ist zu groß! Die maximal erlaubte Größe ist %s!'),
- relsize($archive_max_size)
- )
- );
- }
- }
- }
- }
- }
- }
-
- //Something must have gone wrong:
- return false;
- }
-
-
- /**
- * Adds a FileRef to a Zip archive.
- * This is only a wrapper to addFileTypeToArchive that exists only
- * for compatibility reasons.
- *
- * @see addFileTypeToArchive
- */
- public static function addFileRefToArchive(
- ZipArchive $archive,
- FileRef $file_ref,
- $user_id = null,
- $archive_fs_path = '',
- $do_user_permission_checks = true,
- $ignore_user = false,
- &$file_list = null
- )
- {
- $file_type = $file_ref->getFileType();
- if ($file_type instanceof FileType) {
- return self::addFileTypeToArchive(
- $archive,
- $file_type,
- $user_id,
- $archive_fs_path,
- $do_user_permission_checks,
- $ignore_user,
- $file_list
- );
- }
- //The file type variable does not contain a FileType object.
- return false;
- }
-
-
- /**
- * Adds a FolderType instance to a Zip archive.
- *
- * @param ZipArchive $archive The Zip archive where the FileRef shall be added to.
- * @param FileRef $file_ref The FileRef which shall be added to the zip archive.
- * @param string $user_id The user who wishes to add the FileRef to the archive.
- * @param string $archive_fs_path The path of the folder inside the archive's file system.
- * @param bool $do_user_permission_checks Set to true if reading/downloading permissions
- * shall be checked. False otherwise. Default is true.
- * @param bool $keep_hierarchy True, if the folder hierarchy shall be kept.
- * False, if the folder hierarchy shall be flattened.
- * @param bool $ignore_user Set to true, if a folder
- * of type StandardFolder shall be included without checking
- * if the user (identified by user_id) can read it.
- * @return bool True on success, false on failure.
- *
- * @throws Exception|FileArchiveManagerException If an error occurs a general exception or a more
- * special exception is thrown.
- */
- public static function addFolderToArchive(
- ZipArchive $archive,
- FolderType $folder,
- $user_id = null,
- $archive_fs_path = '',
- $do_user_permission_checks = true,
- $keep_hierarchy = true,
- $ignore_user = false,
- &$file_list = null
- ) {
-
- if ($do_user_permission_checks) {
- //Check if the folder is readable for the user (identified by $user_id):
- if (!$folder->isReadable($user_id)) {
- //Folder is not readable:
- return false;
- }
- } elseif ($ignore_user
- && !($folder instanceof StandardFolder)
- && in_array($folder->range_type, ['course', 'institute']))
- {
- //If user permissions shall be skipped the folder must be
- //an instance of StandardFolder and the folder's range type
- //must be course or institute since we can only be sure
- //that StandardFolder instances in courses or institutes
- //are readable by everyone.
- return false;
- }
-
- $folder_zip_path = $archive_fs_path;
- if ($keep_hierarchy) {
- $folder_zip_path .= FileManager::cleanFileName($folder->name);
- $archive->addEmptyDir($folder_zip_path);
- }
- foreach ($folder->getFiles() as $file) {
-
- /*if (!$file_ref instanceof FileRef) { TODO: OwnCloudPlugin is this ready?
- $plugin = PluginManager::getInstance()->getPlugin($folder->range_id);
- if (!$plugin) {
- $plugin = PluginManager::getInstance()->getPlugin($folder->range_type);;
- }
- if ($plugin) {
- $file_ref = $plugin->getPreparedFile($file_ref->id, true);
- }
- }*/
-
- self::addFileTypeToArchive(
- $archive,
- $file,
- $user_id,
- //keep hierarchy in zip file (files and subdirectories)
- $keep_hierarchy ? $folder_zip_path . '/' : '',
- $do_user_permission_checks,
- $ignore_user,
- $file_list
- );
- }
-
- foreach ($folder->getSubfolders() as $subfolder) {
- self::addFolderToArchive(
- $archive,
- $subfolder,
- $user_id,
- //keep hierarchy in zip file (files and subdirectories)
- $keep_hierarchy ? $folder_zip_path . '/' : '',
- $do_user_permission_checks,
- $keep_hierarchy,
- $ignore_user,
- $file_list
- );
- }
-
- return true;
- }
-
-
- //ARCHIVE CREATION METHODS
-
-
- /**
- * General method for creating file archives.
- *
- * This method is a generalisation for all archive creation methods.
- * For easier archive creation you may use the other archive creation
- * methods which work with less arguments.
- *
- * @param Array $file_area_objects Array of FileRef, FileURL, Folder or FolderType objects.
- * $file_area_objects may contain a mix between those object types.
- * @param string $user_id The user who wishes to pack files.
- * @param string $archive_file_path The path for the archive file.
- * @param bool $do_user_permission_checks Set to true if individual
- * reading/downloading permissions shall be checked. False otherwise.
- * Default is true.
- * @param bool $keep_hierarchy True, if the folder hierarchy shall be kept.
- * False, if the folder hierarchy shall be flattened. Default is true.
- * @param bool $ignore_user Set to true, if all files
- * which have no download restrictions and all folders which are of type
- * StandardFolder shall be included and the user-specific
- * download condition check shall be ignored.
- * If this parameter is set to true, the user_id parameter is irrelevant.
- * The default for this parameter is false.
- * @param string $zip_encoding encoding for filenames in zip
- * @param bool $add_filelist_to_archive If this is set to true a file list
- * in the CSV format will be added to the archive. Its name is hardcoded
- * to archive_filelist.csv. The default value of $add_filelist_to_archive
- * is false which means no file list is added.
- *
- * @return bool True, if the archive file was created and saved successfully
- * at $archive_file_path, false otherwise.
- *
- * @throws Exception|FileArchiveManagerException If an error occurs a general exception or a more
- * special exception is thrown.
- */
- public static function createArchive(
- $file_area_objects = [],
- $user_id = null,
- $archive_file_path = '',
- $do_user_permission_checks = true,
- $keep_hierarchy = true,
- $ignore_user = false,
- $zip_encoding = 'UTF-8',
- $add_filelist_to_archive = false
- )
- {
-
- // check if archive path is set:
- if (!$archive_file_path) {
- throw new FileArchiveManagerException(
- _('Der Zielpfad für das Archiv wurde nicht angegeben!')
- );
- }
-
- // $file_area_objects must be a non-empty array!
- // Otherwise we would return an empty Zip archive.
- if (!is_array($file_area_objects) || empty($file_area_objects)) {
- throw new FileArchiveManagerException(
- _('Es wurden keine Dateien ausgewählt!')
- );
- }
-
- // We can create the Zip archive now since its path exists in the file system
- // and furthermore there are file area objects available.
- $archive = new Studip\ZipArchive();
- if (!$archive->open($archive_file_path, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
- throw new FileArchiveManagerException('Error opening new ZIP archive!');
- }
- $archive->setOutputEncoding($zip_encoding);
-
- //If $file_list is not an array
- //then no files are added to the file list.
- $file_list = null;
- if ($add_filelist_to_archive) {
- $file_list = [];
- }
-
- foreach ($file_area_objects as $file_area_object) {
- if ($file_area_object instanceof FileRef) {
- self::addFileRefToArchive(
- $archive,
- $file_area_object,
- $user_id,
- '',
- $do_user_permission_checks,
- $ignore_user,
- $file_list
- );
- } elseif ($file_area_object instanceof FileType) {
- self::addFileTypeToArchive(
- $archive,
- $file_area_object,
- $user_id,
- '',
- $do_user_permission_checks,
- $ignore_user,
- $file_list
- );
- } elseif ($file_area_object instanceof Folder || $file_area_object instanceof FolderType) {
- $folder = $file_area_object;
- if ($folder instanceof Folder) {
- //We use FolderType instances here.
- $folder = $folder->getTypedFolder();
- }
-
- self::addFolderToArchive(
- $archive,
- $folder,
- $user_id,
- '',
- $do_user_permission_checks,
- $keep_hierarchy,
- $ignore_user,
- $file_list
- );
- }
- }
-
- if ($archive->numFiles > 0) {
- //At least one file is in the archive.
-
- if ($add_filelist_to_archive) {
- //If a file list shall be included in the ZIP archive
- //we must now make a CSV file out of file_list:
-
- $csv_data = array_merge(
- [
- [
- _('Name'),
- _('Größe'),
- _('Vorname'),
- _('Nachname'),
- _('Downloads'),
- _('Datum'),
- _('Pfad')
- ]
- ],
- $file_list
- );
-
- //The CSV file has been generated.
- //Now we must add it to the archive:
- $archive->addFromString('archive_filelist.csv', array_to_csv($csv_data));
- }
-
- //Now the ZIP file is really finished:
- return $archive->close();
- }
-
- //empty archive
- throw new FileArchiveManagerException(
- _('Das ZIP Archiv enthält keine Dateien!')
- );
- }
-
- /**
- * Puts files (identified by their file refs) into one file archive.
- *
- * @param FileRef[] $file_refs Array of FileRef objects.
- * @param User $user The user who wishes to pack files.
- * @param string $archive_file_path The path for the archive file.
- * @param bool $do_user_permission_checks Set to true if reading/downloading
- * permissions shall be checked. False otherwise. Default is true.
- *
- * @return bool True, if the archive file was created and saved successfully
- * at $archive_file_path, false otherwise.
- *
- * @throws Exception|FileArchiveManagerException If an error occurs
- * a general exception or a more special exception is thrown.
- */
- public static function createArchiveFromFileRefs(
- $file_refs,
- User $user,
- $archive_file_path = '',
- $do_user_permission_checks = true
- )
- {
- if (!$archive_file_path) {
- throw new FileArchiveManagerException(
- _('Der Zielpfad für das Archiv wurde nicht angegeben!')
- );
- }
-
- //We must now collect all the files from these FileRefs and copy them
- //into the new archive file.
-
- return self::createArchive(
- $file_refs,
- $user->id,
- $archive_file_path,
- $do_user_permission_checks,
- false //do not keep the file hierarchy
- );
- }
-
- /**
- * Returns all children of a folder type.
- *
- * @param FolderType $folder
- * @return array
- */
- private static function getFolderChildren(FolderType $folder)
- {
- $children = [];
- foreach ($folder->subfolders as $folder) {
- $children[] = $folder;
- }
- foreach ($folder->file_refs as $ref) {
- $children[] = $ref;
- }
- return $children;
- }
-
- /**
- * Creates an archive that contains all files of a course the given user
- * is allowed to download.
- *
- * @param FolderType $folder The folder whose files shall be put inside an archive.
- * @param string $user_id The ID of the user who wishes to put the course's files into an archive
- * @param string $archive_file_path The path for the archive file.
- * @param bool $do_user_permission_checks Set to true if reading/downloading permissions
- * shall be checked. False otherwise. Default is true.
- * @param bool $keep_hierarchy True, if the file hierarchy shall be kept inside the archive.
- * If $keep_hierarchy is set to false you will get an archive that contains only files
- * and no subdirectories.
- *
- * @return bool True, if the archive file was created and saved successfully
- * at $archive_file_path, false otherwise.
- *
- * @throws Exception|FileArchiveManagerException If an error occurs
- * a general exception or a more special exception is thrown.
- */
- public static function createArchiveFromFolder(
- FolderType $folder,
- $user_id = null,
- $archive_file_path = '',
- $do_user_permission_checks = true,
- $keep_hierarchy = true
- )
- {
- return self::createArchive(
- self::getFolderChildren($folder),
- $user_id,
- $archive_file_path,
- $do_user_permission_checks,
- $keep_hierarchy
- );
- }
-
- /**
- * Creates an archive that contains all files of a course the given user
- * is allowed to download.
- *
- * @param string $course_id The ID of the course whose files shall be put inside an archive.
- * @param string $user_id The ID of the user who wishes to put the course's files into an archive
- * @param string $archive_file_path The path for the archive file.
- * @param bool $do_user_permission_checks Set to true if reading/downloading permissions
- * shall be checked. False otherwise. Default is true.
- * @param bool $keep_hierarchy True, if the file hierarchy shall be kept inside the archive.
- * If $keep_hierarchy is set to false you will get an archive that contains only files
- * and no subdirectories.
- *
- * @return bool True, if the archive file was created and saved successfully
- * at $archive_file_path, false otherwise.
- *
- * @throws Exception|FileArchiveManagerException If an error occurs
- * a general exception or a more special exception is thrown.
- */
- public static function createArchiveFromCourse(
- $course_id,
- $user_id = null,
- $archive_file_path = '',
- $do_user_permission_checks = true,
- $keep_hierarchy = true
- )
- {
- $folder = Folder::findTopFolder($course_id);
- if (!$folder) {
- return null;
- }
-
- $folder = $folder->getTypedFolder();
- if (!$folder) {
- return null;
- }
-
- return self::createArchive(
- self::getFolderChildren($folder),
- $user_id,
- $archive_file_path,
- $do_user_permission_checks,
- $keep_hierarchy
- );
- }
-
-
- /**
- * Creates an archive that contains all files of an institute the given user
- * is allowed to download.
- *
- * @param string $institute_id The ID of the institute whose files shall be put inside an archive.
- * @param string $user_id The ID of the user who wishes to put the institute's files into an archive
- * @param string $archive_file_path The path for the archive file.
- * @param bool $do_user_permission_checks Set to true if reading/downloading permissions
- * shall be checked. False otherwise. Default is true.
- * @param bool $keep_hierarchy True, if the file hierarchy shall be kept inside the archive.
- * If $keep_hierarchy is set to false you will get an archive that contains only files
- * and no subdirectories.
- *
- * @return bool True, if the archive file was created and saved successfully
- * at $archive_file_path, false otherwise.
- *
- * @throws Exception|FileArchiveManagerException If an error occurs
- * a general exception or a more special exception is thrown.
- */
- public static function createArchiveFromInstitute(
- $institute_id,
- $user_id = null,
- $archive_file_path = '',
- $do_user_permission_checks = true,
- $keep_hierarchy = true)
- {
- $folder = Folder::findTopFolder($institute_id);
- if(!$folder) {
- return null;
- }
-
- $folder = $folder->getTypedFolder();
- if(!$folder) {
- return null;
- }
-
- return self::createArchive(
- self::getFolderChildren($folder),
- $archive_file_path,
- $do_user_permission_checks,
- $keep_hierarchy
- );
- }
-
- /**
- * Creates an archive that contains all files of a user, if the current
- * user has root permissions to do this.
- *
- * @param string $user_id The ID of the user whose files shall be put inside an archive.
- * @param string $archive_file_path The path for the archive file.
- * @param bool $do_user_permission_checks Set to true if reading/downloading permissions
- * shall be checked. False otherwise. Default is true.
- * @param bool $keep_hierarchy True, if the file hierarchy shall be kept inside the archive.
- * If $keep_hierarchy is set to false you will get an archive that contains only files
- * and no subdirectories.
- *
- * @return bool True, if the archive file was created and saved successfully
- * at $archive_file_path, false otherwise.
- *
- * @throws Exception|FileArchiveManagerException If an error occurs
- * a general exception or a more special exception is thrown.
- */
- public static function createArchiveFromUser(
- $user_id,
- $archive_file_path = '',
- $do_user_permission_checks = true,
- $keep_hierarchy = true
- )
- {
- $folder = Folder::findTopFolder($user_id);
- if (!$folder) {
- return null;
- }
-
- $folder = $folder->getTypedFolder();
- if (!$folder) {
- return null;
- }
-
- return self::createArchive(
- self::getFolderChildren($folder),
- $archive_file_path,
- $do_user_permission_checks,
- $keep_hierarchy
- );
- }
-
-
- /**
- * This method creates an archive with the content of a physical folder
- * (A folder inside the operating system's file system).
- *
- * @param string $folder_path The path to the physical folder
- * which content shall be added to a file archive.
- * @param string $archive_file_path The path to the archive file which
- * shall be created.
- *
- * @return True, if all files were added successfully, false otherwise.
- *
- * @throws Exception|FileArchiveManagerException If an error occurs
- * a general exception or a more special exception is thrown.
- */
- public static function createArchiveFromPhysicalFolder($folder_path, $archive_file_path)
- {
- if (!$folder_path || !$archive_file_path) {
- //we can't work with empty paths!
- return false;
- }
-
- if (!file_exists($folder_path)) {
- //path to physical folder does not exist!
- throw new FileArchiveManagerException(
- _('Der Ordner wurde im Dateisystem des Servers nicht gefunden!')
- );
- }
-
- //Put all the content of the folder inside an archive:
- $archive = Studip\ZipArchive::create($archive_file_path, true);
- $result = $archive->addFromPath($folder_path);
- $archive->close();
- return $result;
- }
-
- //ARCHIVE EXTRACTION METHODS
-
- /**
- * This is a helper method that builds a subfolder hierarchy inside
- * a folder by looking at a string representing a file system path.
- *
- * The variable $path contains a hierarchy of subfolders that shall be created
- * inside the given folder. If $path contains "folder1/folder2/folder3" then
- * the given folder will get a subfolder named "folder1". The folder
- * "folder1" itself will get a subfolder named "folder2" and so on.
- *
- * @param FolderType $folder The folder where a subfolder path shall be created.
- * @param User $user The user who wishes to create the path.
- * @param string $path The path which shall be created inside $folder.
- *
- * @return FolderType[] An array with FolderType objects representing
- * each element of $path.
- */
- public static function createFolderPath(FolderType $folder, User $user, $path = '')
- {
- if (!$path) {
- return [];
- }
-
- // now we strip leading and trailing slashes, whitespaces and other characters:
- // then we convert path into an array of strings:
- $path = trim($path, ' /');
- $path = explode('/', $path);
-
- //now we loop through path and build subfolders:
- $folder_path = [];
-
- $current_folder = $folder;
- foreach ($path as $new_folder_name) {
- //first we check if the folder already exists:
- foreach ($current_folder->getSubfolders() as $subfolder) {
- if ($subfolder->name === $new_folder_name) {
- //We have found a folder that has the name $new_folder_name:
- //No need to create a new folder, we can use that folder
- //and continue with it:
- $current_folder = $subfolder;
- $folder_path[] = $subfolder;
-
- //start next iteration of the outer foreach loop:
- continue 2;
- }
- }
-
- //If code execution has reached this point we have looped
- //throug all subfolders of the current folder and couldn't find
- //any subfolder that matches the name given in $new_folder_name.
- //Therefore we must create a new folder here, if possible:
-
- //Check the user's permissions first:
- if ($current_folder->isSubfolderAllowed($user->id)) {
- //Create a subfolder:
- $result = FileManager::createSubFolder(
- $current_folder,
- $user,
- get_class($current_folder) === RootFolder::class ? StandardFolder::class : get_class($current_folder),
- $new_folder_name
- );
-
- if ($result instanceof FolderType) {
- $folder_path[] = $result;
- }
- }
- }
- return $folder_path;
- }
-
- /**
- * Extracts one file from an opened archive and stores it in a folder.
- *
- * @param ZipArchive $archive The archive from which a file shall be extracted.
- * @param string $archive_path The path of the file in the archive.
- * @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 FileType|null FileType instance on success, null otherwise.
- */
- public static function extractFileFromArchive(
- Studip\ZipArchive $archive,
- $archive_path,
- FolderType $target_folder,
- User $user
- )
- {
- $file_resource = $archive->getStream($archive_path);
- $file_info = $archive->statName($archive_path);
-
- if (!$file_resource) {
- return null;
- }
-
- $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_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_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_path, $file_resource) === false) {
- //Something went wrong: abort and clean up!
- //$file->delete();
- return null;
- }
-
- // Ok, we now must create a File:
- $file_ref = new FileRef();
- $file_ref->file_id = $studip_file->id;
- $file_ref->folder_id = $target_folder->getId();
- $file_ref->user_id = $user->id;
- $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:
- return null;
- }
-
- /**
- * Extracts an archive into a folder inside the Stud.IP file area.
- *
- * @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 FileType[] Array with extracted files, represented as FileRef objects.
- */
- public static function extractArchiveFileToFolder(
- FileType $archive_file,
- FolderType $folder,
- $user_id = null
- )
- {
- $user = $user_id ? User::find($user_id) : User::findCurrent();
- if (!$user) {
- return [];
- }
-
- // Determine, if the folder is writable for the user identified by $user_id:
- if (!$folder->isWritable($user->id)) {
- return [];
- }
-
- // Determine if we can keep the zip archive's folder hierarchy:
- $keep_hierarchy = $folder->isSubfolderAllowed($user->id);
-
- $archive = new Studip\ZipArchive();
- $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:
- $files = [];
-
- for ($i = 0; $i < $archive->numFiles; $i++) {
- $entry_info = $archive->statIndex($i);
- $entry_info_name = $archive->convertArchiveFilename($entry_info['name']);
- // split the entry's path into its path and its name component:
- $entry_path = ltrim(pathinfo($entry_info_name, PATHINFO_DIRNAME), '.');
- $entry_name = pathinfo($entry_info_name, PATHINFO_BASENAME);
-
- // check if $entry_info['name'] ends with a slash:
- // In that case it is a directory entry:
- $entry_is_directory = preg_match('/\/$/', $entry_info_name);
-
- //The folder where the extracted file/folder shall be inserted:
- $extracted_entry_destination_folder = $folder;
-
- if ($keep_hierarchy) {
- //Keep the archive's folder hierarchy:
- //We may have to create subfolders.
- if (basename($entry_path)) {
- //The file/folder doesn't lie in the "top folder" of the archive:
- //Pass the path to createFolderPath and let it generate
- //a folder path before extracting the file:
- $folder_path = self::createFolderPath(
- $folder,
- $user,
- $entry_path
- );
-
- //Get the last element of $folder_path:
- $last_folder_path_element = array_pop($folder_path);
-
- //Compare $extracted_entry_destination_folder's name with the name of the
- //last path item in $file_archive_path. Only if they are equal
- //we can use that folder to store the file. Otherwise
- //we must continue with the next file entry in the archive:
- if ($last_folder_path_element
- && $last_folder_path_element->name === basename($entry_path))
- {
- $extracted_entry_destination_folder = $last_folder_path_element;
- }
- }
- }
-
- if ($entry_is_directory) {
- //We have to create a subfolder if it doesn't exist yet:
- self::createFolderPath(
- $extracted_entry_destination_folder,
- $user,
- $entry_name
- );
- } else {
- //we extract one file:
- //$entry_info['name'] is necessary because we need the full path
- //to the entry inside the archive.
- $file = self::extractFileFromArchive(
- $archive,
- $entry_info['name'],
- $extracted_entry_destination_folder,
- $user
- );
-
- if ($file instanceof FileType) {
- $files[] = $file;
- }
- }
- }
-
- return $files;
- }
-}