MDL-14625 more tolerant to missing subquestions merged from HEAD

This commit is contained in:
pichetp
2008-06-19 01:50:28 +00:00
parent 9676a2860c
commit 3af0788f9c
2 changed files with 105 additions and 21 deletions
@@ -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');
}
}
+95 -18
View File
@@ -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 = '<div class="correctness">';
$feedback .= get_string('correctansweris', 'quiz', s($correctanswer, true));
$feedback .= '</div>';
// $strfeedbackwrapped = get_string('correctanswer and', 'quiz').get_string('feedback', 'quiz');
}
}
if ($options->feedback) {
$chosenanswer = null;
switch ($wrapped->qtype) {
@@ -294,8 +349,13 @@ class embedded_cloze_qtype extends default_questiontype {
}
if (!empty($chosenanswer->feedback)) {
$feedback = s(str_replace(array("\\", "'"), array("\\\\", "\\'"), $chosenanswer->feedback));
$popup = " onmouseover=\"return overlib('$feedback', STICKY, MOUSEOFF, CAPTION, '$strfeedback', FGCOLOR, '#FFFFFF');\" ".
$feedback = s(str_replace(array("\\", "'"), array("\\\\", "\\'"), $feedback.$chosenanswer->feedback));
if ($options->readonly && $options->correct_responses) {
$strfeedbackwrapped = get_string('correctanswerandfeedback', 'qtype_multianswer');
}else {
$strfeedbackwrapped = get_string('feedback', 'quiz');
}
$popup = " onmouseover=\"return overlib('$feedback', STICKY, MOUSEOFF, CAPTION, '$strfeedbackwrapped', FGCOLOR, '#FFFFFF');\" ".
" onmouseout=\"return nd();\" ";
}
@@ -308,6 +368,12 @@ class embedded_cloze_qtype extends default_questiontype {
$feedbackimg = '';
}
}
if ($feedback !='' && $popup == ''){
$strfeedbackwrapped = get_string('correctanswer', 'qtype_multianswer');
$feedback = s(str_replace(array("\\", "'"), array("\\\\", "\\'"), $feedback));
$popup = " onmouseover=\"return overlib('$feedback', STICKY, MOUSEOFF, CAPTION, '$strfeedbackwrapped', FGCOLOR, '#FFFFFF');\" ".
" onmouseout=\"return nd();\" ";
}
// Print the input control
switch ($wrapped->qtype) {
@@ -384,6 +450,14 @@ class embedded_cloze_qtype extends default_questiontype {
}
echo "</label>"; // MDL-7497
}
else {
if(! isset($question->options->questions[$positionkey])){
echo $regs[0]."</label>";
}else {
echo '</label><div class="error" >'.get_string('questionnotfound','qtype_multianswer',$positionkey).'</div>';
}
}
}
// Print the final piece of question text:
echo $qtextremaining;
@@ -396,6 +470,7 @@ class embedded_cloze_qtype extends default_questiontype {
$teststate = clone($state);
$state->raw_grade = 0;
foreach($question->options->questions as $key => $wrapped) {
if ($wrapped != ''){
$state->responses[$key] = $state->responses[$key];
$teststate->responses = array('' => $state->responses[$key]);
$teststate->raw_grade = 0;
@@ -405,6 +480,7 @@ class embedded_cloze_qtype extends default_questiontype {
}
$state->raw_grade += $teststate->raw_grade;
}
}
$state->raw_grade /= $question->defaultgrade;
$state->raw_grade = min(max((float) $state->raw_grade, 0.0), 1.0)
* $question->maxgrade;
@@ -724,6 +800,7 @@ function qtype_multianswer_extract_question($text) {
} else if(!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE])) {
$wrapped->qtype = 'multichoice';
$wrapped->single = 1;
$wrapped->answernumbering = 0;
$wrapped->correctfeedback = '';
$wrapped->partiallycorrectfeedback = '';
$wrapped->incorrectfeedback = '';