From a129b76cc347c6422c88bd129646f0a4819df060 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Fri, 24 Aug 2012 14:19:27 +0100 Subject: [PATCH] MDL-32464 qformat multianswer: fix missing include. Also, add a sample file that can be used for testing, and add a unit test to verify this is working. --- question/format/multianswer/format.php | 31 ++++---- .../tests/fixtures/questions.multianswer.txt | 8 ++ .../tests/multianswerformat_test.php | 76 +++++++++++++++++++ question/type/multianswer/questiontype.php | 6 +- 4 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 question/format/multianswer/tests/fixtures/questions.multianswer.txt create mode 100644 question/format/multianswer/tests/multianswerformat_test.php diff --git a/question/format/multianswer/format.php b/question/format/multianswer/format.php index 45179d8d9f6..d7a7ac788a4 100644 --- a/question/format/multianswer/format.php +++ b/question/format/multianswer/format.php @@ -17,10 +17,9 @@ /** * Embedded answer (Cloze) question importer. * - * @package qformat - * @subpackage multianswer - * @copyright 2003 Henrik Kaipe - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package qformat_multianswer + * @copyright 2003 Henrik Kaipe + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -31,32 +30,36 @@ defined('MOODLE_INTERNAL') || die(); * Importer that imports a text file containing a single Multianswer question * from a text file. * - * @copyright 2003 Henrik Kaipe - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2003 Henrik Kaipe + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class qformat_multianswer extends qformat_default { public function provide_import() { - return true; + return true; } - protected function readquestions($lines) { + public function readquestions($lines) { + question_bank::get_qtype('multianswer'); // Ensure the multianswer code is loaded. + // For this class the method has been simplified as // there can never be more than one question for a - // multianswer import + // multianswer import. $questions = array(); $questiontext = array(); $questiontext['text'] = implode('', $lines); - $questiontext['format'] = 0 ; + $questiontext['format'] = FORMAT_MOODLE; $questiontext['itemid'] = ''; $question = qtype_multianswer_extract_question($questiontext); - $question->questiontext = $question->questiontext['text'] ; - $question->questiontextformat = 0 ; + $question->questiontext = $question->questiontext['text']; + $question->questiontextformat = 0; - $question->qtype = MULTIANSWER; + $question->qtype = 'multianswer'; $question->generalfeedback = ''; - $question->course = $this->course; + $question->generalfeedbackformat = FORMAT_MOODLE; + $question->length = 1; + $question->penalty = 0.3333333; if (!empty($question)) { $name = html_to_text(implode(' ', $lines)); diff --git a/question/format/multianswer/tests/fixtures/questions.multianswer.txt b/question/format/multianswer/tests/fixtures/questions.multianswer.txt new file mode 100644 index 00000000000..57a56a975f2 --- /dev/null +++ b/question/format/multianswer/tests/fixtures/questions.multianswer.txt @@ -0,0 +1,8 @@ +Match the following cities with the correct state: +* San Francisco: {1:MULTICHOICE:=California#OK~Arizona#Wrong} +* Tucson: {1:MULTICHOICE:California#Wrong~%100%Arizona#OK} +* Los Angeles: {1:MULTICHOICE:=California#OK~Arizona#Wrong} +* Phoenix: {1:MULTICHOICE:%0%California#Wrong~=Arizona#OK} +The capital of France is {1:SHORTANSWER:%100%Paris#Congratulations! +~%50%Marseille#No, that is the second largest city in France (after +Paris).~*#Wrong answer. The capital of France is Paris, of course.}. diff --git a/question/format/multianswer/tests/multianswerformat_test.php b/question/format/multianswer/tests/multianswerformat_test.php new file mode 100644 index 00000000000..29c32241cb1 --- /dev/null +++ b/question/format/multianswer/tests/multianswerformat_test.php @@ -0,0 +1,76 @@ +. + +/** + * Unit tests for the Embedded answer (Cloze) question importer. + * + * @package qformat_multianswer + * @copyright 2012 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->libdir . '/questionlib.php'); +require_once($CFG->dirroot . '/question/format.php'); +require_once($CFG->dirroot . '/question/format/multianswer/format.php'); +require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); + + +/** + * Unit tests for the Embedded answer (Cloze) question importer. + * + * @copyright 2012 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qformat_multianswer_test extends question_testcase { + + public function test_import() { + $lines = file(__DIR__ . '/fixtures/questions.multianswer.txt'); + + $importer = new qformat_multianswer(); + $qs = $importer->readquestions($lines); + + $expectedq = (object) array( + 'name' => 'Match the following cities with the ...', + 'questiontext' => 'Match the following cities with the correct state: +* San Francisco: {#1} +* Tucson: {#2} +* Los Angeles: {#3} +* Phoenix: {#4} +The capital of France is {#5}. +', + 'questiontextformat' => FORMAT_MOODLE, + 'generalfeedback' => '', + 'generalfeedbackformat' => FORMAT_MOODLE, + 'qtype' => 'multianswer', + 'defaultmark' => 5, + 'penalty' => 0.3333333, + 'length' => 1, + ); + + $this->assertEquals(1, count($qs)); + $this->assert(new question_check_specified_fields_expectation($expectedq), $qs[0]); + + $this->assertEquals('multichoice', $qs[0]->options->questions[1]->qtype); + $this->assertEquals('multichoice', $qs[0]->options->questions[2]->qtype); + $this->assertEquals('multichoice', $qs[0]->options->questions[3]->qtype); + $this->assertEquals('multichoice', $qs[0]->options->questions[4]->qtype); + $this->assertEquals('shortanswer', $qs[0]->options->questions[5]->qtype); + } +} diff --git a/question/type/multianswer/questiontype.php b/question/type/multianswer/questiontype.php index c87e8e7012e..b39848d8b7a 100644 --- a/question/type/multianswer/questiontype.php +++ b/question/type/multianswer/questiontype.php @@ -304,7 +304,7 @@ function qtype_multianswer_extract_question($text) { $question->defaultmark = 0; // Will be increased for each answer norm for ($positionkey = 1; - preg_match('/'.ANSWER_REGEX.'/', $question->questiontext['text'], $answerregs); + preg_match('/'.ANSWER_REGEX.'/s', $question->questiontext['text'], $answerregs); ++$positionkey) { $wrapped = new stdClass(); $wrapped->generalfeedback['text'] = ''; @@ -390,7 +390,7 @@ function qtype_multianswer_extract_question($text) { $answerindex = 0; $remainingalts = $answerregs[ANSWER_REGEX_ALTERNATIVES]; - while (preg_match('/~?'.ANSWER_ALTERNATIVE_REGEX.'/', $remainingalts, $altregs)) { + while (preg_match('/~?'.ANSWER_ALTERNATIVE_REGEX.'/s', $remainingalts, $altregs)) { if ('=' == $altregs[ANSWER_ALTERNATIVE_REGEX_FRACTION]) { $wrapped->fraction["$answerindex"] = '1'; } else if ($percentile = $altregs[ANSWER_ALTERNATIVE_REGEX_PERCENTILE_FRACTION]) { @@ -412,7 +412,7 @@ function qtype_multianswer_extract_question($text) { } if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_NUMERICAL]) - && preg_match('~'.NUMERICAL_ALTERNATIVE_REGEX.'~', + && preg_match('~'.NUMERICAL_ALTERNATIVE_REGEX.'~s', $altregs[ANSWER_ALTERNATIVE_REGEX_ANSWER], $numregs)) { $wrapped->answer[] = $numregs[NUMERICAL_CORRECT_ANSWER]; if (array_key_exists(NUMERICAL_ABS_ERROR_MARGIN, $numregs)) {