diff --git a/question/type/multianswer/edit_multianswer_form.php b/question/type/multianswer/edit_multianswer_form.php index a06b79f8202..86692fd19f0 100644 --- a/question/type/multianswer/edit_multianswer_form.php +++ b/question/type/multianswer/edit_multianswer_form.php @@ -32,8 +32,13 @@ class question_edit_multianswer_form extends question_edit_form { $this->questiondisplay = ""; } - if ( isset($this->questiondisplay->options->questions) && count($this->questiondisplay->options->questions) > 0 ) { - $countsubquestions = count($this->questiondisplay->options->questions); + if ( isset($this->questiondisplay->options->questions) && is_array($this->questiondisplay->options->questions) ) { + $countsubquestions =0; + foreach($this->questiondisplay->options->questions as $subquestion){ + if ($subquestion != ''){ + $countsubquestions++; + } + } } else { $countsubquestions =0; } @@ -83,6 +88,7 @@ class question_edit_multianswer_form extends question_edit_form { if (isset($question->id) and $question->id and $question->qtype and $question->questiontext) { foreach ($question->options->questions as $key => $wrapped) { + if($wrapped != ''){ // The old way of restoring the definitions is kept to gradually // update all multianswer questions if (empty($wrapped->questiontext)) { @@ -126,6 +132,7 @@ class question_edit_multianswer_form extends question_edit_form { $question->questiontext = str_replace("{#$key}", $parsableanswerdef, $question->questiontext); } } + } // set default to $questiondisplay questions elements if (isset($this->questiondisplay->options->questions)) { @@ -230,7 +237,7 @@ class question_edit_multianswer_form extends question_edit_form { $sub++; } } else { - $errors['questiontext']=get_string('questions missing', 'question'); + $errors['questiontext']=get_string('questionsmissing', 'qtype_multianswer'); } } diff --git a/question/type/multianswer/questiontype.php b/question/type/multianswer/questiontype.php index bb266c4a378..e8955b738e9 100644 --- a/question/type/multianswer/questiontype.php +++ b/question/type/multianswer/questiontype.php @@ -28,8 +28,9 @@ class embedded_cloze_qtype extends default_questiontype { // Get relevant data indexed by positionkey from the multianswers table if (!$sequence = get_field('question_multianswer', 'sequence', 'question', $question->id)) { - notify('Error: Cloze question '.$question->id.' is missing question options!'); - return false; + notify(get_string('noquestions','qtype_multianswer',$question->name)); + $question->options->questions['1']= ''; + return true ; } $wrappedquestions = get_records_list('question', 'id', $sequence, 'id ASC'); @@ -37,17 +38,31 @@ class embedded_cloze_qtype extends default_questiontype { // We want an array with question ids as index and the positions as values $sequence = array_flip(explode(',', $sequence)); array_walk($sequence, create_function('&$val', '$val++;')); - + //If a question is lost, the corresponding index is null + // so this null convention is used to test $question->options->questions + // before using the values. + // first all possible questions from sequence are nulled + // then filled with the data if available in $wrappedquestions + $nbvaliquestion = 0 ; + foreach($sequence as $seq){ + $question->options->questions[$seq]= ''; + } + if (isset($wrappedquestions) && is_array($wrappedquestions)){ foreach ($wrappedquestions as $wrapped) { if (!$QTYPES[$wrapped->qtype]->get_question_options($wrapped)) { notify("Unable to get options for questiontype {$wrapped->qtype} (id={$wrapped->id})"); - } + }else { // for wrapped questions the maxgrade is always equal to the defaultgrade, // there is no entry in the question_instances table for them $wrapped->maxgrade = $wrapped->defaultgrade; - + $nbvaliquestion++ ; $question->options->questions[$sequence[$wrapped->id]] = clone($wrapped); // ??? Why do we need a clone here? } + } + } + if ($nbvaliquestion == 0 ) { + notify(get_string('noquestions','qtype_multianswer',$question->name)); + } return true; } @@ -65,31 +80,36 @@ class embedded_cloze_qtype extends default_questiontype { // First we get all the existing wrapped questions if (!$oldwrappedids = get_field('question_multianswer', 'sequence', 'question', $question->id)) { - $oldwrappedids = array(); + $oldwrappedquestions = array(); } else { - $oldwrappedids = explode(',', $oldwrappedids); + $oldwrappedquestions = get_records_list('question', 'id', $oldwrappedids, 'id ASC'); } $sequence = array(); foreach($question->options->questions as $wrapped) { + if ($wrapped != ''){ // if we still have some old wrapped question ids, reuse the next of them - if ($oldwrappedid = array_shift($oldwrappedids)) { - $wrapped->id = $oldwrappedid; - $oldqtype = get_field('question', 'qtype', 'id',$oldwrappedid) ; - if($oldqtype != $wrapped->qtype ) { - switch ($oldqtype) { + + if (is_array($oldwrappedquestions) && $oldwrappedquestion = array_shift($oldwrappedquestions)) { + $wrapped->id = $oldwrappedquestion->id; + if($oldwrappedquestion->qtype != $wrapped->qtype ) { + switch ($oldwrappedquestion->qtype) { case 'multichoice': - delete_records('question_multichoice', 'question', $oldwrappedid); + delete_records('question_multichoice', 'question' , $oldwrappedquestion->id ); break; case 'shortanswer': - delete_records('question_shortanswer', 'question', $oldwrappedid); + delete_records('question_shortanswer', 'question' , $oldwrappedquestion->id ); break; case 'numerical': - delete_records('question_numerical', 'question', $oldwrappedid); + delete_records('question_numerical', 'question' , $oldwrappedquestion->id ); break; default: error("questiontype $wrapped->qtype not recognized"); + $wrapped->id = 0 ; } } + }else { + $wrapped->id = 0 ; + } } $wrapped->name = $question->name; $wrapped->parent = $question->id; @@ -197,6 +217,7 @@ class embedded_cloze_qtype extends default_questiontype { global $QTYPES; $responses = array(); foreach($question->options->questions as $key => $wrapped) { + if ($wrapped != ''){ if ($correct = $QTYPES[$wrapped->qtype]->get_correct_responses($wrapped, $state)) { $responses[$key] = $correct['']; } else { @@ -206,6 +227,7 @@ class embedded_cloze_qtype extends default_questiontype { return null; } } + } return $responses; } @@ -247,9 +269,10 @@ class embedded_cloze_qtype extends default_questiontype { $qtextremaining = $qtextsplits[1]; $positionkey = $regs[1]; + if (isset($question->options->questions[$positionkey]) && $question->options->questions[$positionkey] != ''){ $wrapped = &$question->options->questions[$positionkey]; $answers = &$wrapped->options->answers; - $correctanswers = $QTYPES[$wrapped->qtype]->get_correct_responses($wrapped, $state); + // $correctanswers = $QTYPES[$wrapped->qtype]->get_correct_responses($wrapped, $state); $inputname = $nameprefix.$positionkey; if (isset($state->responses[$positionkey])) { @@ -262,6 +285,38 @@ class embedded_cloze_qtype extends default_questiontype { $popup = ''; $style = ''; $feedbackimg = ''; + $feedback = '' ; + $correctanswer = ''; + $strfeedbackwrapped = $strfeedback; + // if($wrapped->qtype == 'numerical' ||$wrapped->qtype == 'shortanswer'){ + $testedstate = clone($state); + if ($correctanswers = $QTYPES[$wrapped->qtype]->get_correct_responses($wrapped, $testedstate)) { + if ($options->readonly && $options->correct_responses) { + $delimiter = ''; + if ($correctanswers) { + foreach ($correctanswers as $ca) { + switch($wrapped->qtype){ + case 'numerical': + case 'shortanswer': + $correctanswer .= $delimiter.$ca; + break ; + case 'multichoice': + if (isset($answers[$ca])){ + $correctanswer .= $delimiter.$answers[$ca]->answer; + } + break ; + } + $delimiter = ', '; + } + } + } + if ($correctanswer) { + $feedback = '