1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 /** 17 * Contains the import_strategy_file class. 18 * 19 * @package tool_moodlenet 20 * @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com> 21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 */ 23 namespace tool_moodlenet\local; 24 25 use core\antivirus\manager as avmanager; 26 27 /** 28 * The import_strategy_file class. 29 * 30 * The import_strategy_file objects contains the setup steps needed to prepare a resource for import as a file into Moodle. This 31 * ensures the remote_resource is first downloaded and put in a draft file area, ready for use as a file by the handling module. 32 * 33 * @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com> 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class import_strategy_file implements import_strategy { 37 38 /** 39 * Get an array of import_handler_info objects representing modules supporting import of this file type. 40 * 41 * @param array $registrydata the fully populated registry. 42 * @param remote_resource $resource the remote resource. 43 * @return import_handler_info[] the array of import_handler_info objects. 44 */ 45 public function get_handlers(array $registrydata, remote_resource $resource): array { 46 $handlers = []; 47 foreach ($registrydata['files'] as $index => $items) { 48 foreach ($items as $item) { 49 if ($index === $resource->get_extension() || $index === '*') { 50 $handlers[] = new import_handler_info($item['module'], $item['message'], $this); 51 } 52 } 53 } 54 return $handlers; 55 } 56 57 /** 58 * Import the remote resource according to the rules of this strategy. 59 * 60 * @param remote_resource $resource the resource to import. 61 * @param \stdClass $user the user to import on behalf of. 62 * @param \stdClass $course the course into which the remote_resource is being imported. 63 * @param int $section the section into which the remote_resource is being imported. 64 * @return \stdClass the module data. 65 * @throws \moodle_exception if the file size means the upload limit is exceeded for the user. 66 */ 67 public function import(remote_resource $resource, \stdClass $user, \stdClass $course, int $section): \stdClass { 68 // Before starting a potentially lengthy download, try to ensure the file size does not exceed the upload size restrictions 69 // for the user. This is a time saving measure. 70 // This is a naive check, that serves only to catch files if they provide the content length header. 71 // Because of potential content encoding (compression), the stored file will be checked again after download as well. 72 $size = $resource->get_download_size() ?? -1; 73 $useruploadlimit = $this->get_user_upload_limit($user, $course); 74 if ($this->size_exceeds_upload_limit($size, $useruploadlimit)) { 75 throw new \moodle_exception('uploadlimitexceeded', 'tool_moodlenet', '', ['filesize' => $size, 76 'uploadlimit' => $useruploadlimit]); 77 } 78 79 // Download the file into a request directory and scan it. 80 [$filepath, $filename] = $resource->download_to_requestdir(); 81 avmanager::scan_file($filepath, $filename, true); 82 83 // Check the final size of file against the user upload limits. 84 $localsize = filesize(sprintf('%s/%s', $filepath, $filename)); 85 if ($this->size_exceeds_upload_limit($localsize, $useruploadlimit)) { 86 throw new \moodle_exception('uploadlimitexceeded', 'tool_moodlenet', '', ['filesize' => $localsize, 87 'uploadlimit' => $useruploadlimit]); 88 } 89 90 // Store in the user draft file area. 91 $storedfile = $this->create_user_draft_stored_file($user, $filename, $filepath); 92 93 // Prepare the data to be sent to the modules dndupload_handle hook. 94 return $this->prepare_module_data($course, $resource, $storedfile->get_itemid()); 95 } 96 97 98 /** 99 * Creates the data to pass to the dndupload_handle() hooks. 100 * 101 * @param \stdClass $course the course record. 102 * @param remote_resource $resource the resource being imported as a file. 103 * @param int $draftitemid the itemid of the draft file. 104 * @return \stdClass the data object. 105 */ 106 protected function prepare_module_data(\stdClass $course, remote_resource $resource, int $draftitemid): \stdClass { 107 $data = new \stdClass(); 108 $data->type = 'Files'; 109 $data->course = $course; 110 $data->draftitemid = $draftitemid; 111 $data->displayname = $resource->get_name(); 112 return $data; 113 } 114 115 /** 116 * Get the max file size limit for the user in the course. 117 * 118 * @param \stdClass $user the user to check. 119 * @param \stdClass $course the course to check in. 120 * @return int the file size limit, in bytes. 121 */ 122 protected function get_user_upload_limit(\stdClass $user, \stdClass $course): int { 123 return get_user_max_upload_file_size(\context_course::instance($course->id), get_config('core', 'maxbytes'), 124 $course->maxbytes, 0, $user); 125 } 126 127 /** 128 * Does the size exceed the upload limit for the current import, taking into account user and core settings. 129 * 130 * @param int $sizeinbytes the size, in bytes. 131 * @param int $useruploadlimit the upload limit, in bytes. 132 * @return bool true if exceeded, false otherwise. 133 * @throws \dml_exception 134 */ 135 protected function size_exceeds_upload_limit(int $sizeinbytes, int $useruploadlimit): bool { 136 if ($useruploadlimit != USER_CAN_IGNORE_FILE_SIZE_LIMITS && $sizeinbytes > $useruploadlimit) { 137 return true; 138 } 139 return false; 140 } 141 142 /** 143 * Create a file in the user drafts ready for use by plugins implementing dndupload_handle(). 144 * 145 * @param \stdClass $user the user object. 146 * @param string $filename the name of the file on disk 147 * @param string $path the path where the file is stored on disk 148 * @return \stored_file 149 */ 150 protected function create_user_draft_stored_file(\stdClass $user, string $filename, string $path): \stored_file { 151 global $CFG; 152 153 $record = new \stdClass(); 154 $record->filearea = 'draft'; 155 $record->component = 'user'; 156 $record->filepath = '/'; 157 $record->itemid = file_get_unused_draft_itemid(); 158 $record->license = $CFG->sitedefaultlicense; 159 $record->author = ''; 160 $record->filename = clean_param($filename, PARAM_FILE); 161 $record->contextid = \context_user::instance($user->id)->id; 162 $record->userid = $user->id; 163 164 $fullpathwithname = sprintf('%s/%s', $path, $filename); 165 166 $fs = get_file_storage(); 167 168 return $fs->create_file_from_pathname($record, $fullpathwithname); 169 } 170 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body