Permalink
Browse files

MDL-29739 question import used a bad default for text formats.

The new logic is that the questiontext defaults to HTML if the format is
not specified, then all other fields default to the same format of the
question text.

However, good practice is that the XML file should specify the format
for each bit of text content.

This code is not 100% backwards-compatible, since some methods have new
arguments, however for question types that have not been updated, it
will just generate a PHP Warning, which is, I think, and OK way to let
qtype developers know that they need to update their question types.
  • Loading branch information...
1 parent f08f22c commit 5eb400105070ea07f7db21bea0df7b51ab413ffb @timhunt timhunt committed Oct 31, 2011
Showing with 92 additions and 98 deletions.
  1. +54 −60 question/format/xml/format.php
  2. +38 −38 question/format/xml/simpletest/testxmlformat.php
@@ -81,7 +81,8 @@ protected function trans_format($name) {
} else if ($name == 'markdown') {
return FORMAT_MARKDOWN;
} else {
- return 0; // or maybe warning required
+ debugging("Unrecognised text format '{$name}' in the import file. Assuming 'html'.");
+ return FORMAT_HTML;
}
}
@@ -171,7 +172,7 @@ public function import_headers($question) {
$qo->questiontext = $this->getpath($question,
array('#', 'questiontext', 0, '#', 'text', 0, '#'), '', true);
$qo->questiontextformat = $this->trans_format($this->getpath(
- $question, array('#', 'questiontext', 0, '@', 'format'), ''));
+ $question, array('#', 'questiontext', 0, '@', 'format'), 'html'));
$qo->questiontextfiles = $this->import_files($this->getpath($question,
array('#', 'questiontext', 0, '#', 'file'), array(), false));
@@ -193,7 +194,7 @@ public function import_headers($question) {
array('#', 'generalfeedback', 0, '#', 'text', 0, '#'), $qo->generalfeedback, true);
$qo->generalfeedbackfiles = array();
$qo->generalfeedbackformat = $this->trans_format($this->getpath($question,
- array('#', 'generalfeedback', 0, '@', 'format'), 'moodle_auto_format'));
+ array('#', 'generalfeedback', 0, '@', 'format'), $this->get_format($qo->questiontextformat)));
$qo->generalfeedbackfiles = $this->import_files($this->getpath($question,
array('#', 'generalfeedback', 0, '#', 'file'), array(), false));
@@ -223,25 +224,31 @@ public function import_headers($question) {
/**
* Import the common parts of a single answer
* @param array answer xml tree for single answer
+ * @param bool $withanswerfiles if true, the answers are HTML (or $defaultformat)
+ * and so may contain files, otherwise the answers are plain text.
+ * @param array Default text format for the feedback, and the answers if $withanswerfiles
+ * is true.
* @return object answer object
*/
- public function import_answer($answer, $withanswerfiles = false) {
+ public function import_answer($answer, $withanswerfiles = false, $defaultformat = 'html') {
$ans = new stdClass();
$ans->answer = array();
$ans->answer['text'] = $this->getpath($answer, array('#', 'text', 0, '#'), '', true);
$ans->answer['format'] = $this->trans_format($this->getpath($answer,
- array('@', 'format'), 'moodle_auto_format'));
+ array('@', 'format'), $defaultformat));
if ($withanswerfiles) {
$ans->answer['files'] = $this->import_files($this->getpath($answer,
array('#', 'file'), array()));
+ } else {
+ $ans->answer['format'] = FORMAT_PLAIN;
}
$ans->feedback = array();
$ans->feedback['text'] = $this->getpath($answer,
array('#', 'feedback', 0, '#', 'text', 0, '#'), '', true);
$ans->feedback['format'] = $this->trans_format($this->getpath($answer,
- array('#', 'feedback', 0, '@', 'format'), 'moodle_auto_format'));
+ array('#', 'feedback', 0, '@', 'format'), $defaultformat));
$ans->feedback['files'] = $this->import_files($this->getpath($answer,
array('#', 'feedback', 0, '#', 'file'), array()));
@@ -263,7 +270,7 @@ public function import_combined_feedback($qo, $questionxml, $withshownumpartscor
$text['text'] = $this->getpath($questionxml,
array('#', $field, 0, '#', 'text', 0, '#'), '', true);
$text['format'] = $this->trans_format($this->getpath($questionxml,
- array('#', $field, 0, '@', 'format'), 'moodle_auto_format'));
+ array('#', $field, 0, '@', 'format'), $this->get_format($qo->questiontextformat)));
$text['files'] = $this->import_files($this->getpath($questionxml,
array('#', $field, 0, '#', 'file'), array(), false));
@@ -284,16 +291,19 @@ public function import_combined_feedback($qo, $questionxml, $withshownumpartscor
/**
* Import a question hint
* @param array $hintxml hint xml fragment.
+ * @param string $defaultformat the text format to assume for hints that do not specify.
* @return object hint for storing in the database.
*/
- public function import_hint($hintxml) {
+ public function import_hint($hintxml, $defaultformat) {
if (array_key_exists('hintcontent', $hintxml['#'])) {
// Backwards compatibility:
$hint = new stdClass();
$hint->hint = array('format' => FORMAT_HTML, 'files' => array());
$hint->hint['text'] = $this->getpath($hintxml,
array('#', 'hintcontent', 0, '#', 'text', 0, '#'), '', true);
+ $hint->hint['format'] = $this->trans_format($defaultformat);
+ $hint->hint['files'] = array();
$hint->shownumcorrect = $this->getpath($hintxml,
array('#', 'statenumberofcorrectresponses', 0, '#'), 0);
$hint->clearwrong = $this->getpath($hintxml,
@@ -308,7 +318,7 @@ public function import_hint($hintxml) {
$hint->hint['text'] = $this->getpath($hintxml,
array('#', 'text', 0, '#'), '', true);
$hint->hint['format'] = $this->trans_format($this->getpath($hintxml,
- array('@', 'format'), 'moodle_auto_format'));
+ array('@', 'format'), $defaultformat));
$hint->hint['files'] = $this->import_files($this->getpath($hintxml,
array('#', 'file'), array(), false));
$hint->shownumcorrect = array_key_exists('shownumcorrect', $hintxml['#']);
@@ -322,15 +332,20 @@ public function import_hint($hintxml) {
* Import all the question hints
*
* @param object $qo the question data that is being constructed.
- * @param array $hintsxml hints xml fragment.
+ * @param array $questionxml The xml representing the question.
+ * @param bool $withparts whether the extra fields relating to parts should be imported.
+ * @param bool $withoptions whether the extra options field should be imported.
+ * @param string $defaultformat the text format to assume for hints that do not specify.
+ * @return array of objects representing the hints in the file.
*/
- public function import_hints($qo, $questionxml, $withparts = false, $withoptions = false) {
+ public function import_hints($qo, $questionxml, $withparts = false,
+ $withoptions = false, $defaultformat = 'html') {
if (!isset($questionxml['#']['hint'])) {
return;
}
foreach ($questionxml['#']['hint'] as $hintxml) {
- $hint = $this->import_hint($hintxml);
+ $hint = $this->import_hint($hintxml, $defaultformat);
$qo->hint[] = $hint->hint;
if ($withparts) {
@@ -390,15 +405,15 @@ public function import_multichoice($question) {
$answers = $question['#']['answer'];
$acount = 0;
foreach ($answers as $answer) {
- $ans = $this->import_answer($answer, true);
+ $ans = $this->import_answer($answer, true, $this->get_format($qo->questiontextformat));
$qo->answer[$acount] = $ans->answer;
$qo->fraction[$acount] = $ans->fraction;
$qo->feedback[$acount] = $ans->feedback;
++$acount;
}
$this->import_combined_feedback($qo, $question, true);
- $this->import_hints($qo, $question, true);
+ $this->import_hints($qo, $question, true, false, $this->get_format($qo->questiontextformat));
return $qo;
}
@@ -412,34 +427,36 @@ public function import_multianswer($question) {
question_bank::get_qtype('multianswer');
$questiontext['text'] = $this->import_text($question['#']['questiontext'][0]['#']['text']);
- $questiontext['format'] = '1';
+ $questiontext['format'] = FORMAT_HTML;
$questiontext['itemid'] = '';
$qo = qtype_multianswer_extract_question($questiontext);
// 'header' parts particular to multianswer
$qo->qtype = 'multianswer';
$qo->course = $this->course;
$qo->generalfeedback = '';
+
+ $qo->name = $this->import_text($question['#']['name'][0]['#']['text']);
+ $qo->questiontextformat = $questiontext['format'];
+ $qo->questiontext = $qo->questiontext['text'];
+ $qo->questiontextfiles = array();
+
// restore files in generalfeedback
$qo->generalfeedback = $this->getpath($question,
array('#', 'generalfeedback', 0, '#', 'text', 0, '#'), $qo->generalfeedback, true);
$qo->generalfeedbackformat = $this->trans_format($this->getpath($question,
- array('#', 'generalfeedback', 0, '@', 'format'), 'moodle_auto_format'));
+ array('#', 'generalfeedback', 0, '@', 'format'), $this->get_format($qo->questiontextformat)));
$qo->generalfeedbackfiles = $this->import_files($this->getpath($question,
array('#', 'generalfeedback', 0, '#', 'file'), array(), false));
- $qo->name = $this->import_text($question['#']['name'][0]['#']['text']);
- $qo->questiontext = $qo->questiontext['text'];
- $qo->questiontextformat = '';
-
$qo->penalty = $this->getpath($question,
array('#', 'penalty', 0, '#'), $this->defaultquestion()->penalty);
// Fix problematic rounding from old files:
if (abs($qo->penalty - 0.3333333) < 0.005) {
$qo->penalty = 0.3333333;
}
- $this->import_hints($qo, $question);
+ $this->import_hints($qo, $question, false, false, $this->get_format($qo->questiontextformat));
return $qo;
}
@@ -469,7 +486,7 @@ public function import_truefalse($question) {
$feedback = $this->getpath($answer,
array('#', 'feedback', 0, '#', 'text', 0, '#'), '', true);
$feedbackformat = $this->getpath($answer,
- array('#', 'feedback', 0, '@', 'format'), 'moodle_auto_format');
+ array('#', 'feedback', 0, '@', 'format'), $this->get_format($qo->questiontextformat));
$feedbackfiles = $this->getpath($answer,
array('#', 'feedback', 0, '#', 'file'), array());
$files = array();
@@ -515,7 +532,7 @@ public function import_truefalse($question) {
echo $OUTPUT->notification(get_string('truefalseimporterror', 'qformat_xml', $a));
}
- $this->import_hints($qo, $question);
+ $this->import_hints($qo, $question, false, false, $this->get_format($qo->questiontextformat));
return $qo;
}
@@ -539,14 +556,14 @@ public function import_shortanswer($question) {
$answers = $question['#']['answer'];
$acount = 0;
foreach ($answers as $answer) {
- $ans = $this->import_answer($answer);
+ $ans = $this->import_answer($answer, false, $this->get_format($qo->questiontextformat));
$qo->answer[$acount] = $ans->answer['text'];
$qo->fraction[$acount] = $ans->fraction;
$qo->feedback[$acount] = $ans->feedback;
++$acount;
}
- $this->import_hints($qo, $question);
+ $this->import_hints($qo, $question, false, false, $this->get_format($qo->questiontextformat));
return $qo;
}
@@ -586,7 +603,7 @@ public function import_numerical($question) {
$qo->tolerance = array();
foreach ($answers as $answer) {
// answer outside of <text> is deprecated
- $obj = $this->import_answer($answer);
+ $obj = $this->import_answer($answer, false, $this->get_format($qo->questiontextformat));
$qo->answer[] = $obj->answer['text'];
if (empty($qo->answer)) {
$qo->answer = '*';
@@ -622,12 +639,12 @@ public function import_numerical($question) {
$qo->instructions['text'] = $this->getpath($instructions,
array('0', '#', 'text', '0', '#'), '', true);
$qo->instructions['format'] = $this->trans_format($this->getpath($instructions,
- array('0', '@', 'format'), 'moodle_auto_format'));
+ array('0', '@', 'format'), $this->get_format($qo->questiontextformat)));
$qo->instructions['files'] = $this->import_files($this->getpath(
$instructions, array('0', '#', 'file'), array()));
}
- $this->import_hints($qo, $question);
+ $this->import_hints($qo, $question, false, false, $this->get_format($qo->questiontextformat));
return $qo;
}
@@ -653,7 +670,7 @@ public function import_match($question) {
$subquestion = array();
$subquestion['text'] = $this->getpath($subqxml, array('#', 'text', 0, '#'), '', true);
$subquestion['format'] = $this->trans_format($this->getpath($subqxml,
- array('@', 'format'), 'moodle_auto_format'));
+ array('@', 'format'), $this->get_format($qo->questiontextformat)));
$subquestion['files'] = $this->import_files($this->getpath($subqxml,
array('#', 'file'), array()));
@@ -664,7 +681,7 @@ public function import_match($question) {
}
$this->import_combined_feedback($qo, $question, true);
- $this->import_hints($qo, $question, true);
+ $this->import_hints($qo, $question, true, false, $this->get_format($qo->questiontextformat));
return $qo;
}
@@ -690,7 +707,7 @@ public function import_essay($question) {
$qo->graderinfo['text'] = $this->getpath($question,
array('#', 'graderinfo', 0, '#', 'text', 0, '#'), '', true);
$qo->graderinfo['format'] = $this->trans_format($this->getpath($question,
- array('#', 'graderinfo', 0, '@', 'format'), 'moodle_auto_format'));
+ array('#', 'graderinfo', 0, '@', 'format'), $this->get_format($qo->questiontextformat)));
$qo->graderinfo['files'] = $this->import_files($this->getpath($question,
array('#', 'graderinfo', '0', '#', 'file'), array()));
@@ -716,30 +733,7 @@ public function import_calculated($question) {
array('#', 'answernumbering', 0, '#'), 'abc');
$qo->shuffleanswers = $this->trans_single($shuffleanswers);
- $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'), 'moodle_auto_format'));
- $qo->correctfeedback['files'] = $this->import_files($this->getpath(
- $question, array('#', 'correctfeedback', '0', '#', 'file'), array()));
-
- $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'),
- 'moodle_auto_format'));
- $qo->partiallycorrectfeedback['files'] = $this->import_files($this->getpath(
- $question, array('#', 'partiallycorrectfeedback', '0', '#', 'file'), array()));
-
- $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'), 'moodle_auto_format'));
- $qo->incorrectfeedback['files'] = $this->import_files($this->getpath($question,
- array('#', 'incorrectfeedback', '0', '#', 'file'), array()));
+ $this->import_combined_feedback($qo, $question);
$qo->unitgradingtype = $this->getpath($question,
array('#', 'unitgradingtype', 0, '#'), 0);
@@ -753,7 +747,7 @@ public function import_calculated($question) {
$qo->instructions['text'] = $this->getpath($instructions,
array('0', '#', 'text', '0', '#'), '', true);
$qo->instructions['format'] = $this->trans_format($this->getpath($instructions,
- array('0', '@', 'format'), 'moodle_auto_format'));
+ array('0', '@', 'format'), $this->get_format($qo->questiontextformat)));
$qo->instructions['files'] = $this->import_files($this->getpath($instructions,
array('0', '#', 'file'), array()));
}
@@ -769,7 +763,7 @@ public function import_calculated($question) {
$qo->correctanswerlength = array();
$qo->feedback = array();
foreach ($answers as $answer) {
- $ans = $this->import_answer($answer, true);
+ $ans = $this->import_answer($answer, true, $this->get_format($qo->questiontextformat));
// answer outside of <text> is deprecated
if (empty($ans->answer['text'])) {
$ans->answer['text'] = '*';
@@ -803,7 +797,7 @@ public function import_calculated($question) {
$qo->instructions['text'] = $this->getpath($instructions,
array('0', '#', 'text', '0', '#'), '', true);
$qo->instructions['format'] = $this->trans_format($this->getpath($instructions,
- array('0', '@', 'format'), 'moodle_auto_format'));
+ array('0', '@', 'format'), $this->get_format($qo->questiontextformat)));
$qo->instructions['files'] = $this->import_files($this->getpath($instructions,
array('0', '#', 'file'), array()));
}
@@ -848,7 +842,7 @@ public function import_calculated($question) {
}
}
- $this->import_hints($qo, $question);
+ $this->import_hints($qo, $question, false, false, $this->get_format($qo->questiontextformat));
return $qo;
}
@@ -970,7 +964,7 @@ protected function get_qtype($qtype) {
* @param int id internal code
* @return string format text
*/
- protected function get_format($id) {
+ public function get_format($id) {
switch($id) {
case FORMAT_MOODLE:
return 'moodle_auto_format';
Oops, something went wrong. Retry.

0 comments on commit 5eb4001

Please sign in to comment.