diff --git a/externallib.php b/externallib.php
index fd070212c7cd1d3ddf61ed64e4c176ec28e943ce..1e1b8326b5daf896d23e5f79450496e2c62c7f19 100644
--- a/externallib.php
+++ b/externallib.php
@@ -82,7 +82,7 @@ class qtype_moopt_external extends external_api {
$usercontext = context_user::instance($USER->id);
self::validate_context($usercontext);
- $unzipinfo = unzip_task_file_in_draft_area($draftid, $usercontext);
+ $unzipinfo = unzip_task_file_in_file_area($usercontext, 'user', 'draft', $draftid);
if ($unzipinfo == null) {
return ['error' => 'Error extracting zip file'];
} else if (isset($unzipinfo['error'])) {
@@ -92,7 +92,7 @@ class qtype_moopt_external extends external_api {
$taskzipfilename = $unzipinfo['zip'] ?? null;
$keepfilename = $taskzipfilename != null ? $taskzipfilename : $taskxmlfilename;
- $doc = create_domdocument_from_task_xml($usercontext, $draftid, $taskxmlfilename, $taskzipfilename);
+ $doc = create_domdocument_from_task_xml($usercontext, 'user', 'draft', $draftid, $taskxmlfilename, $taskzipfilename);
$namespace = detect_proforma_namespace($doc);
$returnval = array();
@@ -290,7 +290,7 @@ class qtype_moopt_external extends external_api {
}
// Do a little bit of cleanup and remove everything from the file area we extracted.
- remove_all_files_from_draft_area($draftid, $usercontext, $keepfilename);
+ remove_all_files_from_file_area($usercontext, 'user', 'draft', $draftid, $keepfilename);
return $returnval;
}
diff --git a/locallib.php b/locallib.php
index 8280b24d16199cdb5a8753b562e5a395811626bb..c7b30ab45c72c28ab9de8fe7c043a40fcf6e0116 100644
--- a/locallib.php
+++ b/locallib.php
@@ -118,41 +118,43 @@ use qtype_moopt\exceptions\resource_not_found_exception;
use qtype_moopt\utility\communicator\communicator_factory;
use qtype_moopt\utility\proforma_xml\separate_feedback_handler;
-/*
- * Unzips the task zip file in the given draft area into the area
+/**
+ * Unzips the task zip file in the given file area into the area
* moodle doesn't display thrown exceptions, so we handle them as array with key 'error' in calling function
*
- * @param type $draftareaid
- * @param type $usercontext
+ * @param type $context
+ * @param type $component
+ * @param type $filearea
+ * @param type $fileareaid
* @return array the name of the task zip file and the task xml file.
* [
* 'zip' => (string) the name of the zip file, if any (the key 'zip' is optional)
* 'xml' => (string) the name of the xml file (mandatory)
* ]
- * Returns false, if there is no file in the given draft area.
+ * Returns false, if there is no file in the given file area.
*/
-function unzip_task_file_in_draft_area($draftareaid, $usercontext) {
+function unzip_task_file_in_file_area($context, $component, $filearea, $fileareaid) {
global $USER;
$fs = get_file_storage();
// Check if there is only the file we want.
- $area = file_get_draft_area_info($draftareaid, "/");
+ $area = file_get_file_area_info($context->id, $component, $filearea, $fileareaid, "/");
if ($area['filecount'] == 0) {
return false;
} else if ($area['filecount'] > 1 || $area['foldercount'] != 0) {
- $error = 'Only one file is allowed to be in this draft area: A ProFormA-Task as either ZIP or XML file. Check for additional folders as well.';
+ $error = 'Only one file is allowed to be in this file area: A ProFormA-Task as either ZIP or XML file. Check for additional folders as well.';
return array('error' => $error);
}
// Get name of the file.
- $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftareaid);
+ $files = $fs->get_area_files($context->id, $component, $filearea, $fileareaid);
// Get_area_files returns an associative array where the keys are some kind of hash value.
$keys = array_keys($files);
// Index 1 because index 0 is the current directory it seems.
$filename = $files[$keys[1]]->get_filename();
- $file = $fs->get_file($usercontext->id, 'user', 'draft', $draftareaid, "/", $filename);
+ $file = $fs->get_file($context->id, $component, $filearea, $fileareaid, "/", $filename);
// Check file type (it's really only checking the file extension but that is good enough here).
$fileinfo = pathinfo($filename);
@@ -174,13 +176,13 @@ function unzip_task_file_in_draft_area($draftareaid, $usercontext) {
$zipper = get_file_packer('application/zip');
// Find unused name for directory to extract the archive.
- $temppath = $fs->get_unused_dirname($usercontext->id, 'user', 'draft', $draftareaid, "/" . pathinfo($zipfilename,
+ $temppath = $fs->get_unused_dirname($context->id, $component, $filearea, $fileareaid, "/" . pathinfo($zipfilename,
PATHINFO_FILENAME) . '/');
$donotremovedirs = array();
$doremovedirs = array($temppath);
// Extract archive and move all files from $temppath to $filepath.
- if ($file->extract_to_storage($zipper, $usercontext->id, 'user', 'draft', $draftareaid, $temppath, $USER->id)) {
- $extractedfiles = $fs->get_directory_files($usercontext->id, 'user', 'draft', $draftareaid, $temppath, true);
+ if ($file->extract_to_storage($zipper, $context->id, $component, $filearea, $fileareaid, $temppath, $USER->id)) {
+ $extractedfiles = $fs->get_directory_files($context->id, $component, $filearea, $fileareaid, $temppath, true);
$xtemppath = preg_quote($temppath, '|');
foreach ($extractedfiles as $exfile) {
$realpath = preg_replace('|^' . $xtemppath . '|', '/', $exfile->get_filepath());
@@ -188,13 +190,18 @@ function unzip_task_file_in_draft_area($draftareaid, $usercontext) {
// Set the source to the extracted file to indicate that it came from archive.
$exfile->set_source(serialize((object)array('source' => '/')));
}
- if (!$fs->file_exists($usercontext->id, 'user', 'draft', $draftareaid, $realpath, $exfile->get_filename())) {
+ if (!$fs->file_exists($context->id, $component, $filearea, $fileareaid, $realpath, $exfile->get_filename())) {
// File or directory did not exist, just move it.
$exfile->rename($realpath, $exfile->get_filename());
} else if (!$exfile->is_directory()) {
// File already existed, overwrite it.
- repository::overwrite_existing_draftfile($draftareaid, $realpath, $exfile->get_filename(), $exfile->get_filepath(),
- $exfile->get_filename());
+ if ($file = $fs->get_file($context->id, $component, $filearea, $fileareaid, $realpath, $exfile->get_filename())) {
+ if ($tempfile = $fs->get_file($context->id, $component, $filearea, $fileareaid, $exfile->get_filepath(), $exfile->get_filename())) {
+ $file->delete();
+ $fs->create_file_from_storedfile(array('filepath'=>$exfile->get_filepath(), 'filename'=>$exfile->get_filename()), $tempfile);
+ $tempfile->delete();
+ }
+ }
} else {
// Directory already existed, remove temporary dir but make sure we don't remove the existing dir.
$doremovedirs[] = $exfile->get_filepath();
@@ -209,7 +216,7 @@ function unzip_task_file_in_draft_area($draftareaid, $usercontext) {
}
// Remove remaining temporary directories.
foreach (array_diff($doremovedirs, $donotremovedirs) as $filepath) {
- $file = $fs->get_file($usercontext->id, 'user', 'draft', $draftareaid, $filepath, '.');
+ $file = $fs->get_file($context->id, $component, $filearea, $fileareaid, $filepath, '.');
if ($file) {
$file->delete();
}
@@ -224,16 +231,18 @@ function unzip_task_file_in_draft_area($draftareaid, $usercontext) {
}
/**
- * Removes all files and directories from the given draft area except a file with the given file name
+ * Removes all files and directories from the given file area except a file with the given file name
*
- * @param type $draftareaid
- * @param type $user_context
- * @param type $excluded_file_name
+ * @param type $context
+ * @param type $component
+ * @param type $filearea
+ * @param type $fileareaid
+ * @param type $excludedfilename
*/
-function remove_all_files_from_draft_area($draftareaid, $usercontext, $excludedfilename)
+function remove_all_files_from_file_area($context, $component, $filearea, $fileareaid, $excludedfilename)
{
$fs = get_file_storage();
- $files = $fs->get_area_files($usercontext->id, 'user', 'draft', $draftareaid);
+ $files = $fs->get_area_files($context->id, $component, $filearea, $fileareaid);
foreach ($files as $fi) {
if (($fi->is_directory() && $fi->get_filepath() != '/') || ($fi->get_filename() != $excludedfilename &&
$fi->get_filename() != '.')) {
@@ -245,26 +254,28 @@ function remove_all_files_from_draft_area($draftareaid, $usercontext, $excludedf
/**
* Creates a DOMDocument object from the task.xml file in the given file area and returns it.
*
- * @param type $user_context
- * @param type $draftareaid
+ * @param type $context
+ * @param type $component
+ * @param type $filearea
+ * @param type $fileareaid
* @param type $xmlfilename
* @param type $zipfilename (optional, only if user uploaded a zip)
* @return \DOMDocument
* @throws invalid_parameter_exception
*/
-function create_domdocument_from_task_xml($usercontext, $draftareaid, $xmlfilename, $zipfilename)
+function create_domdocument_from_task_xml($context, $component, $filearea, $fileareaid, $xmlfilename, $zipfilename)
{
$fs = get_file_storage();
- $file = $fs->get_file($usercontext->id, 'user', 'draft', $draftareaid, "/", $xmlfilename);
+ $file = $fs->get_file($context->id, $component, $filearea, $fileareaid, "/", $xmlfilename);
if (!$file) {
- remove_all_files_from_draft_area($draftareaid, $usercontext, $zipfilename);
+ remove_all_files_from_file_area($context, $component, $filearea, $fileareaid, $zipfilename);
throw new invalid_parameter_exception('Supplied zip file doesn\'t contain task.xml file.');
}
$doc = new DOMDocument();
if (!$doc->loadXML($file->get_content())) {
- remove_all_files_from_draft_area($draftareaid, $usercontext, $zipfilename);
+ remove_all_files_from_file_area($context, $component, $filearea, $fileareaid, $zipfilename);
throw new invalid_parameter_exception('Error parsing the supplied ' . $xmlfilename . ' file. See server log for details.');
}
@@ -287,7 +298,7 @@ function get_text_content_from_file($usercontext, $draftareaid, $keepfilename, $
$fs = get_file_storage();
$file = $fs->get_file($usercontext->id, 'user', 'draft', $draftareaid, $filepath, $filename);
if (!$file) {
- remove_all_files_from_draft_area($draftareaid, $usercontext, $keepfilename);
+ remove_all_files_from_file_area($usercontext, 'user', 'draft', $draftareaid, $keepfilename);
throw new invalid_parameter_exception('Supplied file doesn\'t contain file ' . $filepath . $filename . '.');
}
@@ -309,14 +320,13 @@ function get_text_content_from_file($usercontext, $draftareaid, $keepfilename, $
if($enc==false){
return null;
} else if($enc!=='UTF-8'){
- $content = mb_convert_encoding($content, 'UTF-8', $enc);
+ $content = mb_convert_encoding($content, 'UTF-8', $enc);
}
}
return $content;
}
-
/**
* Get the stored_file from the file area PROFORMA_TASKXML_FILEAREA, if any.
* @return stored_file|bool the file or false, if not found.
@@ -334,18 +344,61 @@ function get_task_xml_file_from_filearea($question)
}
+/**
+ * @throws stored_file_creation_exception
+ * @throws dml_exception
+ * @throws file_exception
+ * @throws coding_exception
+ * @throws invalid_parameter_exception
+ * @throws Exception
+ */
function save_task_and_according_files($question)
{
global $USER, $DB;
+ $fs = get_file_storage();
+ $context = '';
+ $component = '';
+ $filearea = '';
+ $fileareaid = '';
+ $filesfordb = array();
+ if (property_exists($question, 'taskfile') && !is_null($question->taskfile)) {
+ $context = $question->taskfile['context'];
+ $component = $question->taskfile['component'];
+ $filearea = $question->taskfile['filearea'];
+ $fileareaid = $question->id;
+ $question->taskfileinfo['itemid'] = $fileareaid;
+
+ $fileinfo = [
+ 'contextid' => $context->id,
+ 'component' => $component,
+ 'filearea' => $filearea,
+ 'itemid' => $fileareaid,
+ 'filepath' => $question->taskfile['filepath'],
+ 'filename' => $question->taskfile['filename']
+ ];
+ $fs->create_file_from_string($fileinfo, $question->taskfile['content']);
+
+ $record = new stdClass();
+ $record->questionid = $question->id;
+ $record->fileid = $filearea == PROFORMA_TASKZIP_FILEAREA ? 'task' : 'taskxml';
+ $record->usedbygrader = 0;
+ $record->visibletostudents = 'no';
+ $record->usagebylms = 'download';
+ $record->filepath = '/';
+ $record->filename = $fileinfo['filename'];
+ $record->filearea = $filearea;
+ $filesfordb[] = $record;
- if (!isset($question->proformataskfileupload)) {
+ } else if (isset($question->proformataskfileupload)) {
+ $context = context_user::instance($USER->id);
+ $component = 'user';
+ $filearea = 'draft';
+ $fileareaid = $question->proformataskfileupload;
+ } else {
return;
}
- $draftareaid = $question->proformataskfileupload;
- $usercontext = context_user::instance($USER->id);
-
- $unzipinfo = unzip_task_file_in_draft_area($draftareaid, $usercontext);
+ $unzipinfo = unzip_task_file_in_file_area($context, $component, $filearea, $fileareaid);
if (!$unzipinfo) {
// Seems like no task file was submitted.
return false;
@@ -355,14 +408,35 @@ function save_task_and_according_files($question)
$keepfilename = $taskzipfilename != null ? $taskzipfilename : $taskxmlfilename;
// Copy all extracted files to the corresponding file area.
- file_save_draft_area_files($draftareaid, $question->context->id, COMPONENT_NAME, PROFORMA_ATTACHED_TASK_FILES_FILEAREA,
- $question->id, array('subdirs' => true));
+ if ($filearea == 'draft') {
+ file_save_draft_area_files($fileareaid, $question->context->id, COMPONENT_NAME, PROFORMA_ATTACHED_TASK_FILES_FILEAREA,
+ $question->id, array('subdirs' => true));
+ } else {
+ foreach ($fs->get_area_files($context->id, $component, $filearea, $fileareaid) AS $file) {
+ if ($file->get_filename() != '.' && $file->get_filename() != $taskzipfilename /* Skip taskfile because its already present in the correct filearea*/) {
+ $newfileinfo = array(
+ 'contextid' => $context->id,
+ 'component' => COMPONENT_NAME,
+ 'filearea' => PROFORMA_ATTACHED_TASK_FILES_FILEAREA,
+ 'itemid' => $question->id,
+ 'filepath' => $file->get_filepath(),
+ 'filename' => $file->get_filename()
+ );
+
+ // Check if the file exists.
+ if (!$fs->file_exists($newfileinfo['contextid'], $newfileinfo['component'], $newfileinfo['filearea'], $newfileinfo['itemid'], $newfileinfo['filepath'], $newfileinfo['filename'])) {
+ $createdFile = $fs->create_file_from_storedfile($newfileinfo, $file);
+ if (!$createdFile) {
+ throw new Exception('Could not create task from moodle xml.');
+ }
+ }
+ }
+ }
+ }
- $doc = create_domdocument_from_task_xml($usercontext, $draftareaid, $taskxmlfilename, $taskzipfilename);
+ $doc = create_domdocument_from_task_xml($context, $component, $filearea, $fileareaid, $taskxmlfilename, $taskzipfilename);
$namespace = detect_proforma_namespace($doc);
- $filesfordb = array();
- $fs = get_file_storage();
$embeddedelems = array("embedded-bin-file", "embedded-txt-file");
$attachedelems = array("attached-bin-file", "attached-txt-file");
foreach ($doc->getElementsByTagNameNS($namespace, 'file') as $file) {
@@ -428,30 +502,32 @@ function save_task_and_according_files($question)
}
// Now move the task xml file to the designated area.
- $file = $fs->get_file($question->context->id, COMPONENT_NAME, PROFORMA_ATTACHED_TASK_FILES_FILEAREA, $question->id,
- '/', $taskxmlfilename);
- $newfilerecord = array(
- 'component' => COMPONENT_NAME,
- 'filearea' => PROFORMA_TASKXML_FILEAREA,
- 'itemid' => $question->id,
- 'contextid' => $question->context->id,
- 'filepath' => '/',
- 'filename' => $taskxmlfilename);
- $fs->create_file_from_storedfile($newfilerecord, $file);
- $file->delete();
-
- $record = new stdClass();
- $record->questionid = $question->id;
- $record->fileid = 'taskxml';
- $record->usedbygrader = 0;
- $record->visibletostudents = 'no';
- $record->usagebylms = 'download';
- $record->filepath = '/';
- $record->filename = $taskxmlfilename;
- $record->filearea = PROFORMA_TASKXML_FILEAREA;
- $filesfordb[] = $record;
-
- if ($taskzipfilename != null) {
+ if ($filearea == 'draft' || ($taskzipfilename != null /* Taskxmlfile already present in the correct filearea */)) {
+ $file = $fs->get_file($question->context->id, COMPONENT_NAME, PROFORMA_ATTACHED_TASK_FILES_FILEAREA, $question->id,
+ '/', $taskxmlfilename);
+ $newfilerecord = array(
+ 'component' => COMPONENT_NAME,
+ 'filearea' => PROFORMA_TASKXML_FILEAREA,
+ 'itemid' => $question->id,
+ 'contextid' => $question->context->id,
+ 'filepath' => '/',
+ 'filename' => $taskxmlfilename);
+ $fs->create_file_from_storedfile($newfilerecord, $file);
+ $file->delete();
+
+ $record = new stdClass();
+ $record->questionid = $question->id;
+ $record->fileid = 'taskxml';
+ $record->usedbygrader = 0;
+ $record->visibletostudents = 'no';
+ $record->usagebylms = 'download';
+ $record->filepath = '/';
+ $record->filename = $taskxmlfilename;
+ $record->filearea = PROFORMA_TASKXML_FILEAREA;
+ $filesfordb[] = $record;
+ }
+
+ if ($taskzipfilename != null && $filearea == 'draft' /* Taskzipfile already present in the correct filearea */) {
// Now move the task zip file to the designated area.
$file = $fs->get_file($question->context->id, COMPONENT_NAME, PROFORMA_ATTACHED_TASK_FILES_FILEAREA, $question->id, '/', $taskzipfilename);
$newfilerecord = array(
@@ -480,7 +556,7 @@ function save_task_and_according_files($question)
$DB->insert_records('qtype_moopt_files', $filesfordb);
// Do a little bit of cleanup and remove everything from the file area we extracted.
- remove_all_files_from_draft_area($draftareaid, $usercontext, $keepfilename);
+ remove_all_files_from_file_area($context, $component, $filearea, $fileareaid, $keepfilename);
}
/**
diff --git a/questiontype.php b/questiontype.php
index 0247be815d3040bc48dd041f36094a23fa6b0caa..257f2ec39bd04b35d833cd0e7effc8094e243883 100644
--- a/questiontype.php
+++ b/questiontype.php
@@ -69,14 +69,18 @@ class qtype_moopt extends question_type {
*/
public function save_question_options($question) {
// Convert the combined representation of the graderID to graderName and graderVersion
- $separatedGraderID = get_name_and_version_from_graderid_html_representation($question->graderselect);
- $question->gradername = $separatedGraderID->gradername;
- $question->graderversion = $separatedGraderID->graderversion;
-
- if (!isset($question->internaldescription['text'])) {
- $question->internaldescription = '';
- } else {
- $question->internaldescription = trim($question->internaldescription['text']);
+ if (property_exists($question, 'graderselect') && !is_null($question->graderselect)) {
+ $separatedGraderID = get_name_and_version_from_graderid_html_representation($question->graderselect);
+ $question->gradername = $separatedGraderID->gradername;
+ $question->graderversion = $separatedGraderID->graderversion;
+ }
+
+ if (is_array($question->internaldescription)) {
+ if (!array_key_exists('text', $question->internaldescription) || !isset($question->internaldescription['text'])) {
+ $question->internaldescription = '';
+ } else {
+ $question->internaldescription = trim($question->internaldescription['text']);
+ }
}
parent::save_question_options($question);
@@ -95,7 +99,9 @@ class qtype_moopt extends question_type {
// Store custom settings for free text input fields.
$DB->delete_records('qtype_moopt_freetexts', array('questionid' => $question->id));
- if ($question->{'enablefreetextsubmissions'} && $question->{'enablecustomsettingsforfreetextinputfields'}) {
+
+ if (property_exists($question, 'enablefreetextsubmissions') && $question->{'enablefreetextsubmissions'} &&
+ property_exists($question, 'enablecustomsettingsforfreetextinputfields') && $question->{'enablecustomsettingsforfreetextinputfields'}) {
$maxfts = $question->ftsmaxnumfields;
// make sure this user-entered max num does not exceed the
// original plugin setting from when it was installed and first-time configured
@@ -104,7 +110,7 @@ class qtype_moopt extends question_type {
throw new \coding_exception("Assertion error: user-entered max free text input fields cannot be greater than the plugin's max number setting.");
for ($i = 0; $i < $maxfts; $i++) {
- if ($question->{"enablecustomsettingsforfreetextinputfield$i"}) {
+ if (property_exists($question, "enablecustomsettingsforfreetextinputfield$i") && $question->{"enablecustomsettingsforfreetextinputfield$i"}) {
$data = new stdClass();
$data->questionid = $question->id;
$data->inputindex = $i;
@@ -135,4 +141,135 @@ class qtype_moopt extends question_type {
parent::delete_question($questionid, $contextid);
}
+ /**
+ * Provide export functionality for xml format
+ * @param question object the question object
+ * @param format object the format object so that helper methods can be used
+ * @param extra mixed any additional format specific data that may be passed by the format (see format code for info)
+ * @return string the data to append to the output buffer or false if error
+ */
+ function export_to_xml($question, $format, $extra=null) {
+ global $DB, $COURSE;
+
+ $xml = new XMLWriter();
+ $xml->openMemory();
+ $xml->setIndent(1);
+ $xml->setIndentString(' ');
+
+ /* Add an empty answer-Element because Moodle-Import function expects it */
+ $xml->startElement('answer');
+ $xml->writeAttribute('fraction', 0);
+ $xml->writeElement('text', '');
+ $xml->endElement();
+
+ $fs = get_file_storage();
+ $taskFileRecord = $DB->get_record('qtype_moopt_files', array('questionid' => $question->id, 'fileid' => 'task'));
+ if (!$taskFileRecord) {
+ // taskxml file without zip
+ $taskFileRecord = $DB->get_record('qtype_moopt_files', array('questionid' => $question->id, 'fileid' => 'taskxml'));
+ }
+ $context = context_course::instance($COURSE->id);
+ $taskfile = $fs->get_file($context->id,COMPONENT_NAME, $taskFileRecord->filearea, $question->id, $taskFileRecord->filepath, $taskFileRecord->filename);
+
+ $taskfilename = $taskfile->get_filename();
+ $taskfilepath = $taskfile->get_filepath();
+ $taskfileencoding = 'base64';
+ $taskfilecontentbase64 = base64_encode($taskfile->get_content());
+
+ $xml->startElement('taskfile');
+ $xml->writeAttribute('filearea', $taskFileRecord->filearea);
+ $xml->writeAttribute('name', $taskfilename);
+ $xml->writeAttribute('path', $taskfilepath);
+ $xml->writeAttribute('encoding', $taskfileencoding);
+ $xml->writeRaw($taskfilecontentbase64);
+ $xml->endElement();
+
+ /* Add freetext specific options to export */
+ $customOptionsForAllFreetexts = $DB->get_records('qtype_moopt_freetexts', array('questionid' => $question->id));
+
+ if (count($customOptionsForAllFreetexts) > 0) {
+ $xml->startElement('customsettingsforfreetextinputfields');
+ foreach ($customOptionsForAllFreetexts as $customOptionsForOneFreetext) {
+ $inputindex = $customOptionsForOneFreetext->inputindex;
+ $xml->startElement('field');
+ $xml->writeAttribute('index', $inputindex);
+ $presetfilename = $customOptionsForOneFreetext->presetfilename ? "0" : "1"; //Invert because in the form later "0" means true
+ $xml->writeElement('namesettingsforfreetextinput', $presetfilename);
+ $xml->writeElement('freetextinputfieldname', $customOptionsForOneFreetext->filename);
+ $xml->writeElement('ftsoverwrittenlang', $customOptionsForOneFreetext->ftslang);
+ $xml->writeElement('ftsinitialdisplayrows', $customOptionsForOneFreetext->initialdisplayrows);
+ $xml->startElement('freetextinputfieldtemplate');
+ $xml->writeCdata($customOptionsForOneFreetext->filecontent);
+ $xml->endElement();
+ $xml->endElement();
+ }
+ $xml->endElement();
+ }
+
+ $xmloutput = $xml->outputMemory();
+ $xmloutput .= parent::export_to_xml($question, $format, $extra);
+ return $xmloutput;
+ }
+
+ /**
+ * Provide import functionality for xml format
+ * @param data mixed the segment of data containing the question
+ * @param question object question object processed (so far) by standard import code
+ * @param format object the format object so that helper methods can be used (in particular error() )
+ * @param extra mixed any additional format specific data that may be passed by the format (see format code for info)
+ * @return object question object suitable for save_options() call or false if cannot handle
+ */
+ function import_from_xml($data, $question, $format, $extra=null) {
+ global $COURSE;
+
+ $ret = parent::import_from_xml($data, $question, $format, $extra);
+ $root = $data['#'];
+
+ /* Import Taskfile */
+ if ($ret && array_key_exists('taskfile', $root)) {
+ $taskfileattributes = $root['taskfile'][0]['@'];
+ $taskfilearea = $taskfileattributes['filearea'];
+ $taskfilename = $taskfileattributes['name'];
+ $taskfilepath = $taskfileattributes['path'];
+ $taskfileencoding = $taskfileattributes['encoding'];
+ $taskfileencoded = $root['taskfile'][0]['#'];
+
+ /* Check encoding of */
+ $taskfilecontent = false;
+ if (strtolower($taskfileencoding) == 'base64') {
+ $taskfilecontent = base64_decode($taskfileencoded, true);
+ }
+
+ if (!$taskfilecontent) {
+ throw new InvalidArgumentException("The taskfile could not be encoded from moodle xml.");
+ }
+
+ $context = context_course::instance($COURSE->id);
+
+ $taskfileinfo = [
+ 'context' => $context,
+ 'component' => COMPONENT_NAME,
+ 'filearea' => $taskfilearea,
+ 'filepath' => $taskfilepath,
+ 'filename' => $taskfilename,
+ 'content' => $taskfilecontent
+ ]; // Only save the taskfile information here and save the file later because question id is unknown until later
+ $ret->taskfile = $taskfileinfo;
+ }
+
+ /* Import custom settings for FreetextInputFields */
+ if ($ret && array_key_exists('customsettingsforfreetextinputfields', $root)) {
+ $ret->{'enablecustomsettingsforfreetextinputfields'} = true;
+ $customsettingsforfreetextinputfields = $root['customsettingsforfreetextinputfields'][0]['#']['field'];
+ foreach ($customsettingsforfreetextinputfields AS $field) {
+ $inputIndex = $field['@']['index'];
+ $ret->{'enablecustomsettingsforfreetextinputfield' . $inputIndex} = true;
+ $options = $field['#'];
+ foreach ($options AS $option => $optionValue) {
+ $ret->{$option . $inputIndex} = $optionValue[0]['#'];
+ }
+ }
+ }
+ return $ret;
+ }
}