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_processor 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 /** 26 * The import_processor class. 27 * 28 * The import_processor objects provide a means to import a remote resource into a course section, delegating the handling of 29 * content to the relevant module, via its dndupload_handler callback. 30 * 31 * @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com> 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class import_processor { 35 36 /** @var object The course that we are uploading to */ 37 protected $course = null; 38 39 /** @var int The section number we are uploading to */ 40 protected $section = null; 41 42 /** @var import_handler_registry $handlerregistry registry object to use for cross checking the supplied handler.*/ 43 protected $handlerregistry; 44 45 /** @var import_handler_info $handlerinfo information about the module handling the import.*/ 46 protected $handlerinfo; 47 48 /** @var \stdClass $user the user conducting the import.*/ 49 protected $user; 50 51 /** @var remote_resource $remoteresource the remote resource being imported.*/ 52 protected $remoteresource; 53 54 /** @var string[] $descriptionoverrides list of modules which support having their descriptions updated, post-import. */ 55 protected $descriptionoverrides = ['folder', 'page', 'resource', 'scorm', 'url']; 56 57 /** 58 * The import_processor constructor. 59 * 60 * @param \stdClass $course the course object. 61 * @param int $section the section number in the course, starting at 0. 62 * @param remote_resource $remoteresource the remote resource to import. 63 * @param import_handler_info $handlerinfo information about which module is handling the import. 64 * @param import_handler_registry $handlerregistry A registry of import handlers, to use for validation. 65 * @throws \coding_exception If any of the params are invalid. 66 */ 67 public function __construct(\stdClass $course, int $section, remote_resource $remoteresource, import_handler_info $handlerinfo, 68 import_handler_registry $handlerregistry) { 69 70 global $DB, $USER; 71 72 if ($section < 0) { 73 throw new \coding_exception("Invalid section number $section. Must be > 0."); 74 } 75 if (!$DB->record_exists('modules', array('name' => $handlerinfo->get_module_name()))) { 76 throw new \coding_exception("Module {$handlerinfo->get_module_name()} does not exist"); 77 } 78 79 $this->course = $course; 80 $this->section = $section; 81 $this->handlerregistry = $handlerregistry; 82 $this->user = $USER; 83 $this->remoteresource = $remoteresource; 84 $this->handlerinfo = $handlerinfo; 85 86 // ALL handlers must have a strategy and ANY strategy can process ANY resource. 87 // It is therefore NOT POSSIBLE to have a resource that CANNOT be processed by a handler. 88 // So, there's no need to verify that the remote_resource CAN be handled by the handler. It always can. 89 } 90 91 /** 92 * Run the import process, including file download, module creation and cleanup (cache purge, etc). 93 */ 94 public function process(): void { 95 // Allow the strategy to do setup for this file import. 96 $moduledata = $this->handlerinfo->get_strategy()->import($this->remoteresource, $this->user, $this->course, $this->section); 97 98 // Create the course module, and add that information to the data to be sent to the plugin handling the resource. 99 $cmdata = $this->create_course_module($this->course, $this->section, $this->handlerinfo->get_module_name()); 100 $moduledata->coursemodule = $cmdata->id; 101 102 // Now, send the data to the handling plugin to let it set up. 103 $instanceid = plugin_callback('mod', $this->handlerinfo->get_module_name(), 'dndupload', 'handle', [$moduledata], 104 'invalidfunction'); 105 if ($instanceid == 'invalidfunction') { 106 $name = $this->handlerinfo->get_module_name(); 107 throw new \coding_exception("$name does not support drag and drop upload (missing {$name}_dndupload_handle function)"); 108 } 109 110 // Now, update the module description if the module supports it and only if it's not currently set. 111 $this->update_module_description($instanceid); 112 113 // Finish setting up the course module. 114 $this->finish_setup_course_module($instanceid, $cmdata->id); 115 } 116 117 /** 118 * Update the module's description (intro), if that feature is supported. 119 * 120 * @param int $instanceid the instance id of the module to update. 121 */ 122 protected function update_module_description(int $instanceid): void { 123 global $DB, $CFG; 124 require_once($CFG->libdir . '/moodlelib.php'); 125 126 if (plugin_supports('mod', $this->handlerinfo->get_module_name(), FEATURE_MOD_INTRO, true)) { 127 require_once($CFG->libdir . '/editorlib.php'); 128 require_once($CFG->libdir . '/modinfolib.php'); 129 130 $rec = $DB->get_record($this->handlerinfo->get_module_name(), ['id' => $instanceid]); 131 132 if (empty($rec->intro) || in_array($this->handlerinfo->get_module_name(), $this->descriptionoverrides)) { 133 $updatedata = (object)[ 134 'id' => $instanceid, 135 'intro' => clean_param($this->remoteresource->get_description(), PARAM_TEXT), 136 'introformat' => editors_get_preferred_format() 137 ]; 138 139 $DB->update_record($this->handlerinfo->get_module_name(), $updatedata); 140 141 rebuild_course_cache($this->course->id, true); 142 } 143 } 144 } 145 146 /** 147 * Create the course module to hold the file/content that has been uploaded. 148 * @param \stdClass $course the course object. 149 * @param int $section the section. 150 * @param string $modname the name of the module, e.g. 'label'. 151 * @return \stdClass the course module data. 152 */ 153 protected function create_course_module(\stdClass $course, int $section, string $modname): \stdClass { 154 global $CFG; 155 require_once($CFG->dirroot . '/course/modlib.php'); 156 list($module, $context, $cw, $cm, $data) = prepare_new_moduleinfo_data($course, $modname, $section); 157 $data->visible = false; // The module is created in a hidden state. 158 $data->coursemodule = $data->id = add_course_module($data); 159 return $data; 160 } 161 162 /** 163 * Finish off any course module setup, such as adding to the course section and firing events. 164 * 165 * @param int $instanceid id returned by the mod when it was created. 166 * @param int $cmid the course module record id, for removal if something went wrong. 167 */ 168 protected function finish_setup_course_module($instanceid, int $cmid): void { 169 global $DB; 170 171 if (!$instanceid) { 172 // Something has gone wrong - undo everything we can. 173 course_delete_module($cmid); 174 throw new \moodle_exception('errorcreatingactivity', 'moodle', '', $this->handlerinfo->get_module_name()); 175 } 176 177 // Note the section visibility. 178 $visible = get_fast_modinfo($this->course)->get_section_info($this->section)->visible; 179 180 $DB->set_field('course_modules', 'instance', $instanceid, array('id' => $cmid)); 181 182 // Rebuild the course cache after update action. 183 rebuild_course_cache($this->course->id, true); 184 185 course_add_cm_to_section($this->course, $cmid, $this->section); 186 187 set_coursemodule_visible($cmid, $visible); 188 if (!$visible) { 189 $DB->set_field('course_modules', 'visibleold', 1, array('id' => $cmid)); 190 } 191 192 // Retrieve the final info about this module. 193 $info = get_fast_modinfo($this->course, $this->user->id); 194 if (!isset($info->cms[$cmid])) { 195 // The course module has not been properly created in the course - undo everything. 196 course_delete_module($cmid); 197 throw new \moodle_exception('errorcreatingactivity', 'moodle', '', $this->handlerinfo->get_module_name()); 198 } 199 $mod = $info->get_cm($cmid); 200 201 // Trigger course module created event. 202 $event = \core\event\course_module_created::create_from_cm($mod); 203 $event->trigger(); 204 } 205 } 206
title
Description
Body
title
Description
Body
title
Description
Body
title
Body