Merged from STABLE
This commit is contained in:
+153
-133
@@ -20,9 +20,13 @@ class qformat_xml extends qformat_default {
|
||||
|
||||
// IMPORT FUNCTIONS START HERE
|
||||
|
||||
/*
|
||||
* Translate human readable format name
|
||||
* into internal Moodle code number
|
||||
* @PARAM string name format name from xml file
|
||||
* @RETURN int Moodle format code
|
||||
*/
|
||||
function trans_format( $name ) {
|
||||
// translate text format string to its internal code
|
||||
|
||||
$name = trim($name);
|
||||
|
||||
if ($name=='moodle_auto_format') {
|
||||
@@ -46,9 +50,13 @@ class qformat_xml extends qformat_default {
|
||||
return $id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate human readable single answer option
|
||||
* to internal code number
|
||||
* @PARAM string name true/false
|
||||
* @RETURN int internal code number
|
||||
*/
|
||||
function trans_single( $name ) {
|
||||
// translate single string to its internal format
|
||||
|
||||
$name = trim($name);
|
||||
|
||||
if ($name=="true") {
|
||||
@@ -63,16 +71,23 @@ class qformat_xml extends qformat_default {
|
||||
return $id;
|
||||
}
|
||||
|
||||
/*
|
||||
* process text string from xml file
|
||||
* @PARAM array text bit of xml tree after ['text']
|
||||
* @RETURN string processed text
|
||||
*/
|
||||
function import_text( $text ) {
|
||||
// handle xml 'text' element
|
||||
$data = $text[0]['#'];
|
||||
$data = html_entity_decode( $data );
|
||||
return addslashes(trim( $data ));
|
||||
}
|
||||
|
||||
/*
|
||||
* import parts of question common to all types
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_headers( $question ) {
|
||||
// read bits that are common to all questions
|
||||
|
||||
// this routine initialises the question object
|
||||
$name = $this->import_text( $question['#']['name'][0]['#']['text'] );
|
||||
$qtext = $this->import_text( $question['#']['questiontext'][0]['#']['text'] );
|
||||
@@ -87,6 +102,9 @@ class qformat_xml extends qformat_default {
|
||||
} else {
|
||||
$commentarytext = '';
|
||||
}
|
||||
if (!empty($question['#']['defaultgrade'][0]['#'])) {
|
||||
$qo->defaultgrade = $question['#']['defaultgrade'][0]['#'];
|
||||
}
|
||||
$penalty = $question['#']['penalty'][0]['#'];
|
||||
|
||||
$qo = $this->defaultquestion();
|
||||
@@ -100,10 +118,12 @@ class qformat_xml extends qformat_default {
|
||||
return $qo;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* import the common parts of a single answer
|
||||
* @PARAM array answer xml tree for single answer
|
||||
* @RETURN object answer object
|
||||
*/
|
||||
function import_answer( $answer ) {
|
||||
// import answer part of question
|
||||
|
||||
$fraction = $answer['@']['fraction'];
|
||||
$text = $this->import_text( $answer['#']['text']);
|
||||
$feedback = $this->import_text( $answer['#']['feedback'][0]['#']['text'] );
|
||||
@@ -116,9 +136,12 @@ class qformat_xml extends qformat_default {
|
||||
return $ans;
|
||||
}
|
||||
|
||||
/*
|
||||
* import multiple choice question
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_multichoice( $question ) {
|
||||
// import multichoice type questions
|
||||
|
||||
// get common parts
|
||||
$qo = $this->import_headers( $question );
|
||||
|
||||
@@ -141,9 +164,12 @@ class qformat_xml extends qformat_default {
|
||||
return $qo;
|
||||
}
|
||||
|
||||
/*
|
||||
* import cloze type question
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_multianswer( $questions ) {
|
||||
// import multianswer (cloze) type questions
|
||||
|
||||
$qo = qtype_multianswer_extract_question($this->import_text(
|
||||
$questions['#']['questiontext'][0]['#']['text'] ));
|
||||
|
||||
@@ -158,9 +184,12 @@ class qformat_xml extends qformat_default {
|
||||
return $qo;
|
||||
}
|
||||
|
||||
/*
|
||||
* import true/false type question
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_truefalse( $question ) {
|
||||
// import true/false type question
|
||||
|
||||
// get common parts
|
||||
$qo = $this->import_headers( $question );
|
||||
|
||||
@@ -189,9 +218,12 @@ class qformat_xml extends qformat_default {
|
||||
return $qo;
|
||||
}
|
||||
|
||||
/*
|
||||
* import short answer type question
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_shortanswer( $question ) {
|
||||
// import short answer question
|
||||
|
||||
// get common parts
|
||||
$qo = $this->import_headers( $question );
|
||||
|
||||
@@ -215,9 +247,12 @@ class qformat_xml extends qformat_default {
|
||||
return $qo;
|
||||
}
|
||||
|
||||
/*
|
||||
* import regexp type question
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_regexp( $question ) {
|
||||
// import short answer question
|
||||
|
||||
// get common parts
|
||||
$qo = $this->import_headers( $question );
|
||||
|
||||
@@ -241,6 +276,11 @@ class qformat_xml extends qformat_default {
|
||||
return $qo;
|
||||
}
|
||||
|
||||
/*
|
||||
* import description type question
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_description( $question ) {
|
||||
// get common parts
|
||||
$qo = $this->import_headers( $question );
|
||||
@@ -248,9 +288,13 @@ class qformat_xml extends qformat_default {
|
||||
$qo->qtype = DESCRIPTION;
|
||||
return $qo;
|
||||
}
|
||||
function import_numerical( $question ) {
|
||||
// import numerical question
|
||||
|
||||
/*
|
||||
* import numerical type question
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_numerical( $question ) {
|
||||
// get common parts
|
||||
$qo = $this->import_headers( $question );
|
||||
|
||||
@@ -283,9 +327,12 @@ class qformat_xml extends qformat_default {
|
||||
return $qo;
|
||||
}
|
||||
|
||||
/*
|
||||
* import matching type question
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_matching( $question ) {
|
||||
// import matching question
|
||||
|
||||
// get common parts
|
||||
$qo = $this->import_headers( $question );
|
||||
|
||||
@@ -312,11 +359,35 @@ class qformat_xml extends qformat_default {
|
||||
return $qo;
|
||||
}
|
||||
|
||||
function readquestions($lines) {
|
||||
// parse the array of lines into an array of questions
|
||||
// this *could* burn memory - but it won't happen that much
|
||||
// so fingers crossed!
|
||||
/*
|
||||
* import essay type question
|
||||
* @PARAM array question question array from xml tree
|
||||
* @RETURN object question object
|
||||
*/
|
||||
function import_essay( $question ) {
|
||||
// get common parts
|
||||
$qo = $this->import_headers( $question );
|
||||
|
||||
// header parts particular to essay
|
||||
$qo->qtype = ESSAY;
|
||||
|
||||
// get feedback
|
||||
$qo->feedback = $this->import_text( $question['#']['answer'][0]['#']['feedback'][0]['#']['text'] );
|
||||
|
||||
// get fraction
|
||||
$qo->fraction = $question['#']['answer'][0]['#']['fraction'][0]['#'];
|
||||
|
||||
return $qo;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse the array of lines into an array of questions
|
||||
* this *could* burn memory - but it won't happen that much
|
||||
* so fingers crossed!
|
||||
* @PARAM array lines array of lines from the input file
|
||||
* @RETURN array (of objects) question objects
|
||||
*/
|
||||
function readquestions($lines) {
|
||||
// we just need it as one big string
|
||||
$text = implode($lines, " ");
|
||||
unset( $lines );
|
||||
@@ -333,7 +404,6 @@ class qformat_xml extends qformat_default {
|
||||
foreach ($xml['quiz']['#']['question'] as $question) {
|
||||
$question_type = $question['@']['type'];
|
||||
$questiontype = get_string( 'questiontype','quiz',$question_type );
|
||||
// echo "<p>$questiontype</p>";
|
||||
|
||||
if ($question_type=='multichoice') {
|
||||
$qo = $this->import_multichoice( $question );
|
||||
@@ -357,7 +427,10 @@ class qformat_xml extends qformat_default {
|
||||
$qo = $this->import_matching( $question );
|
||||
}
|
||||
elseif ($question_type=='cloze') {
|
||||
$qo = $this->import_multianswer( $question );
|
||||
$qo = $this->import_multianswer( $question );
|
||||
}
|
||||
elseif ($question_type=='essay') {
|
||||
$qo = $this->import_essay( $question );
|
||||
}
|
||||
else {
|
||||
$notsupported = get_string( 'xmltypeunsupported','quiz',$question_type );
|
||||
@@ -376,101 +449,21 @@ class qformat_xml extends qformat_default {
|
||||
|
||||
// EXPORT FUNCTIONS START HERE
|
||||
|
||||
function indent_xhtml($source, $indenter = ' ') {
|
||||
// xml tidier-upper
|
||||
// (c) Ari Koivula http://ventionline.com
|
||||
|
||||
// Remove all pre-existing formatting.
|
||||
// Remove all newlines.
|
||||
$source = str_replace("\n", '', $source);
|
||||
$source = str_replace("\r", '', $source);
|
||||
// Remove all tabs.
|
||||
$source = str_replace("\t", '', $source);
|
||||
// Remove all space after ">" and before "<".
|
||||
$source = ereg_replace(">( )*", ">", $source);
|
||||
$source = ereg_replace("( )*<", "<", $source);
|
||||
|
||||
// Iterate through the source.
|
||||
$level = 0;
|
||||
$source_len = strlen($source);
|
||||
$pt = 0;
|
||||
while ($pt < $source_len) {
|
||||
if ($source{$pt} === '<') {
|
||||
// We have entered a tag.
|
||||
// Remember the point where the tag starts.
|
||||
$started_at = $pt;
|
||||
$tag_level = 1;
|
||||
// If the second letter of the tag is "/", assume its an ending tag.
|
||||
if ($source{$pt+1} === '/') {
|
||||
$tag_level = -1;
|
||||
}
|
||||
// If the second letter of the tag is "!", assume its an "invisible" tag.
|
||||
if ($source{$pt+1} === '!') {
|
||||
$tag_level = 0;
|
||||
}
|
||||
// Iterate throught the source until the end of tag.
|
||||
while ($source{$pt} !== '>') {
|
||||
$pt++;
|
||||
}
|
||||
// If the second last letter is "/", assume its a self ending tag.
|
||||
if ($source{$pt-1} === '/') {
|
||||
$tag_level = 0;
|
||||
}
|
||||
$tag_lenght = $pt+1-$started_at;
|
||||
|
||||
// Decide the level of indention for this tag.
|
||||
// If this was an ending tag, decrease indent level for this tag..
|
||||
if ($tag_level === -1) {
|
||||
$level--;
|
||||
}
|
||||
// Place the tag in an array with proper indention.
|
||||
$array[] = str_repeat($indenter, $level).substr($source, $started_at, $tag_lenght);
|
||||
// If this was a starting tag, increase the indent level after this tag.
|
||||
if ($tag_level === 1) {
|
||||
$level++;
|
||||
}
|
||||
// if it was a self closing tag, dont do shit.
|
||||
}
|
||||
// Were out of the tag.
|
||||
// If next letter exists...
|
||||
if (($pt+1) < $source_len) {
|
||||
// ... and its not an "<".
|
||||
if ($source{$pt+1} !== '<') {
|
||||
$started_at = $pt+1;
|
||||
// Iterate through the source until the start of new tag or until we reach the end of file.
|
||||
while ($source{$pt} !== '<' && $pt < $source_len) {
|
||||
$pt++;
|
||||
}
|
||||
// If we found a "<" (we didnt find the end of file)
|
||||
if ($source{$pt} === '<') {
|
||||
$tag_lenght = $pt-$started_at;
|
||||
// Place the stuff in an array with proper indention.
|
||||
$array[] = str_repeat($indenter, $level).substr($source, $started_at, $tag_lenght);
|
||||
}
|
||||
// If the next tag is "<", just advance pointer and let the tag indenter take care of it.
|
||||
} else {
|
||||
$pt++;
|
||||
}
|
||||
// If the next letter doesnt exist... Were done... well, almost..
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Replace old source with the new one we just collected into our array.
|
||||
$source = implode($array, "\n");
|
||||
return $source;
|
||||
}
|
||||
|
||||
|
||||
function export_file_extension() {
|
||||
// override default type so extension is .xml
|
||||
|
||||
return ".xml";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Turn the internal question code into a human readable form
|
||||
* (The code used to be numeric, but this remains as some of
|
||||
* the names don't match the new internal format)
|
||||
* @PARAM mixed type_id Internal code
|
||||
* @RETURN string question type string
|
||||
*/
|
||||
function get_qtype( $type_id ) {
|
||||
// translates question type code number into actual name
|
||||
|
||||
switch( $type_id ) {
|
||||
case TRUEFALSE:
|
||||
$name = 'truefalse';
|
||||
@@ -496,15 +489,22 @@ class qformat_xml extends qformat_default {
|
||||
case MULTIANSWER:
|
||||
$name = 'cloze';
|
||||
break;
|
||||
case ESSAY:
|
||||
$name = 'essay';
|
||||
break;
|
||||
default:
|
||||
$name = 'unknown';
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert internal Moodle text format code into
|
||||
* human readable form
|
||||
* @PARAM int id internal code
|
||||
* @RETURN string format text
|
||||
*/
|
||||
function get_format( $id ) {
|
||||
// translates question text format id number into something sensible
|
||||
|
||||
switch( $id ) {
|
||||
case 0:
|
||||
$name = "moodle_auto_format";
|
||||
@@ -527,9 +527,13 @@ class qformat_xml extends qformat_default {
|
||||
return $name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert internal single question code into
|
||||
* human readable form
|
||||
* @PARAM int id single question code
|
||||
* @RETURN string single question string
|
||||
*/
|
||||
function get_single( $id ) {
|
||||
// translate single value into something sensible
|
||||
|
||||
switch( $id ) {
|
||||
case 0:
|
||||
$name = "false";
|
||||
@@ -543,10 +547,13 @@ class qformat_xml extends qformat_default {
|
||||
return $name;
|
||||
}
|
||||
|
||||
/*
|
||||
* generates <text></text> tags, processing raw text therein
|
||||
* @PARAM int ilev the current indent level
|
||||
* @PARAM boolean short stick it on one line
|
||||
* @RETURN string formatted text
|
||||
*/
|
||||
function writetext( $raw, $ilev=0, $short=true) {
|
||||
// generates <text></text> tags, processing raw text therein
|
||||
// $ilev is the current indent level
|
||||
// $short=true sticks it on one line
|
||||
$indent = str_repeat( " ",$ilev );
|
||||
|
||||
// encode the text to 'disguise' HTML content
|
||||
@@ -573,8 +580,12 @@ 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 ) {
|
||||
// includes image in base64
|
||||
global $CFG;
|
||||
|
||||
if (empty($imagepath)) {
|
||||
@@ -591,10 +602,12 @@ class qformat_xml extends qformat_default {
|
||||
return $content;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turns question into an xml segment
|
||||
* @PARAM array question question array
|
||||
* @RETURN string xml segment
|
||||
*/
|
||||
function writequestion( $question ) {
|
||||
// turns question into string
|
||||
// question reflects database fields for general question and specific to type
|
||||
|
||||
// initial string;
|
||||
$expout = "";
|
||||
|
||||
@@ -620,6 +633,7 @@ class qformat_xml extends qformat_default {
|
||||
$expout .= " <commentarytext>\n";
|
||||
$expout .= $commentary_text;
|
||||
$expout .= " </commentarytext>\n";
|
||||
$expout .= " <defaultgrade>{$question->defaultgrade}</defaultgrade>\n";
|
||||
$expout .= " <penalty>{$question->penalty}</penalty>\n";
|
||||
$expout .= " <hidden>{$question->hidden}</hidden>\n";
|
||||
}
|
||||
@@ -723,7 +737,7 @@ class qformat_xml extends qformat_default {
|
||||
}
|
||||
break;
|
||||
case DESCRIPTION:
|
||||
// nothing more to do for theis type
|
||||
// nothing more to do for this type
|
||||
break;
|
||||
case MULTIANSWER:
|
||||
$a_count=1;
|
||||
@@ -734,6 +748,15 @@ class qformat_xml extends qformat_default {
|
||||
$a_count++;
|
||||
}
|
||||
break;
|
||||
case ESSAY:
|
||||
foreach ($question->options->answers as $answer) {
|
||||
$expout .= "<answer>\n";
|
||||
$expout .= " <feedback>".$this->writetext( $answer->feedback )."</feedback>\n";
|
||||
$expout .= " <fraction>{$answer->fraction}</fraction>\n";
|
||||
$expout .= "</answer>\n";
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
$expout .= "<!-- Question type is unknown or not supported (Type=$question->qtype) -->\n";
|
||||
}
|
||||
@@ -741,9 +764,6 @@ class qformat_xml extends qformat_default {
|
||||
// close the question tag
|
||||
$expout .= "</question>\n";
|
||||
|
||||
// run through xml tidy function
|
||||
// $tidy_expout = $this->indent_xhtml( $expout, ' ' ) . "\n\n";
|
||||
|
||||
return $expout;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user