diff --git a/lib/questionlib.php b/lib/questionlib.php
index f1c77be8491..5de7963fa5c 100644
--- a/lib/questionlib.php
+++ b/lib/questionlib.php
@@ -590,7 +590,8 @@ function question_move_questions_to_category($questionids, $newcategoryid) {
SELECT q.id, q.qtype, qc.contextid
FROM {question} q
JOIN {question_categories} qc ON q.category = qc.id
- WHERE q.id $questionidcondition", $params);
+ WHERE q.id $questionidcondition OR q.parent $questionidcondition",
+ array_merge($params, $params));
foreach ($questions as $question) {
if ($newcontextid != $question->contextid) {
question_bank::get_qtype($question->qtype)->move_files(
diff --git a/question/format/multianswer/format.php b/question/format/multianswer/format.php
index b7c412ea056..b9ea3bd526c 100644
--- a/question/format/multianswer/format.php
+++ b/question/format/multianswer/format.php
@@ -61,7 +61,8 @@ class qformat_multianswer extends qformat_default {
$question->length = 1;
$question->penalty = 0.3333333;
- if (!empty($question)) {
+ if (!empty($question) && isset($question->options) && isset($question->options->questions) &&
+ count($question->options->questions) != 0 ) {
$question->name = $this->create_default_question_name($question->questiontext, get_string('questionname', 'question'));
$questions[] = $question;
}
diff --git a/question/format/xml/format.php b/question/format/xml/format.php
index 69e9695f6f4..ea2e1679f94 100644
--- a/question/format/xml/format.php
+++ b/question/format/xml/format.php
@@ -449,12 +449,12 @@ class qformat_xml extends qformat_default {
*/
public function import_multianswer($question) {
global $USER;
- question_bank::get_qtype('multianswer');
+ $qtypemultianswer = question_bank::get_qtype('multianswer');
$questiontext = $this->import_text_with_files($question,
array('#', 'questiontext', 0));
$qo = qtype_multianswer_extract_question($questiontext);
-
+ $qo = $qtypemultianswer->set_subquestions_elements_itemid($qo, '@@PLUGINFILE@@');
// 'header' parts particular to multianswer
$qo->qtype = 'multianswer';
$qo->course = $this->course;
diff --git a/question/type/multianswer/edit_multianswer_form.php b/question/type/multianswer/edit_multianswer_form.php
index cd792f78a1f..cdecffb0b60 100644
--- a/question/type/multianswer/edit_multianswer_form.php
+++ b/question/type/multianswer/edit_multianswer_form.php
@@ -189,8 +189,10 @@ class qtype_multianswer_edit_form extends question_edit_form {
$mform->addElement('static', 'sub_'.$sub.'_layout',
get_string('layout', 'qtype_multianswer'));
}
-
+ $nbanswer = 0;
+ $choices = array();
foreach ($this->questiondisplay->options->questions[$sub]->answer as $key => $ans) {
+ $nbanswer++;
$mform->addElement('static', 'sub_'.$sub.'_answer['.$key.']',
get_string('answer', 'question'));
@@ -205,6 +207,15 @@ class qtype_multianswer_edit_form extends question_edit_form {
$mform->addElement('static', 'sub_'.$sub.'_feedback['.$key.']',
get_string('feedback', 'question'));
+ if ($this->questiondisplay->options->questions[$sub]->qtype == 'multichoice' &&
+ $this->questiondisplay->options->questions[$sub]->layout == 0) {
+ $choices[] = $ans['text'];
+ }
+ }
+ if ($nbanswer > 0 && $this->questiondisplay->options->questions[$sub]->qtype == 'multichoice' &&
+ $this->questiondisplay->options->questions[$sub]->layout == 0) {
+ $mform->addElement('select', 'sub_'.$sub.'_layoutselectinline',
+ get_string('layoutselectinline', 'qtype_multianswer'), $choices);
}
}
@@ -364,6 +375,7 @@ class qtype_multianswer_edit_form extends question_edit_form {
get_string('layoutundefined', 'qtype_multianswer');
}
}
+ $choices = array();
foreach ($subquestion->answer as $key => $answer) {
if ($subquestion->qtype == 'numerical' && $key == 0) {
$default_values[$prefix.'tolerance['.$key.']'] =
@@ -388,9 +400,19 @@ class qtype_multianswer_edit_form extends question_edit_form {
$maxfraction = $subquestion->fraction[$key];
}
}
-
- $default_values[$prefix.'answer['.$key.']'] =
- htmlspecialchars($answer);
+ if ($subquestion->qtype == 'multichoice' && $subquestion->layout == '0') {
+ $a = new stdClass();
+ $a->strip = strip_tags($trimmedanswer);
+ $a->html = htmlspecialchars($trimmedanswer);
+ $default_values[$prefix.'answer['.$key.']'] = get_string('answerselectelementshownas',
+ 'qtype_multianswer', $a);
+ $choices[$answercount] = $trimmedanswer;
+ } else {
+ $default_values[$prefix.'answer['.$key.']'] = htmlspecialchars($answer);
+ }
+ }
+ if ($subquestion->qtype == 'multichoice' && $subquestion->layout == '0') {
+ $default_values[$prefix.'_layoutselectinline'] = $choices;
}
if ($answercount == 0) {
if ($subquestion->qtype == 'multichoice') {
diff --git a/question/type/multianswer/lang/en/qtype_multianswer.php b/question/type/multianswer/lang/en/qtype_multianswer.php
index ddc01555a6a..0a294a49726 100644
--- a/question/type/multianswer/lang/en/qtype_multianswer.php
+++ b/question/type/multianswer/lang/en/qtype_multianswer.php
@@ -23,6 +23,8 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
+$string['answerselectelementempty'] = '{$a->html}
This answer will appear empty as the dropdown menu does not show HTML components.';
+$string['answerselectelementshownas'] = '{$a->html}
This answer will be rendered in the dropdown menu as : {$a->strip}';
$string['confirmquestionsaveasedited'] = 'I confirm that I want the question to be saved as edited';
$string['confirmsave'] = 'Confirm then save {$a}';
$string['correctanswer'] = 'Correct answer';
diff --git a/question/type/multianswer/lib.php b/question/type/multianswer/lib.php
new file mode 100644
index 00000000000..59faf589a41
--- /dev/null
+++ b/question/type/multianswer/lib.php
@@ -0,0 +1,47 @@
+.
+
+/**
+ * Serve question type files
+ *
+ * @since 2.0
+ * @package qtype_multianswer
+ * @copyright Pierre Pichet
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+
+defined('MOODLE_INTERNAL') || die();
+
+
+/**
+ * Checks file access for multianswer questions.
+ * @package qtype_multianswer
+ * @category files
+ * @param stdClass $course course object
+ * @param stdClass $cm course module object
+ * @param stdClass $context context object
+ * @param string $filearea file area
+ * @param array $args extra arguments
+ * @param bool $forcedownload whether or not force download
+ * @param array $options additional options affecting the file serving
+ * @return bool
+ */
+function qtype_multianswer_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
+ global $DB, $CFG;
+ require_once($CFG->libdir . '/questionlib.php');
+ question_pluginfile($course, $context, 'qtype_multianswer', $filearea, $args, $forcedownload, $options);
+}
diff --git a/question/type/multianswer/questiontype.php b/question/type/multianswer/questiontype.php
index 5df9f2cce59..0153882e66c 100644
--- a/question/type/multianswer/questiontype.php
+++ b/question/type/multianswer/questiontype.php
@@ -168,8 +168,45 @@ class qtype_multianswer extends question_type {
$this->save_hints($question, true);
}
+ /**
+ * Set the itemid if the element contains a valid file identify by (draftfile.php).
+ * param array() $question from qtype_multianswer_extract_question().
+ * param string $searchcriteria i.e $searchcriteria ,@@PLUGINFILE@@.
+ * return $question.
+ */
+ public function set_subquestions_elements_itemid($question, $searchcriteria = '') {
+ if (isset($question->options) && isset($question->options->questions) &&
+ $question->options->questions != '' && isset($question->questiontext['itemid'])
+ && $question->questiontext['itemid'] != '' && $searchcriteria != '') {
+ $questiontextitemid = $question->questiontext['itemid'];
+ foreach ($question->options->questions as $wrapped) {
+ if (preg_match('/'.$searchcriteria.'/', $wrapped->questiontext['text'])) {
+ $wrapped->questiontext['itemid'] = $questiontextitemid;
+ } else {
+ $wrapped->questiontext['itemid'] = '';
+ }
+ foreach ($wrapped->answer as $key => $answer) {
+ if (is_array($answer)) {
+ if (preg_match('/'.$searchcriteria.'/', $answer['text'])) {
+ $wrapped->answer[$key]['itemid'] = $questiontextitemid;
+ } else {
+ $wrapped->answer[$key]['itemid'] = '';
+ }
+ }
+ if (preg_match('/'.$searchcriteria.'/', $wrapped->feedback[$key]['text'])) {
+ $wrapped->feedback[$key]['itemid'] = $questiontextitemid;
+ } else {
+ $wrapped->feedback[$key]['itemid'] = '';
+ }
+ }
+ }
+ }
+ return $question;
+ }
+
public function save_question($authorizedquestion, $form) {
$question = qtype_multianswer_extract_question($form->questiontext);
+ $question = $this->set_subquestions_elements_itemid($question, 'draftfile.php');
if (isset($authorizedquestion->id)) {
$question->id = $authorizedquestion->id;
}
@@ -296,9 +333,15 @@ define('ANSWER_REGEX_ALTERNATIVES', 9);
function qtype_multianswer_extract_question($text) {
// Variable $text is an array [text][format][itemid].
+ // If the main question contains a file then its [itemid]
+ // will not be empty.
+ // The other subquestions question , answers feedback and
+ // multiple choice vertical and horizontal answers should be declared
+ // array and should have [itemid] set to [text][itemid].
$question = new stdClass();
$question->qtype = 'multianswer';
$question->questiontext = $text;
+ $question->questiontext['text'] = str_replace(array('
', ''), array('', ''), $question->questiontext['text']); $question->generalfeedback['text'] = ''; $question->generalfeedback['format'] = FORMAT_HTML; $question->generalfeedback['itemid'] = ''; @@ -314,6 +357,9 @@ function qtype_multianswer_extract_question($text) { $wrapped->generalfeedback['text'] = ''; $wrapped->generalfeedback['format'] = FORMAT_HTML; $wrapped->generalfeedback['itemid'] = ''; + $wrapped->questiontext['text'] = $answerregs[0]; + $wrapped->questiontext['format'] = $question->questiontext['format']; + $wrapped->questiontext['itemid'] = $question->questiontext['itemid']; if (isset($answerregs[ANSWER_REGEX_NORM])&& $answerregs[ANSWER_REGEX_NORM]!== '') { $wrapped->defaultmark = $answerregs[ANSWER_REGEX_NORM]; } else { @@ -388,9 +434,6 @@ function qtype_multianswer_extract_question($text) { $wrapped->answer = array(); $wrapped->fraction = array(); $wrapped->feedback = array(); - $wrapped->questiontext['text'] = $answerregs[0]; - $wrapped->questiontext['format'] = FORMAT_HTML; - $wrapped->questiontext['itemid'] = ''; $answerindex = 0; $remainingalts = $answerregs[ANSWER_REGEX_ALTERNATIVES]; @@ -408,7 +451,7 @@ function qtype_multianswer_extract_question($text) { $feedback = str_replace('\}', '}', $feedback); $wrapped->feedback["$answerindex"]['text'] = str_replace('\#', '#', $feedback); $wrapped->feedback["$answerindex"]['format'] = FORMAT_HTML; - $wrapped->feedback["$answerindex"]['itemid'] = ''; + $wrapped->feedback["$answerindex"]['itemid'] = $question->questiontext['itemid']; } else { $wrapped->feedback["$answerindex"]['text'] = ''; $wrapped->feedback["$answerindex"]['format'] = FORMAT_HTML; @@ -436,6 +479,11 @@ function qtype_multianswer_extract_question($text) { 'text' => $wrapped->answer["$answerindex"], 'format' => FORMAT_HTML, 'itemid' => ''); + if ($wrapped->answer["$answerindex"]['text'] != '' && + ($wrapped->layout == qtype_multichoice_base::LAYOUT_HORIZONTAL || + $wrapped->layout == qtype_multichoice_base::LAYOUT_VERTICAL )) { + $wrapped->answer["$answerindex"]['itemid'] = $question->questiontext['itemid']; + } } } $tmp = explode($altregs[0], $remainingalts, 2); diff --git a/question/type/multianswer/renderer.php b/question/type/multianswer/renderer.php index d67d0fc8620..403c9851d2c 100644 --- a/question/type/multianswer/renderer.php +++ b/question/type/multianswer/renderer.php @@ -388,7 +388,7 @@ class qtype_multianswer_multichoice_vertical_renderer extends qtype_multianswer_ question_state::$gradedright) { $feedback[] = get_string('correctansweris', 'qtype_multichoice', $subq->format_text($ans->answer, $ans->answerformat, - $qa, 'question', 'answer', $ansid)); + $qa, 'question', 'answer', $ans->id)); break; } } diff --git a/question/type/numerical/questiontype.php b/question/type/numerical/questiontype.php index 2d290aacb57..995de5cb573 100644 --- a/question/type/numerical/questiontype.php +++ b/question/type/numerical/questiontype.php @@ -206,7 +206,8 @@ class qtype_numerical extends question_type { } $options->question = $question->id; $options->answer = $answer->id; - if (trim($question->tolerance[$key]) == '') { + // When the answer is * the tolerance can be absent i.e. in multianswer. + if (!isset($question->tolerance[$key]) || trim($question->tolerance[$key]) == '') { $options->tolerance = ''; } else { $options->tolerance = $this->apply_unit($question->tolerance[$key],