Merge branch 'MDL-37068_23' of git://github.com/timhunt/moodle into MOODLE_23_STABLE
[moodle.git] / question / format / learnwise / format.php
CommitLineData
14e31fa3 1<?php
d3603157
TH
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
41a89a07 17/**
d3603157
TH
18 * Examview question importer.
19 *
20 * @package qformat
21 * @subpackage learnwise
22 * @copyright 2005 Alton College, Hampshire, UK
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41a89a07 24 */
f5565b69 25
d3603157 26
a17b297d
TH
27defined('MOODLE_INTERNAL') || die();
28
29
d3603157
TH
30/**
31 * Examview question importer.
32 *
33 * Alton College, Hampshire, UK - Tom Flannaghan, Andrew Walker
34 *
5e8a85aa 35 * Imports learnwise multiple choice questions (single and multiple answers)
d3603157
TH
36 * currently ignores the deduct attribute for multiple answer questions
37 * deductions are currently simply found by dividing the award for the incorrect
38 * answer by the total number of options
39 *
40 * @copyright 2005 Alton College, Hampshire, UK
41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42 */
f5565b69 43class qformat_learnwise extends qformat_default {
44
18651b0b 45 public function provide_import() {
d3603157 46 return true;
f5565b69 47 }
48
18651b0b
TH
49 public function export_file_extension() {
50 return '.xml';
51 }
52
4d188926 53 protected function readquestions($lines) {
f5565b69 54 $questions = array();
55 $currentquestion = array();
2befe778 56
f5565b69 57 foreach($lines as $line) {
58 $line = trim($line);
59 $currentquestion[] = $line;
2befe778 60
f5565b69 61 if ($question = $this->readquestion($currentquestion)) {
62 $questions[] = $question;
63 $currentquestion = array();
64 }
2befe778 65 }
f5565b69 66 return $questions;
67 }
68
18651b0b 69 protected function readquestion($lines) {
f5565b69 70 $text = implode(' ', $lines);
18651b0b 71 $text = str_replace(array('\t','\n','\r'), array('','',''), $text);
f5565b69 72
73 $startpos = strpos($text, '<question type');
74 $endpos = strpos($text, '</question>');
75 if ($startpos === false || $endpos === false) {
76 return false;
77 }
78
79 preg_match("/<question type=[\"\']([^\"\']+)[\"\']>/i", $text, $matches);
80 $type = strtolower($matches[1]); // multichoice or multianswerchoice
81
18651b0b
TH
82 $questiontext = textlib::entities_to_utf8($this->stringbetween($text, '<text>', '</text>'));
83 $questionhint = textlib::entities_to_utf8($this->stringbetween($text, '<hint>', '</hint>'));
f5565b69 84 $questionaward = $this->stringbetween($text, '<award>', '</award>');
85 $optionlist = $this->stringbetween($text, '<answer>', '</answer>');
86
87 $optionlist = explode('<option', $optionlist);
88
89 $n = 0;
90
91 $optionscorrect = array();
92 $optionstext = array();
93
94 if ($type == 'multichoice') {
95 foreach ($optionlist as $option) {
18651b0b
TH
96 if (trim($option) === '') {
97 continue;
98 }
f5565b69 99 $correct = $this->stringbetween($option, ' correct="', '">');
100 $answer = $this->stringbetween($option, '">', '</option>');
aeb15530 101 $optionscorrect[$n] = $correct;
18651b0b 102 $optionstext[$n] = textlib::entities_to_utf8($answer);
f5565b69 103 ++$n;
104 }
105 } else if ($type == 'multianswerchoice') {
106 $numcorrect = 0;
107 $totalaward = 0;
108
109 $optionsaward = array();
110
111 foreach ($optionlist as $option) {
18651b0b
TH
112 if (trim($option) === '') {
113 continue;
114 }
f5565b69 115 preg_match("/correct=\"([^\"]*)\"/i", $option, $correctmatch);
116 preg_match("/award=\"([^\"]*)\"/i", $option, $awardmatch);
117
118 $correct = $correctmatch[1];
119 $award = $awardmatch[1];
120 if ($correct == 'yes') {
121 $totalaward += $award;
122 ++$numcorrect;
123 }
124
125 $answer = $this->stringbetween($option, '">', '</option>');
126
aeb15530 127 $optionscorrect[$n] = $correct;
18651b0b 128 $optionstext[$n] = textlib::entities_to_utf8($answer);
f5565b69 129 $optionsaward[$n] = $award;
130 ++$n;
131 }
132
133 } else {
134 echo "<p>I don't understand this question type (type = <strong>$type</strong>).</p>\n";
135 }
136
137 $question = $this->defaultquestion();
138 $question->qtype = MULTICHOICE;
5df0a6b4 139 $question->name = $this->create_default_question_name($questiontext, get_string('questionname', 'question'));
18651b0b 140 $this->add_blank_combined_feedback($question);
f5565b69 141
142 $question->questiontext = $questiontext;
18651b0b 143 $question->questiontextformat = FORMAT_HTML;
f5565b69 144 $question->single = ($type == 'multichoice') ? 1 : 0;
2befe778 145
f5565b69 146 $question->fraction = array();
147 $question->answer = array();
148 for ($n = 0; $n < count($optionstext); ++$n) {
149 if ($optionstext[$n]) {
18651b0b
TH
150 if (!isset($numcorrect)) {
151 // Single answer.
f5565b69 152 if ($optionscorrect[$n] == 'yes') {
aeb15530 153 $fraction = (int) $questionaward;
f5565b69 154 } else {
155 $fraction = 0;
aeb15530 156 }
18651b0b
TH
157 } else {
158 // Multiple answers.
f5565b69 159 if ($optionscorrect[$n] == 'yes') {
aeb15530 160 $fraction = $optionsaward[$n] / $totalaward;
f5565b69 161 } else {
162 $fraction = -$optionsaward[$n] / count($optionstext);
163 }
164 }
165 $question->fraction[] = $fraction;
18651b0b
TH
166 $question->answer[] = array('text' => $optionstext[$n], 'format' => FORMAT_HTML);
167 $question->feedback[] = array('text' => '', 'format' => FORMAT_HTML); // No feedback in this type.
f5565b69 168 }
169 }
170
171 return $question;
172 }
173
18651b0b
TH
174 /**
175 * Extract the substring of $text between $start and $end.
176 * @param string $text text to analyse.
177 * @param string $start opening delimiter.
178 * @param string $end closing delimiter.
179 * @return string the requested substring.
180 */
181 protected function stringbetween($text, $start, $end) {
f5565b69 182 $startpos = strpos($text, $start) + strlen($start);
183 $endpos = strpos($text, $end);
2befe778 184
f5565b69 185 if ($startpos <= $endpos) {
186 return substr($text, $startpos, $endpos - $startpos);
187 }
188 }
f5565b69 189}