diff --git a/lib/testing/generator/component_generator_base.php b/lib/testing/generator/component_generator_base.php index cd3f2194f03..4828f0ea4ea 100644 --- a/lib/testing/generator/component_generator_base.php +++ b/lib/testing/generator/component_generator_base.php @@ -86,4 +86,95 @@ abstract class component_generator_base { \core\session\manager::set_user($user); } + + /** + * Update the instance record, inserting any files that are referenced. + * + * @param stdClass $instance The instance record of the already-created record + * @param stdClass $record The data passed in to create the instance + * @param string $table The table that the data exists in + * @param context $context The context of the instance + * @param string $component The component of the owning plugin + * @param string $filearea The name of the file area + * @param int $targetitemid The itemid to use when saving the files + * @return stdClass The updated instance record + */ + protected function insert_files( + stdClass $instance, + stdClass $record, + string $table, + context $context, + string $component, + string $filearea, + int $targetitemid + ): stdClass { + global $CFG, $DB, $USER; + + $fieldname = "[[files::{$filearea}]]"; + if (!isset($record->$fieldname)) { + return $instance; + } + + preg_match('/\[\[files::(.*)\]\]/', $fieldname, $matches); + if (empty($matches[1])) { + throw new coding_exception('Invalid file field name: ' . $fieldname); + } + + $referencedfieldname = trim($matches[1]); + if (!isset($record->$referencedfieldname)) { + throw new coding_exception("File field '{$fieldname}' references non-existent field '{$referencedfieldname}'"); + } + + $fs = get_file_storage(); + $itemid = file_get_unused_draft_itemid(); + $itemidfieldname = "{$referencedfieldname}[itemid]"; + $record->$itemidfieldname = $itemid; + + $filenames = explode(',', $record->$fieldname); + foreach ($filenames as $filename) { + $filename = trim($filename); + if (!$filename) { + continue; + } + + $explodedfilename = explode('::', $filename, 3); + if (count($explodedfilename) === 2) { + [$sourcefile, $targetfile] = $explodedfilename; + $user = $USER; + } else { + [$sourcefile, $targetfile, $username] = $explodedfilename; + $user = \core_user::get_user_by_username($username); + } + $filepath = "{$CFG->dirroot}/{$sourcefile}"; + if (!file_exists($filepath)) { + throw new coding_exception("File '{$filepath}' does not exist"); + } + $filerecord = [ + 'userid' => $user->id, + 'contextid' => context_user::instance($user->id)->id, + 'component' => 'user', + 'filearea' => 'draft', + 'itemid' => $itemid, + 'filepath' => '/' . dirname($targetfile), + 'filename' => basename($targetfile), + ]; + $fs->create_file_from_pathname($filerecord, $filepath); + } + + $olduser = $USER; + $this->set_user($user); + $instance->$referencedfieldname = file_save_draft_area_files( + $itemid, + $context->id, + $component, + $referencedfieldname, + $targetitemid, + null, + $instance->$referencedfieldname + ); + $this->set_user($olduser); + + $DB->update_record($table, $instance); + return $instance; + } } diff --git a/lib/testing/generator/module_generator.php b/lib/testing/generator/module_generator.php index bb4ef49f11b..2752cffd0bd 100644 --- a/lib/testing/generator/module_generator.php +++ b/lib/testing/generator/module_generator.php @@ -200,6 +200,7 @@ abstract class testing_module_generator extends component_generator_base { 'conditionfieldgroup' => array(), 'conditioncompletiongroup' => array() ); + foreach ($defaults as $key => $value) { if (!isset($moduleinfo->$key)) { $moduleinfo->$key = $value; @@ -277,9 +278,21 @@ abstract class testing_module_generator extends component_generator_base { $moduleinfo = add_moduleinfo($record, $course); // Prepare object to return with additional field cmid. - $instance = $DB->get_record($this->get_modulename(), array('id' => $moduleinfo->instance), '*', MUST_EXIST); + $modulename = $this->get_modulename(); + $instance = $DB->get_record($modulename, ['id' => $moduleinfo->instance], '*', MUST_EXIST); $instance->cmid = $moduleinfo->coursemodule; + // Insert files for the 'intro' file area. + $instance = $this->insert_files( + $instance, + $record, + $modulename, + \context_module::instance($instance->cmid), + "mod_{$modulename}", + 'intro', + 0 + ); + // If the theme was initialised while creating the module instance, something somewhere called an output // function. Rather than leaving this as a hard-to-debug situation, let's make it fail with a clear error. $outputstartedafter = $PAGE->get_where_theme_was_initialised();