MDL-15573, question export rewrite

This commit is contained in:
Dongsheng Cai 2010-11-05 06:34:00 +00:00
parent cc7719396e
commit cde2709a88
16 changed files with 796 additions and 325 deletions

View File

@ -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 '<textarea cols=90 rows=20>';
//echo $content;
//echo '</textarea>';
//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);
}

View File

@ -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 "<hr />";
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 '<p><div class="boxaligncenter"><a href="' . $efile . '">' .
get_string('download', 'quiz') . '</a></div></p>';
echo '<p><div class="boxaligncenter"><font size="-1">' .
get_string('downloadextra', 'quiz') . '</font></div></p>';
} else {
$efile = get_file_url($filename, null, 'questionfile');
echo '<p><div class="boxaligncenter">' .
get_string('yourfileshoulddownload', 'question', $efile) . '</div></p>';
$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();

View File

@ -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 {
//--------------------------------------------------------------------------------
}
}

View File

@ -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 "<hr /><p><b>$count</b>. ".$this->format_question_text($question)."</p>";
$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 "<hr /><p><b>$count</b>. ".$this->format_question_text($question)."</p>";
if (question_has_capability_on($question, 'view', $question->category)){
$expout .= $this->writequestion( $question ) . "\n";
//echo '<hr />';
//echo $OUTPUT->container_start();
//echo '<strong>' . $count . '.</strong>&nbsp;';
//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 .= '<file ';
$string .= ('name="' . $file->get_filename() . '"');
$string .= (' encoding="' . $encoding . '"');
$string .= '>';
$string .= base64_encode($file->get_content());
//$string .= 'base64';
$string .= '</file>';
}
return $string;
}
}

View File

@ -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 <text> 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 - <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 "<pre> question";print_r($question);echo "</pre>";
// echo "<pre> question";print_r($question);echo "</pre>";
$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 <text> 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 "<pre>loaded qo";print_r($qo);echo "</pre>";
// echo "<pre>loaded qo";print_r($qo);echo "</pre>";
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 = " <image_base64>\n".base64_encode( $binary )."\n".
"\n </image_base64>\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 .= " </category>\n";
$expout .= " </question>\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 .= " <question type=\"$question_type\">\n";
$expout .= " <name>$name_text</name>\n";
$expout .= " <questiontext format=\"$qtformat\">\n";
$expout .= $question_text;
$expout .= $question_text_files;
$expout .= " </questiontext>\n";
$expout .= " <image>{$question->image}</image>\n";
$expout .= $this->writeimage($question->image);
$expout .= " <generalfeedback>\n";
$expout .= " <generalfeedback format=\"$generalfeedbackformat\">\n";
$expout .= $generalfeedback;
$expout .= $generalfeedback_files;
$expout .= " </generalfeedback>\n";
$expout .= " <defaultgrade>{$question->defaultgrade}</defaultgrade>\n";
$expout .= " <penalty>{$question->penalty}</penalty>\n";
$expout .= " <hidden>{$question->hidden}</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 .= " <answer fraction=\"$fraction_pc\">\n";
$expout .= $this->writetext($answertext, 3) . "\n";
$expout .= " <feedback>\n";
$expout .= $this->writetext( $answer->feedback,4,false );
$feedbackformat = $this->get_format($answer->feedbackformat);
$expout .= " <feedback format=\"$feedbackformat\">\n";
$expout .= $this->writetext($answer->feedback,4,false);
$expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " </feedback>\n";
$expout .= " </answer>\n";
}
@ -908,28 +1092,51 @@ class qformat_xml extends qformat_default {
case MULTICHOICE:
$expout .= " <single>".$this->get_single($question->options->single)."</single>\n";
$expout .= " <shuffleanswers>".$this->get_single($question->options->shuffleanswers)."</shuffleanswers>\n";
$expout .= " <correctfeedback>".$this->writetext($question->options->correctfeedback, 3)."</correctfeedback>\n";
$expout .= " <partiallycorrectfeedback>".$this->writetext($question->options->partiallycorrectfeedback, 3)."</partiallycorrectfeedback>\n";
$expout .= " <incorrectfeedback>".$this->writetext($question->options->incorrectfeedback, 3)."</incorrectfeedback>\n";
$textformat = $this->get_format($question->options->correctfeedbackformat);
$files = $fs->get_area_files($contextid, 'qtype_multichoice', 'correctfeedback', $question->id);
$expout .= " <correctfeedback format=\"$textformat\">\n";
$expout .= $this->writetext($question->options->correctfeedback, 3);
$expout .= $this->writefiles($files);
$expout .= " </correctfeedback>\n";
$textformat = $this->get_format($question->options->partiallycorrectfeedbackformat);
$files = $fs->get_area_files($contextid, 'qtype_multichoice', 'partiallycorrectfeedback', $question->id);
$expout .= " <partiallycorrectfeedback format=\"$textformat\">\n";
$expout .= $this->writetext($question->options->partiallycorrectfeedback, 3);
$expout .= $this->writefiles($files);
$expout .= " </partiallycorrectfeedback>\n";
$textformat = $this->get_format($question->options->incorrectfeedbackformat);
$files = $fs->get_area_files($contextid, 'qtype_multichoice', 'incorrectfeedback', $question->id);
$expout .= " <incorrectfeedback format=\"$textformat\">\n";
$expout .= $this->writetext($question->options->incorrectfeedback, 3);
$expout .= $this->writefiles($files);
$expout .= " </incorrectfeedback>\n";
$expout .= " <answernumbering>".$this->writetext($question->options->answernumbering, 3)."</answernumbering>\n";
foreach($question->options->answers as $answer) {
$percent = $answer->fraction * 100;
$expout .= " <answer fraction=\"$percent\">\n";
$expout .= $this->writetext( $answer->answer,4,false );
$expout .= " <feedback>\n";
$expout .= $this->writetext( $answer->feedback,5,false );
$expout .= $this->writetext($answer->answer,4,false);
$feedbackformat = $this->get_format($answer->feedbackformat);
$expout .= " <feedback format=\"$feedbackformat\">\n";
$expout .= $this->writetext($answer->feedback,5,false);
$expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " </feedback>\n";
$expout .= " </answer>\n";
}
break;
case SHORTANSWER:
$expout .= " <usecase>{$question->options->usecase}</usecase>\n ";
$expout .= " <usecase>{$question->options->usecase}</usecase>\n ";
foreach($question->options->answers as $answer) {
$percent = 100 * $answer->fraction;
$expout .= " <answer fraction=\"$percent\">\n";
$expout .= $this->writetext( $answer->answer,3,false );
$expout .= " <feedback>\n";
$expout .= $this->writetext( $answer->feedback,4,false );
$feedbackformat = $this->get_format($answer->feedbackformat);
$expout .= " <feedback format=\"$feedbackformat\">\n";
$expout .= $this->writetext($answer->feedback);
$expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " </feedback>\n";
$expout .= " </answer>\n";
}
@ -942,7 +1149,11 @@ class qformat_xml extends qformat_default {
// <text> tags are an added feature, old filed won't have them
$expout .= " <text>{$answer->answer}</text>\n";
$expout .= " <tolerance>$tolerance</tolerance>\n";
$expout .= " <feedback>".$this->writetext( $answer->feedback )."</feedback>\n";
$feedbackformat = $this->get_format($answer->feedbackformat);
$expout .= " <feedback format=\"$feedbackformat\">\n";
$expout .= $this->writetext($answer->feedback);
$expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " </feedback>\n";
// fraction tag is deprecated
// $expout .= " <fraction>{$answer->fraction}</fraction>\n";
$expout .= "</answer>\n";
@ -959,12 +1170,25 @@ class qformat_xml extends qformat_default {
}
$expout .= "</units>\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 .= " <instructions format=\"$textformat\">\n";
$expout .= $this->writetext($question->options->instructions, 3);
$expout .= $this->writefiles($files);
$expout .= " </instructions>\n";
}
break;
case MATCH:
foreach($question->options->subquestions as $subquestion) {
$expout .= "<subquestion>\n";
$expout .= $this->writetext( $subquestion->questiontext );
$expout .= "<answer>".$this->writetext( $subquestion->answertext )."</answer>\n";
$files = $fs->get_area_files($contextid, 'qtype_match', 'subquestion', $subquestion->id);
$textformat = $this->get_format($subquestion->questiontextformat);
$expout .= "<subquestion format=\"$textformat\">\n";
$expout .= $this->writetext($subquestion->questiontext);
$expout .= $this->writefiles($files);
$expout .= "<answer>";
$expout .= $this->writetext($subquestion->answertext);
$expout .= "</answer>\n";
$expout .= "</subquestion>\n";
}
break;
@ -985,7 +1209,11 @@ class qformat_xml extends qformat_default {
foreach ($question->options->answers as $answer) {
$percent = 100 * $answer->fraction;
$expout .= "<answer fraction=\"$percent\">\n";
$expout .= " <feedback>".$this->writetext( $answer->feedback )."</feedback>\n";
$feedbackformat = $this->get_format($answer->feedbackformat);
$expout .= " <feedback format=\"$feedbackformat\">\n";
$expout .= $this->writetext($answer->feedback);
$expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " </feedback>\n";
// fraction tag is deprecated
// $expout .= " <fraction>{$answer->fraction}</fraction>\n";
$expout .= "</answer>\n";
@ -999,9 +1227,26 @@ class qformat_xml extends qformat_default {
$expout .= " <single>{$question->options->single}</single>\n";
$expout .= " <answernumbering>{$question->options->answernumbering}</answernumbering>\n";
$expout .= " <shuffleanswers>".$this->writetext($question->options->shuffleanswers, 3)."</shuffleanswers>\n";
$expout .= " <correctfeedback>".$this->writetext($question->options->correctfeedback, 3)."</correctfeedback>\n";
$expout .= " <partiallycorrectfeedback>".$this->writetext($question->options->partiallycorrectfeedback, 3)."</partiallycorrectfeedback>\n";
$expout .= " <incorrectfeedback>".$this->writetext($question->options->incorrectfeedback, 3)."</incorrectfeedback>\n";
$component = 'qtype_' . $question->qtype;
$files = $fs->get_area_files($contextid, $component, 'correctfeedback', $question->id);
$expout .= " <correctfeedback>\n";
$expout .= $this->writetext($question->options->correctfeedback, 3);
$expout .= $this->writefiles($files);
$expout .= " </correctfeedback>\n";
$files = $fs->get_area_files($contextid, $component, 'partiallycorrectfeedback', $question->id);
$expout .= " <partiallycorrectfeedback>\n";
$expout .= $this->writetext($question->options->partiallycorrectfeedback, 3);
$expout .= $this->writefiles($files);
$expout .= " </partiallycorrectfeedback>\n";
$files = $fs->get_area_files($contextid, $component, 'incorrectfeedback', $question->id);
$expout .= " <incorrectfeedback>\n";
$expout .= $this->writetext($question->options->incorrectfeedback, 3);
$expout .= $this->writefiles($files);
$expout .= " </incorrectfeedback>\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>$tolerancetype</tolerancetype>\n";
$expout .= " <correctanswerformat>$correctanswerformat</correctanswerformat>\n";
$expout .= " <correctanswerlength>$correctanswerlength</correctanswerlength>\n";
$expout .= " <feedback>".$this->writetext( $answer->feedback )."</feedback>\n";
$feedbackformat = $this->get_format($answer->feedbackformat);
$expout .= " <feedback format=\"$feedbackformat\">\n";
$expout .= $this->writetext($answer->feedback);
$expout .= $this->writefiles($answer->feedbackfiles);
$expout .= " </feedback>\n";
$expout .= "</answer>\n";
}
$expout .= " <unitgradingtype>{$question->options->unitgradingtype}</unitgradingtype>\n";
$expout .= " <unitpenalty>{$question->options->unitpenalty}</unitpenalty>\n";
$expout .= " <showunits>{$question->options->showunits}</showunits>\n";
$expout .= " <unitsleft>{$question->options->unitsleft}</unitsleft>\n";
$expout .= " <instructions>".$this->writetext($question->options->instructions, 3)."</instructions>\n";
$units = $question->options->units;
if (count($units)) {
$expout .= "<units>\n";
foreach ($units as $unit) {
$expout .= " <unit>\n";
$expout .= " <multiplier>{$unit->multiplier}</multiplier>\n";
$expout .= " <unit_name>{$unit->unit}</unit_name>\n";
$expout .= " </unit>\n";
if (!empty($question->options->unitgradingtype)) {
$expout .= " <unitgradingtype>{$question->options->unitgradingtype}</unitgradingtype>\n";
}
if (!empty($question->options->unitpenalty)) {
$expout .= " <unitpenalty>{$question->options->unitpenalty}</unitpenalty>\n";
}
if (!empty($question->options->showunits)) {
$expout .= " <showunits>{$question->options->showunits}</showunits>\n";
}
if (!empty($question->options->unitsleft)) {
$expout .= " <unitsleft>{$question->options->unitsleft}</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 .= " <instructions format=\"$textformat\">\n";
$expout .= $this->writetext($question->options->instructions, 3);
$expout .= $this->writefiles($files);
$expout .= " </instructions>\n";
}
if (isset($question->options->units)) {
$units = $question->options->units;
if (count($units)) {
$expout .= "<units>\n";
foreach ($units as $unit) {
$expout .= " <unit>\n";
$expout .= " <multiplier>{$unit->multiplier}</multiplier>\n";
$expout .= " <unit_name>{$unit->unit}</unit_name>\n";
$expout .= " </unit>\n";
}
$expout .= "</units>\n";
}
$expout .= "</units>\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 .= "</question>\n";
// XXX: debuging
//echo '<textarea cols=100 rows=20>';
//echo $expout;
//echo '</textarea>';
return $expout;
}
}
?>

View File

@ -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());
}

View File

@ -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));
}

View File

@ -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));
}

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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) {

View File

@ -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 {

View File

@ -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);
}
}
}

View File

@ -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));
}

View File

@ -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));
}