diff --git a/lib/questionlib.php b/lib/questionlib.php
index dc04838c94c..05183b5e56e 100644
--- a/lib/questionlib.php
+++ b/lib/questionlib.php
@@ -3270,10 +3270,73 @@ function quiz_rewrite_question_urls($text, $file, $contextid, $component, $filea
function question_pluginfile($course, $context, $component, $filearea, $args, $forcedownload) {
global $DB, $CFG;
+ list($context, $course, $cm) = get_context_info_array($context->id);
+ require_login($course, false, $cm);
+
+ if ($filearea === 'export') {
+ require_once($CFG->dirroot . '/question/editlib.php');
+ $contexts = new question_edit_contexts($context);
+ // check export capability
+ $contexts->require_one_edit_tab_cap('export');
+ $category_id = (int)array_shift($args);
+ $format = array_shift($args);
+ $cattofile = array_shift($args);
+ $contexttofile = array_shift($args);
+ $filename = array_shift($args);
+
+ // load parent class for import/export
+ require_once($CFG->dirroot . '/question/format.php');
+ require_once($CFG->dirroot . '/question/editlib.php');
+ require_once($CFG->dirroot . '/question/format/' . $format . '/format.php');
+
+ $classname = 'qformat_' . $format;
+ if (!class_exists($classname)) {
+ send_file_not_found();
+ }
+
+ $qformat = new $classname();
+
+ if (!$category = $DB->get_record('question_categories', array('id' => $category_id))) {
+ send_file_not_found();
+ }
+
+ $qformat->setCategory($category);
+ $qformat->setContexts($contexts->having_one_edit_tab_cap('export'));
+ $qformat->setCourse($course);
+
+ if ($cattofile == 'withcategories') {
+ $qformat->setCattofile(true);
+ } else {
+ $qformat->setCattofile(false);
+ }
+
+ if ($contexttofile == 'withcontexts') {
+ $qformat->setContexttofile(true);
+ } else {
+ $qformat->setContexttofile(false);
+ }
+
+ if (!$qformat->exportpreprocess()) {
+ send_file_not_found();
+ print_error('exporterror', 'question', $thispageurl->out());
+ }
+
+ // export data to moodle file pool
+ if (!$content = $qformat->exportprocess(true)) {
+ send_file_not_found();
+ }
+
+ //DEBUG
+ //echo '';
+ //die;
+ send_file($content, $filename, 0, 0, true, true);
+ }
+
$attemptid = (int)array_shift($args);
$questionid = (int)array_shift($args);
- require_login($course, false);
if ($attemptid === 0) {
// preview
@@ -3321,3 +3384,19 @@ function question_check_file_access($question, $state, $options, $contextid, $co
return $QTYPES[$question->qtype]->check_file_access($question, $state, $options, $contextid, $component,
$filearea, $args, $forcedownload);
}
+
+/**
+ * Create url for question export
+ *
+ * @param int $contextid, current context
+ * @param int $categoryid, categoryid
+ * @param string $format
+ * @param string $withcategories
+ * @param string $ithcontexts
+ * @param moodle_url export file url
+ */
+function question_make_export_url($contextid, $categoryid, $format, $withcategories, $withcontexts) {
+ global $CFG;
+ $urlbase = "$CFG->httpswwwroot/pluginfile.php";
+ return moodle_url::make_file_url($urlbase, "/$contextid/question/export/{$categoryid}/{$format}/{$withcategories}/{$withcontexts}/export.xml", true);
+}
diff --git a/question/export.php b/question/export.php
index fd965af004b..d4772f05ac8 100644
--- a/question/export.php
+++ b/question/export.php
@@ -37,68 +37,30 @@
$PAGE->set_heading($COURSE->fullname);
echo $OUTPUT->header();
- $exportfilename = default_export_filename($COURSE, $category);
- $export_form = new question_export_form($thispageurl, array('contexts'=>$contexts->having_one_edit_tab_cap('export'), 'defaultcategory'=>$pagevars['cat'],
- 'defaultfilename'=>$exportfilename));
+ $export_form = new question_export_form($thispageurl, array('contexts'=>$contexts->having_one_edit_tab_cap('export'), 'defaultcategory'=>$pagevars['cat']));
- if ($from_form = $export_form->get_data()) { /// Filename
-
-
- if (! is_readable("format/$from_form->format/format.php")) {
+ if ($from_form = $export_form->get_data()) {
+ $thiscontext = $contexts->lowest();
+ if (!is_readable("format/$from_form->format/format.php")) {
print_error('unknowformat', '', '', $from_form->format);
}
-
- // load parent class for import/export
- require_once("format.php");
-
- // and then the class for the selected format
- require_once("format/$from_form->format/format.php");
-
- $classname = "qformat_$from_form->format";
- $qformat = new $classname();
- $qformat->setContexts($contexts->having_one_edit_tab_cap('export'));
- $qformat->setCategory($category);
- $qformat->setCourse($COURSE);
-
- if (empty($from_form->exportfilename)) {
- $from_form->exportfilename = default_export_filename($COURSE, $category);
+ $withcategories = 'nocategories';
+ if (!empty($from_form->cattofile)) {
+ $withcategories = 'withcategories';
}
- $qformat->setFilename($from_form->exportfilename);
- $canaccessbackupdata = has_capability('moodle/backup:backupcourse', $contexts->lowest());
- $qformat->set_can_access_backupdata($canaccessbackupdata);
- $qformat->setCattofile(!empty($from_form->cattofile));
- $qformat->setContexttofile(!empty($from_form->contexttofile));
-
- if (! $qformat->exportpreprocess()) { // Do anything before that we need to
- print_error('exporterror', 'question', $thispageurl->out());
+ $withcontexts = 'nocontexts';
+ if (!empty($from_form->contexttofile)) {
+ $withcontexts = 'withcontexts';
}
- if (! $qformat->exportprocess()) { // Process the export data
- print_error('exporterror', 'question', $thispageurl->out());
- }
+ $export_url = question_make_export_url($thiscontext->id, $category->id, $from_form->format, $withcategories, $withcontexts);
- if (! $qformat->exportpostprocess()) { // In case anything needs to be done after
- print_error('exporterror', 'question', $thispageurl->out());
- }
- echo "
";
+ echo $OUTPUT->box_start();
+ echo get_string('yourfileshoulddownload', 'question', $export_url->out());
+ echo $OUTPUT->box_end();
- // link to download the finished file
- $file_ext = $qformat->export_file_extension();
- $filename = $from_form->exportfilename . $file_ext;
- if ($canaccessbackupdata) {
- $efile = get_file_url($qformat->question_get_export_dir() . '/' . $filename,
- array('forcedownload' => 1));
- echo '';
- echo '' .
- get_string('downloadextra', 'quiz') . '
';
- } else {
- $efile = get_file_url($filename, null, 'questionfile');
- echo '' .
- get_string('yourfileshoulddownload', 'question', $efile) . '
';
- $PAGE->requires->js_function_call('document.location.replace', array($efile), false, 1);
- }
+ $PAGE->requires->js_function_call('document.location.replace', array($export_url->out()), false, 1);
echo $OUTPUT->continue_button(new moodle_url('edit.php', $thispageurl->params()));
echo $OUTPUT->footer();
@@ -111,4 +73,3 @@
$export_form->display();
echo $OUTPUT->footer();
-
diff --git a/question/export_form.php b/question/export_form.php
index 3528ed2f2a2..f76a991b6fb 100644
--- a/question/export_form.php
+++ b/question/export_form.php
@@ -13,7 +13,6 @@ class question_export_form extends moodleform {
$defaultcategory = $this->_customdata['defaultcategory'];
$contexts = $this->_customdata['contexts'];
- $defaultfilename = $this->_customdata['defaultfilename'];
//--------------------------------------------------------------------------------
$mform->addElement('header','fileformat',get_string('fileformat','quiz'));
$fileformatnames = get_import_export_formats('export');
@@ -46,10 +45,6 @@ class question_export_form extends moodleform {
// $mform->addElement('select', 'format', get_string('fileformat','quiz'), $fileformatnames);
// $mform->setDefault('format', 'gift');
- $mform->addElement('text', 'exportfilename', get_string('exportname', 'quiz'), array('size'=>40));
- $mform->setDefault('exportfilename', $defaultfilename);
- $mform->setType('exportfilename', PARAM_FILE);
-
// set a template for the format select elements
$renderer =& $mform->defaultRenderer();
$template = "{help} {element}\n";
@@ -60,4 +55,3 @@ class question_export_form extends moodleform {
//--------------------------------------------------------------------------------
}
}
-
diff --git a/question/format.php b/question/format.php
index d8c52be36d0..3748307deef 100644
--- a/question/format.php
+++ b/question/format.php
@@ -27,6 +27,7 @@ class qformat_default {
var $translator = null;
var $canaccessbackupdata = true;
+ protected $importcontext = null;
// functions to indicate import/export functionality
// override to return true if implemented
@@ -225,13 +226,17 @@ class qformat_default {
/**
* Process the file
* This method should not normally be overidden
+ * @param object $context
* @return boolean success
*/
- function importprocess() {
- global $USER, $DB, $OUTPUT;
+ function importprocess($category) {
+ global $USER, $DB, $OUTPUT, $QTYPES;
+
+ $context = $category->context;
+ $this->importcontext = $context;
// reset the timer in case file upload was slow
- @set_time_limit(0);
+ set_time_limit(0);
// STAGE 1: Parse the file
echo $OUTPUT->notification( get_string('parsingquestions','quiz') );
@@ -241,7 +246,7 @@ class qformat_default {
return false;
}
- if (! $questions = $this->readquestions($lines)) { // Extract all the questions
+ if (!$questions = $this->readquestions($lines)) { // Extract all the questions
echo $OUTPUT->notification( get_string('noquestionsinfile','quiz') );
return false;
}
@@ -264,6 +269,7 @@ class qformat_default {
$gradeerrors = 0;
$goodquestions = array();
foreach ($questions as $question) {
+
if (!empty($question->fraction) and (is_array($question->fraction))) {
$fractions = $question->fraction;
$answersvalid = true; // in case they are!
@@ -314,26 +320,35 @@ class qformat_default {
}
continue;
}
+ $question->context = $context;
$count++;
echo "
$count. ".$this->format_question_text($question)."
";
- $question->category = $this->category->id;
+ $question->category = $category->id;
$question->stamp = make_unique_id_code(); // Set the unique code (not to be changed)
$question->createdby = $USER->id;
$question->timecreated = time();
- $question->id = $DB->insert_record("question", $question);
+ $question->id = $DB->insert_record('question', $question);
+ if (isset($question->questiontextfiles)) {
+ foreach ($question->questiontextfiles as $file) {
+ $QTYPES[$question->qtype]->import_file($context, 'question', 'questiontext', $question->id, $file);
+ }
+ }
+ if (isset($question->generalfeedbackfiles)) {
+ foreach ($question->generalfeedbackfiles as $file) {
+ $QTYPES[$question->qtype]->import_file($context, 'question', 'generalfeedback', $question->id, $file);
+ }
+ }
$this->questionids[] = $question->id;
// Now to save all the answers and type-specific options
- global $QTYPES;
- $result = $QTYPES[$question->qtype]
- ->save_question_options($question);
+ $result = $QTYPES[$question->qtype]->save_question_options($question);
if (!empty($result->error)) {
echo $OUTPUT->notification($result->error);
@@ -455,9 +470,10 @@ class qformat_default {
* then you will need to override this method. Even then
* try to use readquestion for each question
* @param array lines array of lines from readdata
+ * @param object $context
* @return array array of question objects
*/
- function readquestions($lines) {
+ function readquestions($lines, $context) {
$questions = array();
$currentquestion = array();
@@ -477,7 +493,7 @@ class qformat_default {
}
if (!empty($currentquestion)) { // There may be a final question
- if ($question = $this->readquestion($currentquestion)) {
+ if ($question = $this->readquestion($currentquestion, $context)) {
$questions[] = $question;
}
}
@@ -548,50 +564,6 @@ class qformat_default {
return true;
}
- /**
- * Import an image file encoded in base64 format
- * @param string path path (in course data) to store picture
- * @param string base64 encoded picture
- * @return string filename (nb. collisions are handled)
- */
- function importimagefile( $path, $base64 ) {
- global $CFG;
-
- //TODO: MDL-16094
- throw new coding_exception('importimagefile() was not converted to new file api yet, sorry - see MDL-16094');
-
- // all this to get the destination directory
- // and filename!
- $fullpath = "{$CFG->dataroot}/{$this->course->id}/$path";
- $path_parts = pathinfo( $fullpath );
- $destination = $path_parts['dirname'];
- $file = clean_filename( $path_parts['basename'] );
-
- // check if path exists
- check_dir_exists($destination, true, true );
-
- // detect and fix any filename collision - get unique filename
- $newfiles = resolve_filename_collisions( $destination, array($file) );
- $newfile = $newfiles[0];
-
- // convert and save file contents
- if (!$content = base64_decode( $base64 )) {
- return '';
- }
- $newfullpath = "$destination/$newfile";
- if (!$fh = fopen( $newfullpath, 'w' )) {
- return '';
- }
- if (!fwrite( $fh, $content )) {
- return '';
- }
- fclose( $fh );
-
- // return the (possibly) new filename
- $newfile = preg_replace("~{$CFG->dataroot}/{$this->course->id}/~", '',$newfullpath);
- return $newfile;
- }
-
/*******************
* EXPORT FUNCTIONS
@@ -654,26 +626,20 @@ class qformat_default {
/**
* Do the export
* For most types this should not need to be overrided
- * @return boolean success
+ * @return stored_file
*/
function exportprocess() {
- global $CFG, $OUTPUT;
-
- // create a directory for the exports (if not already existing)
- if (! $export_dir = make_upload_directory($this->question_get_export_dir())) {
- print_error('cannotcreatepath', 'quiz', $export_dir);
- }
- $path = $CFG->dataroot.'/'.$this->question_get_export_dir();
+ global $CFG, $OUTPUT, $DB, $USER;
// get the questions (from database) in this category
// only get q's with no parents (no cloze subquestions specifically)
- if ($this->category){
+ if ($this->category) {
$questions = get_questions_category( $this->category, true );
} else {
$questions = $this->questions;
}
- echo $OUTPUT->notification( get_string('exportingquestions','quiz') );
+ //echo $OUTPUT->notification( get_string('exportingquestions','quiz') );
$count = 0;
// results are first written into string (and then to a file)
@@ -685,8 +651,13 @@ class qformat_default {
// file if selected. 0 means that it will get printed before the 1st question
$trackcategory = 0;
+ $fs = get_file_storage();
+
// iterate through questions
foreach($questions as $question) {
+ // used by file api
+ $contextid = $DB->get_field('question_categories', 'contextid', array('id'=>$question->category));
+ $question->contextid = $contextid;
// do not export hidden questions
if (!empty($question->hidden)) {
@@ -711,15 +682,35 @@ class qformat_default {
$dummyquestion->name = 'Switch category to ' . $categoryname;
$dummyquestion->id = 0;
$dummyquestion->questiontextformat = '';
+ $dummyquestion->contextid = 0;
$expout .= $this->writequestion($dummyquestion) . "\n";
}
}
// export the question displaying message
$count++;
- echo "
$count. ".$this->format_question_text($question)."
";
- if (question_has_capability_on($question, 'view', $question->category)){
- $expout .= $this->writequestion( $question ) . "\n";
+
+ //echo '
';
+ //echo $OUTPUT->container_start();
+ //echo '' . $count . '. ';
+ //echo $this->format_question_text($question);
+ //echo $OUTPUT->container_end();
+
+ if (question_has_capability_on($question, 'view', $question->category)) {
+ // files used by questiontext
+ $files = $fs->get_area_files($contextid, 'question', 'questiontext', $question->id);
+ $question->questiontextfiles = $files;
+ // files used by generalfeedback
+ $files = $fs->get_area_files($contextid, 'question', 'generalfeedback', $question->id);
+ $question->generalfeedbackfiles = $files;
+ if (!empty($question->options->answers)) {
+ foreach ($question->options->answers as $answer) {
+ $files = $fs->get_area_files($contextid, 'question', 'answerfeedback', $answer->id);
+ $answer->feedbackfiles = $files;
+ }
+ }
+
+ $expout .= $this->writequestion($question, $contextid) . "\n";
}
}
@@ -733,18 +724,8 @@ class qformat_default {
}
// final pre-process on exported data
- $expout = $this->presave_process( $expout );
-
- // write file
- $filepath = $path."/".$this->filename . $this->export_file_extension();
- if (!$fh=fopen($filepath,"w")) {
- print_error( 'cannotopen','quiz',$continuepath,$filepath );
- }
- if (!fwrite($fh, $expout, strlen($expout) )) {
- print_error( 'cannotwrite','quiz',$continuepath,$filepath );
- }
- fclose($fh);
- return true;
+ $expout = $this->presave_process($expout);
+ return $expout;
}
/**
@@ -876,4 +857,30 @@ class qformat_default {
$text = $question->questiontext;
return format_text(html_to_text($text), $format, $formatoptions);
}
+
+ /**
+ * convert files into text output in the given format.
+ * @param array
+ * @param string encoding method
+ * @return string $string
+ */
+ function writefiles($files, $encoding='base64') {
+ if (empty($files)) {
+ return '';
+ }
+ $string = '';
+ foreach ($files as $file) {
+ if ($file->is_directory()) {
+ continue;
+ }
+ $string .= 'get_filename() . '"');
+ $string .= (' encoding="' . $encoding . '"');
+ $string .= '>';
+ $string .= base64_encode($file->get_content());
+ //$string .= 'base64';
+ $string .= '';
+ }
+ return $string;
+ }
}
diff --git a/question/format/xml/format.php b/question/format/xml/format.php
index b5a3b91d627..a922d03502d 100755
--- a/question/format/xml/format.php
+++ b/question/format/xml/format.php
@@ -116,7 +116,7 @@ class qformat_xml extends qformat_default {
* @param string error if set value must exist, return false and issue message if not
* @return mixed value
*/
- function getpath( $xml, $path, $default, $istext=false, $error='' ) {
+ function getpath($xml, $path, $default, $istext=false, $error='') {
foreach ($path as $index) {
if (!isset($xml[$index])) {
if (!empty($error)) {
@@ -132,7 +132,7 @@ class qformat_xml extends qformat_default {
if (!is_string($xml)) {
$this->error( get_string('invalidxml','qformat_xml') );
}
- $xml = trim( $xml );
+ $xml = trim($xml);
}
return $xml;
@@ -144,25 +144,49 @@ class qformat_xml extends qformat_default {
* @param $question array question question array from xml tree
* @return object question object
*/
- function import_headers( $question ) {
+ function import_headers($question) {
// get some error strings
- $error_noname = get_string( 'xmlimportnoname','quiz' );
- $error_noquestion = get_string( 'xmlimportnoquestion','quiz' );
+ $error_noname = get_string('xmlimportnoname','quiz');
+ $error_noquestion = get_string('xmlimportnoquestion','quiz');
// this routine initialises the question object
$qo = $this->defaultquestion();
// question name
$qo->name = $this->getpath( $question, array('#','name',0,'#','text',0,'#'), '', true, $error_noname );
- $qo->questiontext = $this->getpath( $question, array('#','questiontext',0,'#','text',0,'#'), '', true );
- $qo->questiontextformat = $this->trans_format($this->getpath(
- $question, array('#','questiontext',0,'@','format'), ''));
- $qo->image = $this->getpath( $question, array('#','image',0,'#'), $qo->image );
+ $qo->questiontext = $this->getpath($question, array('#','questiontext',0,'#','text',0,'#'), '', true );
+ $qo->questiontextformat = $this->trans_format($this->getpath($question, array('#','questiontext',0,'@','format'), ''));
+ $qo->image = $this->getpath($question, array('#','image',0,'#'), $qo->image );
$image_base64 = $this->getpath( $question, array('#','image_base64','0','#'),'' );
if (!empty($image_base64)) {
- $qo->image = $this->importimagefile( $qo->image, $image_base64);
+ $qo->image = $this->importimagefile($qo->image, $image_base64);
}
- $qo->generalfeedback = $this->getpath( $question, array('#','generalfeedback',0,'#','text',0,'#'), $qo->generalfeedback, true );
+
+ $qo->questiontextfiles = array();
+
+ // restore files in questiontext
+ $files = $this->getpath($question, array('#', 'questiontext', 0, '#','file'), array(), false);
+ foreach ($files as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->encoding = $file['@']['encoding'];
+ $data->name = $file['@']['name'];
+ $qo->questiontextfiles[] = $data;
+ }
+
+ // restore files in generalfeedback
+ $qo->generalfeedback = $this->getpath($question, array('#','generalfeedback',0,'#','text',0,'#'), $qo->generalfeedback, true);
+ $qo->generalfeedbackfiles = array();
+ $qo->generalfeedbackformat = $this->trans_format($this->getpath($question, array('#', 'generalfeedback', 0, '@', 'format'), ''));
+ $files = $this->getpath($question, array('#', 'generalfeedback', 0, '#', 'file'), array(), false);
+ foreach ($files as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->encoding = $file['@']['encoding'];
+ $data->name = $file['@']['name'];
+ $qo->generalfeedbackfiles[] = $data;
+ }
+
$qo->defaultgrade = $this->getpath( $question, array('#','defaultgrade',0,'#'), $qo->defaultgrade );
$qo->penalty = $this->getpath( $question, array('#','penalty',0,'#'), $qo->penalty );
@@ -174,15 +198,45 @@ class qformat_xml extends qformat_default {
* @param array answer xml tree for single answer
* @return object answer object
*/
- function import_answer( $answer ) {
- $fraction = $this->getpath( $answer, array('@','fraction'),0 );
- $text = $this->getpath( $answer, array('#','text',0,'#'), '', true );
- $feedback = $this->getpath( $answer, array('#','feedback',0,'#','text',0,'#'), '', true );
+ function import_answer($answer) {
+ $fraction = $this->getpath($answer, array('@', 'fraction'), 0);
+ $answertext = $this->getpath($answer, array('#', 'text', 0, '#'), '', true);
+ $answerformat = $this->trans_format($this->getpath($answer, array('#', 'text', 0, '#'), ''));
+ $answerfiles = array();
+ $files = $this->getpath($answer, array('#', 'answer', 0, '#', 'file'), array());
+ foreach ($files as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->name = $file['@']['name'];
+ $data->encoding = $file['@']['encoding'];
+ $answerfiles[] = $data;
+ }
+
+ $feedbacktext = $this->getpath($answer, array('#', 'feedback', 0, '#', 'text', 0, '#'), '', true);
+ $feedbackformat = $this->trans_format($this->getpath($answer, array('#', 'feedback', 0, '@', 'format'), ''));
+ $feedbackfiles = array();
+ $files = $this->getpath($answer, array('#', 'feedback', 0, '#', 'file'), array());
+ foreach ($files as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->name = $file['@']['name'];
+ $data->encoding = $file['@']['encoding'];
+ $feedbackfiles[] = $data;
+ }
+
+ $ans = new stdclass;
+
+ $ans->answer = array();
+ $ans->answer['text'] = $answertext;
+ $ans->answer['format'] = $answerformat;
+ $ans->answer['files'] = $answerfiles;
+
+ $ans->feedback = array();
+ $ans->feedback['text'] = $feedbacktext;
+ $ans->feedback['format'] = $feedbackformat;
+ $ans->feedback['files'] = $feedbackfiles;
- $ans = null;
- $ans->answer = $text;
$ans->fraction = $fraction / 100;
- $ans->feedback = $feedback;
return $ans;
}
@@ -191,9 +245,9 @@ class qformat_xml extends qformat_default {
* @param array question question array from xml tree
* @return object question object
*/
- function import_multichoice( $question ) {
+ function import_multichoice($question) {
// get common parts
- $qo = $this->import_headers( $question );
+ $qo = $this->import_headers($question);
// 'header' parts particular to multichoice
$qo->qtype = MULTICHOICE;
@@ -202,9 +256,48 @@ class qformat_xml extends qformat_default {
$shuffleanswers = $this->getpath( $question, array('#','shuffleanswers',0,'#'), 'false' );
$qo->answernumbering = $this->getpath( $question, array('#','answernumbering',0,'#'), 'abc' );
$qo->shuffleanswers = $this->trans_single($shuffleanswers);
- $qo->correctfeedback = $this->getpath( $question, array('#','correctfeedback',0,'#','text',0,'#'), '', true );
- $qo->partiallycorrectfeedback = $this->getpath( $question, array('#','partiallycorrectfeedback',0,'#','text',0,'#'), '', true );
- $qo->incorrectfeedback = $this->getpath( $question, array('#','incorrectfeedback',0,'#','text',0,'#'), '', true );
+
+ $qo->correctfeedback = array();
+ $qo->correctfeedback['text'] = $this->getpath($question, array('#', 'correctfeedback', 0, '#', 'text', 0, '#'), '', true);
+ $qo->correctfeedback['format'] = $this->trans_format($this->getpath($question, array('#', 'correctfeedback', 0, '@', 'format'), ''));
+ $qo->correctfeedback['files'] = array();
+ // restore files in correctfeedback
+ $files = $this->getpath($question, array('#', 'correctfeedback', 0, '#','file'), array(), false);
+ foreach ($files as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->encoding = $file['@']['encoding'];
+ $data->name = $file['@']['name'];
+ $qo->correctfeedback['files'][] = $data;
+ }
+
+ $qo->partiallycorrectfeedback = array();
+ $qo->partiallycorrectfeedback['text'] = $this->getpath( $question, array('#','partiallycorrectfeedback',0,'#','text',0,'#'), '', true );
+ $qo->partiallycorrectfeedback['format'] = $this->trans_format($this->getpath($question, array('#', 'partiallycorrectfeedback', 0, '@', 'format'), ''));
+ $qo->partiallycorrectfeedback['files'] = array();
+ // restore files in partiallycorrectfeedback
+ $files = $this->getpath($question, array('#', 'partiallycorrectfeedback', 0, '#','file'), array(), false);
+ foreach ($files as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->encoding = $file['@']['encoding'];
+ $data->name = $file['@']['name'];
+ $qo->partiallycorrectfeedback['files'][] = $data;
+ }
+
+ $qo->incorrectfeedback = array();
+ $qo->incorrectfeedback['text'] = $this->getpath( $question, array('#','incorrectfeedback',0,'#','text',0,'#'), '', true );
+ $qo->incorrectfeedback['format'] = $this->trans_format($this->getpath($question, array('#', 'incorrectfeedback', 0, '@', 'format'), ''));
+ $qo->incorrectfeedback['files'] = array();
+ // restore files in incorrectfeedback
+ $files = $this->getpath($question, array('#', 'incorrectfeedback', 0, '#','file'), array(), false);
+ foreach ($files as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->encoding = $file['@']['encoding'];
+ $data->name = $file['@']['name'];
+ $qo->incorrectfeedback['files'][] = $data;
+ }
// There was a time on the 1.8 branch when it could output an empty answernumbering tag, so fix up any found.
if (empty($qo->answernumbering)) {
@@ -215,12 +308,13 @@ class qformat_xml extends qformat_default {
$answers = $question['#']['answer'];
$a_count = 0;
foreach ($answers as $answer) {
- $ans = $this->import_answer( $answer );
+ $ans = $this->import_answer($answer);
$qo->answer[$a_count] = $ans->answer;
$qo->fraction[$a_count] = $ans->fraction;
$qo->feedback[$a_count] = $ans->feedback;
++$a_count;
}
+
return $qo;
}
@@ -268,7 +362,17 @@ class qformat_xml extends qformat_default {
$warning = false;
foreach ($question['#']['answer'] as $answer) {
$answertext = $this->getpath( $answer, array('#','text',0,'#'), '', true );
- $feedback = $this->getpath($answer, array('#','feedback',0,'#','text',0,'#'), '', true );
+ $feedback = $this->getpath($answer, array('#','feedback',0,'#','text',0,'#'), '', true);
+ $feedbackformat = $this->getpath($answer, array('#','feedback',0, '@', 'format'), '', true);
+ $feedbackfiles = $this->getpath($answer, array('#', 'feedback', 0, '#', 'file'), array(), false);
+ $files = array();
+ foreach ($feedbackfiles as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->encoding = $file['@']['encoding'];
+ $data->name = $file['@']['name'];
+ $files[] = $data;
+ }
if ($answertext != 'true' && $answertext != 'false') {
$warning = true;
$answertext = $first ? 'true' : 'false'; // Old style file, assume order is true/false.
@@ -276,11 +380,19 @@ class qformat_xml extends qformat_default {
if ($answertext == 'true') {
$qo->answer = ($answer['@']['fraction'] == 100);
$qo->correctanswer = $qo->answer;
- $qo->feedbacktrue = $feedback;
+ $qo->feedbacktrue = array();
+ $qo->feedbacktrue['text'] = $feedback;
+ $qo->feedbacktrue['format'] = $this->trans_format($feedbackformat);
+ $qo->feedbacktrue['itemid'] = null;
+ $qo->feedbacktruefiles = $files;
} else {
$qo->answer = ($answer['@']['fraction'] != 100);
$qo->correctanswer = $qo->answer;
- $qo->feedbackfalse = $feedback;
+ $qo->feedbackfalse = array();
+ $qo->feedbackfalse['text'] = $feedback;
+ $qo->feedbackfalse['format'] = $this->trans_format($feedbackformat);
+ $qo->feedbackfalse['itemid'] = null;
+ $qo->feedbackfalsefiles = $files;
}
$first = false;
}
@@ -358,12 +470,12 @@ class qformat_xml extends qformat_default {
$qo->tolerance = array();
foreach ($answers as $answer) {
// answer outside of is deprecated
- $answertext = trim( $this->getpath( $answer, array('#',0), '' ) );
- $qo->answer[] = $this->getpath( $answer, array('#','text',0,'#'), $answertext, true );
+ $obj = $this->import_answer($answer);
+ $qo->answer[] = $obj->answer;
if (empty($qo->answer)) {
$qo->answer = '*';
}
- $qo->feedback[] = $this->getpath( $answer, array('#','feedback',0,'#','text',0,'#'), '', true );
+ $qo->feedback[] = $obj->feedback;
$qo->tolerance[] = $this->getpath( $answer, array('#','tolerance',0,'#'), 0 );
// fraction as a tag is deprecated
@@ -381,6 +493,21 @@ class qformat_xml extends qformat_default {
$qo->unit[] = $this->getpath( $unit, array('#','unit_name',0,'#'), '', true );
}
}
+ $instructions = $this->getpath($question, array('#', 'instructions'), array());
+ if (!empty($instructions)) {
+ $qo->instructions = array();
+ $qo->instructions['text'] = $instructions[0]['#']['text'][0]['#'];
+ $qo->instructions['format'] = $this->trans_format($instructions[0]['@']['format']);
+ $files = $instructions[0]['#']['file'];
+ $qo->instructionsfiles = array();
+ foreach ($files as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->encoding = $file['@']['encoding'];
+ $data->name = $file['@']['name'];
+ $qo->instructionsfiles[] = $data;
+ }
+ }
return $qo;
}
@@ -404,8 +531,22 @@ class qformat_xml extends qformat_default {
// run through subquestions
foreach ($subquestions as $subquestion) {
- $qo->subquestions[] = $this->getpath( $subquestion, array('#','text',0,'#'), '', true );
- $qo->subanswers[] = $this->getpath( $subquestion, array('#','answer',0,'#','text',0,'#'), '', true);
+ $question = array();
+ $question['text'] = $this->getpath($subquestion, array('#', 'text', 0, '#'), '', true);
+ $question['format'] = $this->trans_format($this->getpath($subquestion, array('@', 'format'), '', true));
+ $question['files'] = array();
+
+ $files = $this->getpath($subquestion, array('#', 'file'), array());
+ foreach ($files as $file) {
+ $data = new stdclass();
+ $data->content = $file['#'];
+ $data->encoding = $file['@']['encoding'];
+ $data->name = $file['@']['name'];
+ $question['files'][] = $data;
+ }
+ $qo->subquestions[] = $question;
+ $answers = $this->getpath($subquestion, array('#', 'answer'), array());
+ $qo->subanswers[] = $this->getpath($subquestion, array('#','answer',0,'#','text',0,'#'), '', true);
}
return $qo;
}
@@ -422,8 +563,11 @@ class qformat_xml extends qformat_default {
// header parts particular to essay
$qo->qtype = ESSAY;
+ $answers = $question['#']['answer'];
+ $answer = array_pop($answers);
+ $answer = $this->import_answer($answer);
// get feedback
- $qo->feedback = $this->getpath( $question, array('#','answer',0,'#','feedback',0,'#','text',0,'#'), '', true );
+ $qo->feedback = $answer->feedback;
// get fraction - tag is deprecated
$qo->fraction = $this->getpath( $question, array('@','fraction'), 0 ) / 100;
@@ -432,7 +576,7 @@ class qformat_xml extends qformat_default {
return $qo;
}
- function import_calculated( $question ) {
+ function import_calculated($question) {
// import calculated question
// get common parts
@@ -446,16 +590,59 @@ class qformat_xml extends qformat_default {
$shuffleanswers = $this->getpath( $question, array('#','shuffleanswers',0,'#'), 'false' );
$qo->answernumbering = $this->getpath( $question, array('#','answernumbering',0,'#'), 'abc' );
$qo->shuffleanswers = $this->trans_single($shuffleanswers);
- $qo->correctfeedback = $this->getpath( $question, array('#','correctfeedback',0,'#','text',0,'#'), '', true );
- $qo->partiallycorrectfeedback = $this->getpath( $question, array('#','partiallycorrectfeedback',0,'#','text',0,'#'), '', true );
- $qo->incorrectfeedback = $this->getpath( $question, array('#','incorrectfeedback',0,'#','text',0,'#'), '', true );
+
+ $qo->correctfeedback = array();
+ $qo->correctfeedback['text'] = $this->getpath( $question, array('#','correctfeedback',0,'#','text',0,'#'), '', true );
+ $qo->correctfeedback['format'] = $this->trans_format($this->getpath( $question, array('#', 'correctfeedback', 0, '@', 'formath'), '', true ));
+ $qo->correctfeedback['files'] = array();
+
+ $files = $this->getpath($question, array('#', 'correctfeedback', '0', '#', 'file'), array());
+ foreach ($files as $file) {
+ $data = new stdclass();
+ $data->content = $file['#'];
+ $data->name = $file['@']['name'];
+ $data->encoding = $file['@']['encoding'];
+ $qo->correctfeedback['files'][] = $data;
+ }
+
+ $qo->partiallycorrectfeedback = array();
+ $qo->partiallycorrectfeedback['text'] = $this->getpath( $question, array('#','partiallycorrectfeedback',0,'#','text',0,'#'), '', true );
+ $qo->partiallycorrectfeedback['format'] = $this->trans_format($this->getpath($question, array('#','partiallycorrectfeedback', 0, '@','format'), '', true ));
+ $qo->partiallycorrectfeedback['files'] = array();
+
+ $files = $this->getpath($question, array('#', 'partiallycorrectfeedback', '0', '#', 'file'), array());
+ foreach ($files as $file) {
+ $data = new stdclass();
+ $data->content = $file['#'];
+ $data->name = $file['@']['name'];
+ $data->encoding = $file['@']['encoding'];
+ $qo->partiallycorrectfeedback['files'][] = $data;
+ }
+
+ $qo->incorrectfeedback = array();
+ $qo->incorrectfeedback['text'] = $this->getpath( $question, array('#','incorrectfeedback',0,'#','text',0,'#'), '', true );
+ $qo->incorrectfeedback['format'] = $this->trans_format($this->getpath($question, array('#','incorrectfeedback', 0, '@','format'), '', true ));
+ $qo->incorrectfeedback['files'] = array();
+
+ $files = $this->getpath($question, array('#', 'incorrectfeedback', '0', '#', 'file'), array());
+ foreach ($files as $file) {
+ $data = new stdclass();
+ $data->content = $file['#'];
+ $data->name = $file['@']['name'];
+ $data->encoding = $file['@']['encoding'];
+ $qo->incorrectfeedback['files'][] = $data;
+ }
+
$qo->unitgradingtype = $this->getpath( $question, array('#','unitgradingtype',0,'#'), 0 );
$qo->unitpenalty = $this->getpath( $question, array('#','unitpenalty',0,'#'), 0 );
$qo->showunits = $this->getpath( $question, array('#','showunits',0,'#'), 0 );
$qo->unitsleft = $this->getpath( $question, array('#','unitsleft',0,'#'), 0 );
$qo->instructions = $this->getpath( $question, array('#','instructions',0,'#','text',0,'#'), '', true );
+
+ $files = $this->getpath($question, array('#', 'instructions', 0, '#', 'file', 0, '@'), '', false);
+
// get answers array
- // echo " question";print_r($question);echo "
";
+ // echo " question";print_r($question);echo "
";
$answers = $question['#']['answer'];
$qo->answers = array();
$qo->feedback = array();
@@ -466,25 +653,18 @@ class qformat_xml extends qformat_default {
$qo->correctanswerlength = array();
$qo->feedback = array();
foreach ($answers as $answer) {
+ $ans = $this->import_answer($answer);
// answer outside of is deprecated
- if (!empty( $answer['#']['text'] )) {
- $answertext = $this->import_text( $answer['#']['text'] );
+ if (empty($ans->answer['text'])) {
+ $ans->answer['text'] = '*';
}
- else {
- $answertext = trim($answer['#'][0]);
- }
- if ($answertext == '') {
- $qo->answers[] = '*';
- } else {
- $qo->answers[] = $answertext;
- }
- $qo->feedback[] = $this->import_text( $answer['#']['feedback'][0]['#']['text'] );
+ $qo->answers[] = $ans->answer;
+ $qo->feedback[] = $ans->feedback;
$qo->tolerance[] = $answer['#']['tolerance'][0]['#'];
// fraction as a tag is deprecated
if (!empty($answer['#']['fraction'][0]['#'])) {
$qo->fraction[] = $answer['#']['fraction'][0]['#'];
- }
- else {
+ } else {
$qo->fraction[] = $answer['@']['fraction'] / 100;
}
$qo->tolerancetype[] = $answer['#']['tolerancetype'][0]['#'];
@@ -501,9 +681,26 @@ class qformat_xml extends qformat_default {
$qo->unit[] = $unit['#']['unit_name'][0]['#'];
}
}
- $datasets = $question['#']['dataset_definitions'][0]['#']['dataset_definition'];
- $qo->dataset = array();
- $qo->datasetindex= 0 ;
+ $instructions = $this->getpath($question, array('#', 'instructions'), array());
+ if (!empty($instructions)) {
+ $qo->instructions = array();
+ $qo->instructions['text'] = $instructions[0]['#']['text'][0]['#'];
+ $qo->instructions['format'] = $this->trans_format($instructions[0]['@']['format']);
+ $qo->instructionsfiles = array();
+ if (isset($instructions[0]['#']['file'])) {
+ $files = $instructions[0]['#']['file'];
+ foreach ($files as $file) {
+ $data = new stdclass;
+ $data->content = $file['#'];
+ $data->encoding = $file['@']['encoding'];
+ $data->name = $file['@']['name'];
+ $qo->instructionsfiles[] = $data;
+ }
+ }
+ }
+ $datasets = $question['#']['dataset_definitions'][0]['#']['dataset_definition'];
+ $qo->dataset = array();
+ $qo->datasetindex= 0 ;
foreach ($datasets as $dataset) {
$qo->datasetindex++;
$qo->dataset[$qo->datasetindex] = new stdClass();
@@ -522,14 +719,13 @@ class qformat_xml extends qformat_default {
$datasetitems = $dataset['#']['dataset_items'][0]['#']['dataset_item'];
foreach ($datasetitems as $datasetitem) {
$qo->dataset[$qo->datasetindex]->itemindex++;
- $qo->dataset[$qo->datasetindex]->datasetitem[$qo->dataset[$qo->datasetindex]->itemindex] = new stdClass();
- $qo->dataset[$qo->datasetindex]->datasetitem[$qo->dataset[$qo->datasetindex]->itemindex]->itemnumber = $datasetitem['#']['number'][0]['#']; //[0]['#']['number'][0]['#'] ; // [0]['numberitems'] ;//['#']['number'][0]['#'];// $datasetitems['#']['number'][0]['#'];
- $qo->dataset[$qo->datasetindex]->datasetitem[$qo->dataset[$qo->datasetindex]->itemindex]->value = $datasetitem['#']['value'][0]['#'] ;//$datasetitem['#']['value'][0]['#'];
- }
+ $qo->dataset[$qo->datasetindex]->datasetitem[$qo->dataset[$qo->datasetindex]->itemindex] = new stdClass();
+ $qo->dataset[$qo->datasetindex]->datasetitem[$qo->dataset[$qo->datasetindex]->itemindex]->itemnumber = $datasetitem['#']['number'][0]['#']; //[0]['#']['number'][0]['#'] ; // [0]['numberitems'] ;//['#']['number'][0]['#'];// $datasetitems['#']['number'][0]['#'];
+ $qo->dataset[$qo->datasetindex]->datasetitem[$qo->dataset[$qo->datasetindex]->itemindex]->value = $datasetitem['#']['value'][0]['#'] ;//$datasetitem['#']['value'][0]['#'];
+ }
}
- // echo "loaded qo";print_r($qo);echo "
";
-
+ // echo "loaded qo";print_r($qo);echo "
";
return $qo;
}
@@ -558,12 +754,12 @@ class qformat_xml extends qformat_default {
function readquestions($lines) {
// we just need it as one big string
$text = implode($lines, " ");
- unset( $lines );
+ unset($lines);
// this converts xml to big nasty data structure
// the 0 means keep white space as it is (important for markdown format)
// print_r it if you want to see what it looks like!
- $xml = xmlize( $text, 0 );
+ $xml = xmlize($text, 0);
// set up array to hold all our questions
$questions = array();
@@ -742,7 +938,7 @@ class qformat_xml extends qformat_default {
* @param boolean short stick it on one line
* @return string formatted text
*/
- function writetext( $raw, $ilev=0, $short=true) {
+ function writetext($raw, $ilev=0, $short=true) {
$indent = str_repeat( " ",$ilev );
// if required add CDATA tags
@@ -790,35 +986,17 @@ class qformat_xml extends qformat_default {
return $content;
}
- /**
- * Include an image encoded in base 64
- * @param string imagepath The location of the image file
- * @return string xml code segment
- */
- function writeimage( $imagepath ) {
- global $CFG;
-
- if (empty($imagepath)) {
- return '';
- }
-
- $courseid = $this->course->id;
- if (!$binary = file_get_contents( "{$CFG->dataroot}/$courseid/$imagepath" )) {
- return '';
- }
-
- $content = " \n".base64_encode( $binary )."\n".
- "\n \n";
- return $content;
- }
-
/**
* Turns question into an xml segment
- * @param array question question array
+ * @param object question object
+ * @param int context id
* @return string xml segment
*/
- function writequestion( $question ) {
- global $CFG,$QTYPES, $OUTPUT;
+ function writequestion($question) {
+ global $CFG, $QTYPES, $OUTPUT;
+
+ $fs = get_file_storage();
+ $contextid = $question->contextid;
// initial string;
$expout = "";
@@ -841,28 +1019,32 @@ class qformat_xml extends qformat_default {
$expout .= " \n";
$expout .= " \n";
return $expout;
- }
- elseif ($question->qtype != MULTIANSWER) {
+ } elseif ($question->qtype != MULTIANSWER) {
// for all question types except Close
- $name_text = $this->writetext( $question->name );
+ $name_text = $this->writetext($question->name);
$qtformat = $this->get_format($question->questiontextformat);
- $question_text = $this->writetext( $question->questiontext );
- $generalfeedback = $this->writetext( $question->generalfeedback );
+ $generalfeedbackformat = $this->get_format($question->generalfeedbackformat);
+
+ $question_text = $this->writetext($question->questiontext);
+ $question_text_files = $this->writefiles($question->questiontextfiles);
+
+ $generalfeedback = $this->writetext($question->generalfeedback);
+ $generalfeedback_files = $this->writefiles($question->generalfeedbackfiles);
+
$expout .= " \n";
$expout .= " $name_text\n";
$expout .= " \n";
$expout .= $question_text;
+ $expout .= $question_text_files;
$expout .= " \n";
- $expout .= " {$question->image}\n";
- $expout .= $this->writeimage($question->image);
- $expout .= " \n";
+ $expout .= " \n";
$expout .= $generalfeedback;
+ $expout .= $generalfeedback_files;
$expout .= " \n";
$expout .= " {$question->defaultgrade}\n";
$expout .= " {$question->penalty}\n";
$expout .= " {$question->hidden}\n";
- }
- else {
+ } else {
// for Cloze type only
$name_text = $this->writetext( $question->name );
$question_text = $this->writetext( $question->questiontext );
@@ -899,8 +1081,10 @@ class qformat_xml extends qformat_default {
}
$expout .= " \n";
$expout .= $this->writetext($answertext, 3) . "\n";
- $expout .= " \n";
- $expout .= $this->writetext( $answer->feedback,4,false );
+ $feedbackformat = $this->get_format($answer->feedbackformat);
+ $expout .= " \n";
+ $expout .= $this->writetext($answer->feedback,4,false);
+ $expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " \n";
$expout .= " \n";
}
@@ -908,28 +1092,51 @@ class qformat_xml extends qformat_default {
case MULTICHOICE:
$expout .= " ".$this->get_single($question->options->single)."\n";
$expout .= " ".$this->get_single($question->options->shuffleanswers)."\n";
- $expout .= " ".$this->writetext($question->options->correctfeedback, 3)."\n";
- $expout .= " ".$this->writetext($question->options->partiallycorrectfeedback, 3)."\n";
- $expout .= " ".$this->writetext($question->options->incorrectfeedback, 3)."\n";
+
+ $textformat = $this->get_format($question->options->correctfeedbackformat);
+ $files = $fs->get_area_files($contextid, 'qtype_multichoice', 'correctfeedback', $question->id);
+ $expout .= " \n";
+ $expout .= $this->writetext($question->options->correctfeedback, 3);
+ $expout .= $this->writefiles($files);
+ $expout .= " \n";
+
+ $textformat = $this->get_format($question->options->partiallycorrectfeedbackformat);
+ $files = $fs->get_area_files($contextid, 'qtype_multichoice', 'partiallycorrectfeedback', $question->id);
+ $expout .= " \n";
+ $expout .= $this->writetext($question->options->partiallycorrectfeedback, 3);
+ $expout .= $this->writefiles($files);
+ $expout .= " \n";
+
+ $textformat = $this->get_format($question->options->incorrectfeedbackformat);
+ $files = $fs->get_area_files($contextid, 'qtype_multichoice', 'incorrectfeedback', $question->id);
+ $expout .= " \n";
+ $expout .= $this->writetext($question->options->incorrectfeedback, 3);
+ $expout .= $this->writefiles($files);
+ $expout .= " \n";
+
$expout .= " ".$this->writetext($question->options->answernumbering, 3)."\n";
foreach($question->options->answers as $answer) {
$percent = $answer->fraction * 100;
$expout .= " \n";
- $expout .= $this->writetext( $answer->answer,4,false );
- $expout .= " \n";
- $expout .= $this->writetext( $answer->feedback,5,false );
+ $expout .= $this->writetext($answer->answer,4,false);
+ $feedbackformat = $this->get_format($answer->feedbackformat);
+ $expout .= " \n";
+ $expout .= $this->writetext($answer->feedback,5,false);
+ $expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " \n";
$expout .= " \n";
}
break;
case SHORTANSWER:
- $expout .= " {$question->options->usecase}\n ";
+ $expout .= " {$question->options->usecase}\n ";
foreach($question->options->answers as $answer) {
$percent = 100 * $answer->fraction;
$expout .= " \n";
$expout .= $this->writetext( $answer->answer,3,false );
- $expout .= " \n";
- $expout .= $this->writetext( $answer->feedback,4,false );
+ $feedbackformat = $this->get_format($answer->feedbackformat);
+ $expout .= " \n";
+ $expout .= $this->writetext($answer->feedback);
+ $expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " \n";
$expout .= " \n";
}
@@ -942,7 +1149,11 @@ class qformat_xml extends qformat_default {
// tags are an added feature, old filed won't have them
$expout .= " {$answer->answer}\n";
$expout .= " $tolerance\n";
- $expout .= " ".$this->writetext( $answer->feedback )."\n";
+ $feedbackformat = $this->get_format($answer->feedbackformat);
+ $expout .= " \n";
+ $expout .= $this->writetext($answer->feedback);
+ $expout .= $this->writefiles($answer->feedbackfiles);
+ $expout .= " \n";
// fraction tag is deprecated
// $expout .= " {$answer->fraction}\n";
$expout .= "\n";
@@ -959,12 +1170,25 @@ class qformat_xml extends qformat_default {
}
$expout .= "\n";
}
+ if (!empty($question->options->instructionsformat)) {
+ $textformat = $this->get_format($question->options->instructionsformat);
+ $files = $fs->get_area_files($contextid, 'qtype_numerical', 'instruction', $question->id);
+ $expout .= " \n";
+ $expout .= $this->writetext($question->options->instructions, 3);
+ $expout .= $this->writefiles($files);
+ $expout .= " \n";
+ }
break;
case MATCH:
foreach($question->options->subquestions as $subquestion) {
- $expout .= "\n";
- $expout .= $this->writetext( $subquestion->questiontext );
- $expout .= "".$this->writetext( $subquestion->answertext )."\n";
+ $files = $fs->get_area_files($contextid, 'qtype_match', 'subquestion', $subquestion->id);
+ $textformat = $this->get_format($subquestion->questiontextformat);
+ $expout .= "\n";
+ $expout .= $this->writetext($subquestion->questiontext);
+ $expout .= $this->writefiles($files);
+ $expout .= "";
+ $expout .= $this->writetext($subquestion->answertext);
+ $expout .= "\n";
$expout .= "\n";
}
break;
@@ -985,7 +1209,11 @@ class qformat_xml extends qformat_default {
foreach ($question->options->answers as $answer) {
$percent = 100 * $answer->fraction;
$expout .= "\n";
- $expout .= " ".$this->writetext( $answer->feedback )."\n";
+ $feedbackformat = $this->get_format($answer->feedbackformat);
+ $expout .= " \n";
+ $expout .= $this->writetext($answer->feedback);
+ $expout .= $this->writefiles($answer->feedbackfiles);
+ $expout .= " \n";
// fraction tag is deprecated
// $expout .= " {$answer->fraction}\n";
$expout .= "\n";
@@ -999,9 +1227,26 @@ class qformat_xml extends qformat_default {
$expout .= " {$question->options->single}\n";
$expout .= " {$question->options->answernumbering}\n";
$expout .= " ".$this->writetext($question->options->shuffleanswers, 3)."\n";
- $expout .= " ".$this->writetext($question->options->correctfeedback, 3)."\n";
- $expout .= " ".$this->writetext($question->options->partiallycorrectfeedback, 3)."\n";
- $expout .= " ".$this->writetext($question->options->incorrectfeedback, 3)."\n";
+
+ $component = 'qtype_' . $question->qtype;
+ $files = $fs->get_area_files($contextid, $component, 'correctfeedback', $question->id);
+ $expout .= " \n";
+ $expout .= $this->writetext($question->options->correctfeedback, 3);
+ $expout .= $this->writefiles($files);
+ $expout .= " \n";
+
+ $files = $fs->get_area_files($contextid, $component, 'partiallycorrectfeedback', $question->id);
+ $expout .= " \n";
+ $expout .= $this->writetext($question->options->partiallycorrectfeedback, 3);
+ $expout .= $this->writefiles($files);
+ $expout .= " \n";
+
+ $files = $fs->get_area_files($contextid, $component, 'incorrectfeedback', $question->id);
+ $expout .= " \n";
+ $expout .= $this->writetext($question->options->incorrectfeedback, 3);
+ $expout .= $this->writefiles($files);
+ $expout .= " \n";
+
foreach ($question->options->answers as $answer) {
$tolerance = $answer->tolerance;
$tolerancetype = $answer->tolerancetype;
@@ -1015,25 +1260,48 @@ class qformat_xml extends qformat_default {
$expout .= " $tolerancetype\n";
$expout .= " $correctanswerformat\n";
$expout .= " $correctanswerlength\n";
- $expout .= " ".$this->writetext( $answer->feedback )."\n";
+ $feedbackformat = $this->get_format($answer->feedbackformat);
+ $expout .= " \n";
+ $expout .= $this->writetext($answer->feedback);
+ $expout .= $this->writefiles($answer->feedbackfiles);
+ $expout .= " \n";
$expout .= "\n";
}
- $expout .= " {$question->options->unitgradingtype}\n";
- $expout .= " {$question->options->unitpenalty}\n";
- $expout .= " {$question->options->showunits}\n";
- $expout .= " {$question->options->unitsleft}\n";
- $expout .= " ".$this->writetext($question->options->instructions, 3)."\n";
- $units = $question->options->units;
- if (count($units)) {
- $expout .= "\n";
- foreach ($units as $unit) {
- $expout .= " \n";
- $expout .= " {$unit->multiplier}\n";
- $expout .= " {$unit->unit}\n";
- $expout .= " \n";
+ if (!empty($question->options->unitgradingtype)) {
+ $expout .= " {$question->options->unitgradingtype}\n";
+ }
+ if (!empty($question->options->unitpenalty)) {
+ $expout .= " {$question->options->unitpenalty}\n";
+ }
+ if (!empty($question->options->showunits)) {
+ $expout .= " {$question->options->showunits}\n";
+ }
+ if (!empty($question->options->unitsleft)) {
+ $expout .= " {$question->options->unitsleft}\n";
+ }
+
+ if (!empty($question->options->instructionsformat)) {
+ $textformat = $this->get_format($question->options->instructionsformat);
+ $files = $fs->get_area_files($contextid, $component, 'instruction', $question->id);
+ $expout .= " \n";
+ $expout .= $this->writetext($question->options->instructions, 3);
+ $expout .= $this->writefiles($files);
+ $expout .= " \n";
+ }
+
+ if (isset($question->options->units)) {
+ $units = $question->options->units;
+ if (count($units)) {
+ $expout .= "\n";
+ foreach ($units as $unit) {
+ $expout .= " \n";
+ $expout .= " {$unit->multiplier}\n";
+ $expout .= " {$unit->unit}\n";
+ $expout .= " \n";
+ }
+ $expout .= "\n";
}
- $expout .= "\n";
- }
+ }
//The tag $question->export_process has been set so we get all the data items in the database
// from the function $QTYPES['calculated']->get_question_options(&$question);
// calculatedsimple defaults to calculated
@@ -1080,8 +1348,11 @@ class qformat_xml extends qformat_default {
// close the question tag
$expout .= "\n";
+ // XXX: debuging
+ //echo '';
+
return $expout;
}
}
-
-?>
diff --git a/question/import.php b/question/import.php
index 7affec34e0d..48be0d45252 100644
--- a/question/import.php
+++ b/question/import.php
@@ -28,10 +28,12 @@ if (!$category = $DB->get_record("question_categories", array("id" => $catid)))
$PAGE->set_pagelayout('standard');
+$categorycontext = get_context_instance_by_id($category->contextid);
+$category->context = $categorycontext;
//this page can be called without courseid or cmid in which case
//we get the context from the category object.
if ($contexts === null) { // need to get the course from the chosen category
- $contexts = new question_edit_contexts(get_context_instance_by_id($category->contextid));
+ $contexts = new question_edit_contexts($categorycontext);
$thiscontext = $contexts->lowest();
if ($thiscontext->contextlevel == CONTEXT_COURSE){
require_login($thiscontext->instanceid, false);
@@ -65,22 +67,14 @@ if ($form = $import_form->get_data()) {
// work out if this is an uploaded file
// or one from the filesarea.
- if (!empty($form->choosefile)) {
- $importfile = "{$CFG->dataroot}/{$COURSE->id}/{$form->choosefile}";
- $realfilename = $form->choosefile;
- if (file_exists($importfile)) {
- $fileisgood = true;
- } else {
- print_error('uploadproblem', 'moodle', $form->choosefile);
- }
- } else {
- $realfilename = $import_form->get_new_filename('newfile');
- $importfile = "{$CFG->dataroot}/{$COURSE->id}/{$realfilename}";
- if (!$result = $import_form->save_file('newfile', $importfile, true)) {
- print_error('uploadproblem', 'moodle');
- }else {
- $fileisgood = true;
- }
+ $realfilename = $import_form->get_new_filename('newfile');
+
+ $importfile = "{$CFG->dataroot}/temp/questionimport/{$realfilename}";
+ make_upload_directory('temp/questionimport');
+ if (!$result = $import_form->save_file('newfile', $importfile, true)) {
+ print_error('uploadproblem', 'moodle');
+ }else {
+ $fileisgood = true;
}
// process if we are happy file is ok
@@ -114,7 +108,7 @@ if ($form = $import_form->get_data()) {
}
// Process the uploaded file
- if (! $qformat->importprocess()) {
+ if (! $qformat->importprocess($category)) {
//TODO: need more detailed error info
print_error('cannotimport', '', $thispageurl->out());
}
diff --git a/question/type/calculated/questiontype.php b/question/type/calculated/questiontype.php
index b0faf5e344f..9e646a47aa9 100644
--- a/question/type/calculated/questiontype.php
+++ b/question/type/calculated/questiontype.php
@@ -64,7 +64,7 @@ class question_calculated_qtype extends default_questiontype {
"WHERE a.question = ? " .
"AND a.id = c.answer ".
"ORDER BY a.id ASC", array($question->id))) {
- echo $OUTPUT->notification('Error: Missing question answer for calculated question ' . $question->id . '!');
+ // echo $OUTPUT->notification('Error: Missing question answer for calculated question ' . $question->id . '!');
return false;
}
@@ -151,7 +151,13 @@ class question_calculated_qtype extends default_questiontype {
$options->$feedbackname = trim($feedback['text']);
$feedbackformat = $feedbackname . 'format';
$options->$feedbackformat = trim($feedback['format']);
- $options->$feedbackname = file_save_draft_area_files($feedback['itemid'], $context->id, 'qtype_calculated', $feedbackname, $question->id, self::$fileoptions, trim($feedback['text']));
+ if (isset($feedback['files'])) {
+ foreach ($feedback['files'] as $file) {
+ $this->import_file($question->context, 'qtype_calculated', $feedbackname, $question->id, $file);
+ }
+ } else {
+ $options->$feedbackname = file_save_draft_area_files($feedback['itemid'], $context->id, 'qtype_calculated', $feedbackname, $question->id, self::$fileoptions, trim($feedback['text']));
+ }
}
if ($update) {
@@ -182,21 +188,33 @@ class question_calculated_qtype extends default_questiontype {
$question->answers=$question->answer;
}
foreach ($question->answers as $key => $dataanswer) {
+ if (is_array($dataanswer)) {
+ $dataanswer = $dataanswer['text'];
+ }
if ( trim($dataanswer) != '' ) {
$answer = new stdClass;
$answer->question = $question->id;
$answer->answer = trim($dataanswer);
$answer->fraction = $question->fraction[$key];
$answer->feedbackformat = $question->feedback[$key]['format'];
+ if (isset($question->feedback[$key]['files'])) {
+ $files = $question->feedback[$key]['files'];
+ }
if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
$answer->id = $oldanswer->id;
$answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $oldanswer->id, self::$fileoptions, trim($question->feedback[$key]['text']));
$DB->update_record("question_answers", $answer);
} else { // This is a completely new answer
- $answer->feedback = '';
+ $answer->feedback = trim($question->feedback[$key]['text']);
$answer->id = $DB->insert_record("question_answers", $answer);
- $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, trim($question->feedback[$key]['text']));
+ if (isset($files)) {
+ foreach ($files as $file) {
+ $this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
+ }
+ } else {
+ $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, trim($question->feedback[$key]['text']));
+ }
$DB->set_field('question_answers', 'feedback', $answer->feedback, array('id'=>$answer->id));
}
diff --git a/question/type/calculatedmulti/questiontype.php b/question/type/calculatedmulti/questiontype.php
index 3c05862b1bc..d7a4ec059d7 100644
--- a/question/type/calculatedmulti/questiontype.php
+++ b/question/type/calculatedmulti/questiontype.php
@@ -65,7 +65,15 @@ class question_calculatedmulti_qtype extends question_calculated_qtype {
$feedbackformat = $feedbackname . 'format';
$feedback = $question->$feedbackname;
$options->$feedbackformat = $feedback['format'];
- $options->$feedbackname = file_save_draft_area_files($feedback['itemid'], $context->id, 'qtype_calculatedmulti', $feedbackname, $question->id, self::$fileoptions, trim($feedback['text']));
+ if (isset($feedback['files'])) {
+ $options->$feedbackname = trim($feedback['text']);
+ $files = $feedback['files'];
+ foreach ($files as $file) {
+ $this->import_file($question->context, 'qtype_calculatedmulti', $feedbackname, $question->id, $file);
+ }
+ } else {
+ $options->$feedbackname = file_save_draft_area_files($feedback['itemid'], $context->id, 'qtype_calculatedmulti', $feedbackname, $question->id, self::$fileoptions, trim($feedback['text']));
+ }
}
if ($update) {
@@ -97,6 +105,9 @@ class question_calculatedmulti_qtype extends question_calculated_qtype {
$question->answers = $question->answer;
}
foreach ($question->answers as $key => $dataanswer) {
+ if (is_array($dataanswer)) {
+ $dataanswer = $dataanswer['text'];
+ }
if ( trim($dataanswer) != '' ) {
$answer = new stdClass;
$answer->question = $question->id;
@@ -104,6 +115,9 @@ class question_calculatedmulti_qtype extends question_calculated_qtype {
$answer->fraction = $question->fraction[$key];
$answer->feedback = trim($question->feedback[$key]['text']);
$answer->feedbackformat = $question->feedback[$key]['format'];
+ if (isset($question->feedback[$key]['files'])) {
+ $files = $question->feedback[$key]['files'];
+ }
if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
$answer->id = $oldanswer->id;
@@ -111,7 +125,14 @@ class question_calculatedmulti_qtype extends question_calculated_qtype {
$DB->update_record("question_answers", $answer);
} else { // This is a completely new answer
$answer->id = $DB->insert_record("question_answers", $answer);
- $feedbacktext = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $answer->feedback);
+ if (isset($files)) {
+ $feedbacktext = $answer->feedback;
+ foreach ($files as $file) {
+ $this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
+ }
+ } else {
+ $feedbacktext = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $answer->feedback);
+ }
$DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$answer->id));
}
diff --git a/question/type/calculatedsimple/questiontype.php b/question/type/calculatedsimple/questiontype.php
index 3cbc40173e5..ea9d6cb7d7a 100644
--- a/question/type/calculatedsimple/questiontype.php
+++ b/question/type/calculatedsimple/questiontype.php
@@ -64,21 +64,33 @@ class question_calculatedsimple_qtype extends question_calculated_qtype {
$question->answers=$question->answer;
}
foreach ($question->answers as $key => $dataanswer) {
+ if (is_array($dataanswer)) {
+ $dataanswer = $dataanswer['text'];
+ }
if ( trim($dataanswer) != '' ) {
$answer = new stdClass;
$answer->question = $question->id;
$answer->answer = trim($dataanswer);
$answer->fraction = $question->fraction[$key];
$answer->feedbackformat = $question->feedback[$key]['format'];
+ if (isset($question->feedback[$key]['files'])) {
+ $files = $question->feedback[$key]['files'];
+ }
if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
$answer->id = $oldanswer->id;
$answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, trim($question->feedback[$key]['text']));
$DB->update_record("question_answers", $answer);
} else { // This is a completely new answer
- $answer->feedback = '';
+ $answer->feedback = trim($question->feedback[$key]['text']);
$answer->id = $DB->insert_record("question_answers", $answer);
- $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, trim($question->feedback[$key]['text']));
+ if (isset($files)) {
+ foreach ($files as $file) {
+ $this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
+ }
+ } else {
+ $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, trim($question->feedback[$key]['text']));
+ }
$DB->set_field('question_answers', 'feedback', $answer->feedback, array('id'=>$answer->id));
}
diff --git a/question/type/essay/questiontype.php b/question/type/essay/questiontype.php
index 02680ccea9f..7c8395159aa 100644
--- a/question/type/essay/questiontype.php
+++ b/question/type/essay/questiontype.php
@@ -56,7 +56,14 @@ class question_essay_qtype extends default_questiontype {
$answer->feedback = $question->feedback['text'];
$answer->answer = $answer->feedback;
$answer->id = $DB->insert_record('question_answers', $answer);
- $answer->feedback = file_save_draft_area_files($question->feedback['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, trim($question->feedback['text']));
+ if (isset($question->feedback['files'])) {
+ // import
+ foreach ($question->feedback['files'] as $file) {
+ $this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
+ }
+ } else {
+ $answer->feedback = file_save_draft_area_files($question->feedback['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, trim($question->feedback['text']));
+ }
$answer->answer = $answer->feedback;
$DB->update_record('question_answers', $answer);
}
diff --git a/question/type/match/questiontype.php b/question/type/match/questiontype.php
index 76b97a8a086..c185bb0efba 100644
--- a/question/type/match/questiontype.php
+++ b/question/type/match/questiontype.php
@@ -51,7 +51,12 @@ class question_match_qtype extends default_questiontype {
// Insert all the new question+answer pairs
foreach ($question->subquestions as $key => $questiontext) {
- $itemid = $questiontext['itemid'];
+ if (!empty($questiontext['itemid'])) {
+ $itemid = $questiontext['itemid'];
+ }
+ if (!empty($questiontext['files'])) {
+ $files = $questiontext['files'];
+ }
$format = $questiontext['format'];
$questiontext = trim($questiontext['text']);
$answertext = trim($question->subanswers[$key]);
@@ -73,7 +78,13 @@ class question_match_qtype extends default_questiontype {
$subquestion->questiontextformat = $format;
$subquestion->answertext = $answertext;
$subquestion->id = $DB->insert_record("question_match_sub", $subquestion);
- $questiontext = file_save_draft_area_files($itemid, $context->id, 'qtype_match', 'subquestion', $subquestion->id, self::$fileoptions, $questiontext);
+ if (!isset($itemid)) {
+ foreach ($files as $file) {
+ $this->import_file($context, 'qtype_match', 'subquestion', $subquestion->id, $file);
+ }
+ } else {
+ $questiontext = file_save_draft_area_files($itemid, $context->id, 'qtype_match', 'subquestion', $subquestion->id, self::$fileoptions, $questiontext);
+ }
$DB->set_field('question_match_sub', 'questiontext', $questiontext, array('id'=>$subquestion->id));
}
$subquestions[] = $subquestion->id;
diff --git a/question/type/multichoice/questiontype.php b/question/type/multichoice/questiontype.php
index d82366f7cf3..10a2da3a5de 100644
--- a/question/type/multichoice/questiontype.php
+++ b/question/type/multichoice/questiontype.php
@@ -74,14 +74,27 @@ class question_multichoice_qtype extends default_questiontype {
$answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $question->feedback[$key]['text']);
$DB->update_record("question_answers", $answer);
} else {
+ // import goes here too
unset($answer);
- $answer->answer = $dataanswer;
+ if (is_array($dataanswer)) {
+ $answer->answer = $dataanswer['text'];
+ $answer->answerformat = $dataanswer['format'];
+ } else {
+ $answer->answer = $dataanswer;
+ }
$answer->question = $question->id;
$answer->fraction = $question->fraction[$key];
- $answer->feedback = '';
+ $answer->feedback = $question->feedback[$key]['text'];
$answer->feedbackformat = $feedbackformat;
$answer->id = $DB->insert_record("question_answers", $answer);
- $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $question->feedback[$key]['text']);
+ if (isset($question->feedback[$key]['files'])) {
+ foreach ($question->feedback[$key]['files'] as $file) {
+ $this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
+ }
+ } else {
+ $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $question->feedback[$key]['text']);
+ }
+
$DB->set_field('question_answers', 'feedback', $answer->feedback, array('id'=>$answer->id));
}
$answers[] = $answer->id;
@@ -114,9 +127,18 @@ class question_multichoice_qtype extends default_questiontype {
foreach (array('correct', 'partiallycorrect', 'incorrect') as $feedbacktype) {
$feedbackname = $feedbacktype . 'feedback';
$feedbackformat = $feedbackname . 'format';
+ $feedbackfiles = $feedbackname . 'files';
$feedback = $question->$feedbackname;
$options->$feedbackformat = trim($feedback['format']);
- $options->$feedbackname = file_save_draft_area_files($feedback['itemid'], $context->id, 'qtype_multichoice', $feedbackname, $question->id, self::$fileoptions, trim($feedback['text']));
+ $options->$feedbackname = trim($feedback['text']);
+ if (isset($feedback['files'])) {
+ // import
+ foreach ($feedback['files'] as $file) {
+ $this->import_file($context, 'qtype_multichoice', $feedbackname, $question->id, $file);
+ }
+ } else {
+ $options->$feedbackname = file_save_draft_area_files($feedback['itemid'], $context->id, 'qtype_multichoice', $feedbackname, $question->id, self::$fileoptions, trim($feedback['text']));
+ }
}
if ($update) {
diff --git a/question/type/numerical/questiontype.php b/question/type/numerical/questiontype.php
index a16f6c399b4..7a3d79c496e 100644
--- a/question/type/numerical/questiontype.php
+++ b/question/type/numerical/questiontype.php
@@ -167,6 +167,9 @@ class question_numerical_qtype extends question_shortanswer_qtype {
// Insert all the new answers
foreach ($question->answer as $key => $dataanswer) {
+ if (is_array($dataanswer)) {
+ $dataanswer = $dataanswer['text'];
+ }
// Check for, and ingore, completely blank answer from the form.
if (trim($dataanswer) == '' && $question->fraction[$key] == 0 &&
html_is_blank($question->feedback[$key]['text'])) {
@@ -186,10 +189,13 @@ class question_numerical_qtype extends question_shortanswer_qtype {
$answer->fraction = $question->fraction[$key];
$feedbacktext = trim($question->feedback[$key]['text']);
- $draftid = $question->feedback[$key]['itemid'];
-
-
$answer->feedbackformat = $question->feedback[$key]['format'];
+ if (!empty($question->feedback[$key]['itemid'])) {
+ $draftid = $question->feedback[$key]['itemid'];
+ }
+ if ($question->feedback[$key]['files']) {
+ $feedbackfiles = $question->feedback[$key]['files'];
+ }
if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
$feedbacktext = file_save_draft_area_files($draftid, $context->id, 'question', 'answerfeedback', $oldanswer->id, self::$fileoptions, $feedbacktext);
@@ -199,7 +205,13 @@ class question_numerical_qtype extends question_shortanswer_qtype {
} else { // This is a completely new answer
$answer->feedback = $feedbacktext;
$answer->id = $DB->insert_record("question_answers", $answer);
- $feedbacktext = file_save_draft_area_files($draftid, $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $feedbacktext);
+ if (!isset($draftid) && isset($feedbackfiles)) {
+ foreach ($feedbackfiles as $file) {
+ $this->import_file($question->context, 'question', 'answerfeedback', $answer->id, $file);
+ }
+ } else {
+ $feedbacktext = file_save_draft_area_files($draftid, $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $feedbacktext);
+ }
$DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$answer->id));
}
@@ -319,14 +331,21 @@ class question_numerical_qtype extends question_shortanswer_qtype {
$options->instructions = '' ;
}
$component = 'qtype_' . $question->qtype;
- $options->instructions = file_save_draft_area_files($question->instructions['itemid'],
- $question->context->id, // context
- $component, // component
- 'instruction', // filearea
- $question->id, // itemid
- self::$fileoptions, // options
- $question->instructions['text'] // text
- );
+ if (isset($question->instructionsfiles) && is_array($question->instructionsfiles)) {
+ // import
+ foreach ($question->instructionsfiles as $file) {
+ $this->import_file($question->context, $component, 'instruction', $question->id, $file);
+ }
+ } else {
+ $options->instructions = file_save_draft_area_files($question->instructions['itemid'],
+ $question->context->id, // context
+ $component, // component
+ 'instruction', // filearea
+ $question->id, // itemid
+ self::$fileoptions, // options
+ $question->instructions['text'] // text
+ );
+ }
if ($update) {
$DB->update_record("question_numerical_options", $options);
} else {
diff --git a/question/type/questiontype.php b/question/type/questiontype.php
index 9281a7fa710..7e10310113b 100644
--- a/question/type/questiontype.php
+++ b/question/type/questiontype.php
@@ -1782,4 +1782,28 @@ class default_questiontype {
}
}
}
+
+ function import_file($context, $component, $filearea, $itemid, $file) {
+ $fs = get_file_storage();
+ $record = new stdclass;
+ if (is_object($context)) {
+ $record->contextid = $context->id;
+ } else {
+ $record->contextid = $context;
+ }
+ $record->component = $component;
+ $record->filearea = $filearea;
+ $record->itemid = $itemid;
+ $record->filename = $file->name;
+ $record->filepath = '/';
+ return $fs->create_file_from_string($record, $this->decode_file($file));
+ }
+
+ function decode_file($file) {
+ switch ($file->encoding) {
+ case 'base64':
+ default:
+ return base64_decode($file->content);
+ }
+ }
}
diff --git a/question/type/shortanswer/questiontype.php b/question/type/shortanswer/questiontype.php
index 19ee8d277fd..412842e9ace 100644
--- a/question/type/shortanswer/questiontype.php
+++ b/question/type/shortanswer/questiontype.php
@@ -93,6 +93,9 @@ class question_shortanswer_qtype extends default_questiontype {
// Insert all the new answers
foreach ($question->answer as $key => $dataanswer) {
+ if (is_array($dataanswer)) {
+ $dataanswer = $dataanswer['text'];
+ }
// Check for, and ingore, completely blank answer from the form.
if (trim($dataanswer) == '' && $question->fraction[$key] == 0 &&
html_is_blank($question->feedback[$key]['text'])) {
@@ -100,6 +103,9 @@ class question_shortanswer_qtype extends default_questiontype {
}
$feedbackformat = $question->feedback[$key]['format'];
+ if (isset($question->feedback[$key]['files'])) {
+ $feedbackfiles = $question->feedback[$key]['files'];
+ }
if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
$answer = $oldanswer;
@@ -117,12 +123,19 @@ class question_shortanswer_qtype extends default_questiontype {
$answer->question = $question->id;
$answer->fraction = $question->fraction[$key];
// feedback content needs to be rewriten
- $answer->feedback = '';
+ $answer->feedback = $question->feedback[$key]['text'];
$answer->feedbackformat = $feedbackformat;
$answer->id = $DB->insert_record("question_answers", $answer);
+ if (isset($feedbackfiles)) {
+ // import
+ foreach ($feedbackfiles as $file) {
+ $this->import_file($question->context, 'question', 'answerfeedback', $answer->id, $file);
+ }
+ } else {
// save draft file and rewrite text in feedback
- $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $question->feedback[$key]['text']);
+ $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, self::$fileoptions, $question->feedback[$key]['text']);
+ }
// update feedback content
$DB->set_field('question_answers', 'feedback', $answer->feedback, array('id'=>$answer->id));
}
diff --git a/question/type/truefalse/questiontype.php b/question/type/truefalse/questiontype.php
index a0935cd5de0..1f06e1ae2ad 100644
--- a/question/type/truefalse/questiontype.php
+++ b/question/type/truefalse/questiontype.php
@@ -35,6 +35,7 @@ class question_truefalse_qtype extends default_questiontype {
function save_question_options($question) {
global $DB;
$result = new stdClass;
+ $fs = get_file_storage();
// fetch old answer ids so that we can reuse them
if (!$oldanswers = $DB->get_records("question_answers", array("question" => $question->id), "id ASC")) {
@@ -44,6 +45,9 @@ class question_truefalse_qtype extends default_questiontype {
$feedbacktext = $question->feedbacktrue['text'];
$feedbackitemid = $question->feedbacktrue['itemid'];
$feedbackformat = $question->feedbacktrue['format'];
+ if (isset($question->feedbacktruefiles)) {
+ $files = $question->feedbacktruefiles;
+ }
// Save answer 'True'
if ($true = array_shift($oldanswers)) { // Existing answer, so reuse it
$true->answer = get_string("true", "quiz");
@@ -61,7 +65,15 @@ class question_truefalse_qtype extends default_questiontype {
$true->feedback = '';
$true->feedbackformat = $feedbackformat;
$true->id = $DB->insert_record("question_answers", $true);
- $feedbacktext = file_save_draft_area_files($feedbackitemid, $question->context->id, 'question', 'answerfeedback', $true->id, self::$fileoptions, $feedbacktext);
+ // import
+ if (isset($files)) {
+ foreach ($files as $file) {
+ $this->import_file($question->context, 'question', 'answerfeedback', $true->id, $file);
+ }
+ } else {
+ // moodle form
+ $feedbacktext = file_save_draft_area_files($feedbackitemid, $question->context->id, 'question', 'answerfeedback', $true->id, self::$fileoptions, $feedbacktext);
+ }
$DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$true->id));
}
@@ -85,7 +97,13 @@ class question_truefalse_qtype extends default_questiontype {
$false->feedback = '';
$false->feedbackformat = $feedbackformat;
$false->id = $DB->insert_record("question_answers", $false);
- $feedbacktext = file_save_draft_area_files($feedbackitemid, $question->context->id, 'question', 'answerfeedback', $false->id, self::$fileoptions, $feedbacktext);
+ if ($feedbackitemid == null && !empty($files)) {
+ foreach ($files as $file) {
+ $this->import_file($question->context, 'question', 'answerfeedback', $false->id, $file);
+ }
+ } else {
+ $feedbacktext = file_save_draft_area_files($feedbackitemid, $question->context->id, 'question', 'answerfeedback', $false->id, self::$fileoptions, $feedbacktext);
+ }
$DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$false->id));
}