From 0a5b58af8963ed9eab77a2305329cd5f90cd2d4c Mon Sep 17 00:00:00 2001 From: gustav_delius Date: Wed, 5 Apr 2006 05:53:18 +0000 Subject: [PATCH] Many bugfixes accummulated during CVS outage, more to come. --- lang/en_utf8/help/quiz/reorderingtool.html | 2 +- lang/en_utf8/quiz.php | 1 + lib/questionlib.php | 31 +++++++------------- lib/soap/phpsoap.php | 8 ++--- mod/quiz/editlib.php | 2 ++ mod/quiz/report/default.php | 4 +-- mod/quiz/report/grading/report.php | 2 +- mod/quiz/report/regrade/report.php | 10 +++++-- mod/quiz/review.php | 7 ++++- mod/quiz/reviewquestion.php | 2 +- mod/quiz/tabs.php | 6 ++-- mod/quiz/view.php | 34 ++++++++++++---------- question/type/calculated/questiontype.php | 2 +- question/type/description/question.html | 2 +- question/type/match/display.html | 2 +- question/type/match/questiontype.php | 7 ++++- question/type/missingtype/display.html | 4 +-- question/type/multianswer/questiontype.php | 7 ++--- question/type/multichoice/display.html | 2 +- question/type/questiontype.php | 7 +++-- question/type/random/questiontype.php | 2 +- question/type/shortanswer/display.html | 2 +- question/type/shortanswer/editquestion.php | 3 +- question/type/truefalse/display.html | 2 +- question/type/truefalse/questiontype.php | 9 ++++++ 25 files changed, 92 insertions(+), 68 deletions(-) diff --git a/lang/en_utf8/help/quiz/reorderingtool.html b/lang/en_utf8/help/quiz/reorderingtool.html index a1ef4c7d674..54c2ee367b9 100644 --- a/lang/en_utf8/help/quiz/reorderingtool.html +++ b/lang/en_utf8/help/quiz/reorderingtool.html @@ -7,7 +7,7 @@ reordered according to the line numbers you specified.

Line numbers do not have to be integers, you can also use numbers with - a decimal point if you find that convenient

+ a decimal point if you find that convenient.

Page breaks are given line numbers as well, to allow you to move them around in the same manner. If you have unticked the "Show page breaks" diff --git a/lang/en_utf8/quiz.php b/lang/en_utf8/quiz.php index 1920dc3920b..6d3962c4040 100644 --- a/lang/en_utf8/quiz.php +++ b/lang/en_utf8/quiz.php @@ -258,6 +258,7 @@ $string['min'] = 'Min'; $string['minutes'] = 'Minutes'; $string['missinganswer'] = 'Too few :ANSWER, :Lx, :Rx statements for question line $a. You must define at last 2 possible answers'; $string['missingcorrectanswer'] = 'Correct answer must be specified'; +$string['missingformula'] = 'Missing formula'; $string['missingitemtypename'] = 'Missing name'; $string['missingname'] = 'Missing question name'; $string['missingquestion'] = 'Missing question label after line $a'; diff --git a/lib/questionlib.php b/lib/questionlib.php index 975f28584fd..c852955f660 100644 --- a/lib/questionlib.php +++ b/lib/questionlib.php @@ -819,7 +819,7 @@ function question_extract_responses($questions, $formdata, $defaultevent=QUESTIO * * TODO: Make sure this is not quiz-specific * -* @return boolean Indicates success/failure +* @return boolean Indicates whether the grade has changed * @param object $question A question object * @param object $attempt The attempt, in which the question needs to be regraded. * @param object $cmoptions @@ -843,19 +843,15 @@ function regrade_question_in_attempt($question, $attempt, $cmoptions, $verbose=f $replaystate = clone($state); $replaystate->last_graded = $state; - $changed = 0; + $changed = false; for($j = 1; $j < count($states); $j++) { restore_question_state($question, $states[$j]); $action = new stdClass; $action->responses = $states[$j]->responses; $action->timestamp = $states[$j]->timestamp; - // Close the last state of a finished attempt - if (((count($states) - 1) === $j) && ($attempt->timefinish > 0)) { - $action->event = QUESTION_EVENTCLOSE; - // Change event to submit so that it will be reprocessed - } else if (QUESTION_EVENTCLOSE == $states[$j]->event + if (QUESTION_EVENTCLOSE == $states[$j]->event or QUESTION_EVENTGRADE == $states[$j]->event or QUESTION_EVENTCLOSEANDGRADE == $states[$j]->event) { $action->event = QUESTION_EVENTSUBMIT; @@ -872,28 +868,23 @@ function regrade_question_in_attempt($question, $attempt, $cmoptions, $verbose=f // We need rounding here because grades in the DB get truncated // e.g. 0.33333 != 0.3333333, but we want them to be equal here - if (round((float)$replaystate->grade, 5) != round((float)$states[$j]->grade, 5)) { - $changed++; + if ((round((float)$replaystate->raw_grade, 5) != round((float)$states[$j]->raw_grade, 5)) + or (round((float)$replaystate->penalty, 5) != round((float)$states[$j]->penalty, 5)) + or (round((float)$replaystate->grade, 5) != round((float)$states[$j]->grade, 5))) { + $changed = true; } $replaystate->id = $states[$j]->id; $replaystate->update = true; // This will ensure that the existing database entry is updated rather than a new one created save_question_session($question, $replaystate); } - if ($verbose) { - if ($changed) { - link_to_popup_window ('/question/reviewquestion.php?attempt='.$attempt->id.'&question='.$question->id, - 'reviewquestion', ' #'.$attempt->id, 450, 550, get_string('reviewresponse', 'quiz')); - update_record('quiz_attempts', $attempt); - } else { - echo ' #'.$attempt->id; - } - echo "\n"; @flush(); @ob_flush(); + if ($changed) { + update_record('quiz_attempts', $attempt); } - return true; + return $changed; } - return true; + return false; } /** diff --git a/lib/soap/phpsoap.php b/lib/soap/phpsoap.php index f207ee90ad6..ab7f0fcb125 100644 --- a/lib/soap/phpsoap.php +++ b/lib/soap/phpsoap.php @@ -87,7 +87,7 @@ function get_last_soap_messages($connection) { return array('request'=>$connection->__getLastRequest(), 'response'=>$connection->__getLastResponse()); } -// Fix simple type encoding - work around a bug in PHP +// Fix simple type encoding - work around a bug in early versions of PHP5 < 5.0.3, see http://bugs.php.net/bug.php?id=31832 function soap_encode($value, $name, $type, $namespace, $encode=XSD_STRING) { $value = new SoapVar($value, $encode, $type, $namespace); if ('' === $name) @@ -95,7 +95,7 @@ function soap_encode($value, $name, $type, $namespace, $encode=XSD_STRING) { return new SoapParam($value, $name); } -// Fix complex type encoding - work around a bug in PHP +// Fix complex type encoding - work around a bug in early versions of PHP5 < 5.0.3, see http://bugs.php.net/bug.php?id=31832 function soap_encode_object($value, $name, $type, $namespace) { if (!is_object($value)) return $value; @@ -105,7 +105,7 @@ function soap_encode_object($value, $name, $type, $namespace) { return new SoapParam($value, $name); } -// Fix array encoding - work around a bug in PHP +// Fix array encoding - work around a bug in early versions of PHP5 < 5.0.3, see http://bugs.php.net/bug.php?id=31832 function soap_encode_array($value, $name, $type, $namespace) { if (!is_array($value)) return $value; @@ -115,4 +115,4 @@ function soap_encode_array($value, $name, $type, $namespace) { return new SoapParam($value, $name); } -?> +?> \ No newline at end of file diff --git a/mod/quiz/editlib.php b/mod/quiz/editlib.php index 9cfe1931b8e..aa007a38f98 100644 --- a/mod/quiz/editlib.php +++ b/mod/quiz/editlib.php @@ -46,6 +46,8 @@ function quiz_delete_quiz_question($id, &$modform) { if (!set_field('quiz', 'questions', $modform->questions, 'id', $modform->instance)) { error('Could not save question list'); } + delete_records('quiz_question_instances', 'quiz', $modform->instance, 'question', $question); + return true; } diff --git a/mod/quiz/report/default.php b/mod/quiz/report/default.php index 5acfd6dd96a..d27ee925770 100644 --- a/mod/quiz/report/default.php +++ b/mod/quiz/report/default.php @@ -21,7 +21,7 @@ class quiz_default_report { return true; } - function print_header_and_tabs($cm, $course, $quiz, $reportmode="overview"){ + function print_header_and_tabs($cm, $course, $quiz, $reportmode="overview", $meta=""){ global $CFG; /// Define some strings $strquizzes = get_string("modulenameplural", "quiz"); @@ -30,7 +30,7 @@ class quiz_default_report { print_header_simple(format_string($quiz->name), "", "id\">$strquizzes -> ".format_string($quiz->name), - "", "", true, update_module_button($cm->id, $course->id, $strquiz), navmenu($course, $cm)); + '', $meta, true, update_module_button($cm->id, $course->id, $strquiz), navmenu($course, $cm)); /// Print the tabs $currenttab = 'reports'; $mode = $reportmode; diff --git a/mod/quiz/report/grading/report.php b/mod/quiz/report/grading/report.php index 6f687675792..fa8750e2c06 100644 --- a/mod/quiz/report/grading/report.php +++ b/mod/quiz/report/grading/report.php @@ -184,7 +184,7 @@ class quiz_report extends quiz_default_report { restore_question_state($question, $state); $state->last_graded = $state; - $options = quiz_get_reviewoptions($quiz, $attempt, isteacher()); + $options = quiz_get_reviewoptions($quiz, $attempt, true); $options->validation = ($state->event == QUESTION_EVENTVALIDATE); // not sure what this is //$options->history = 'all'; // had this on, but seemed confusing for this diff --git a/mod/quiz/report/regrade/report.php b/mod/quiz/report/regrade/report.php index b932e3f96b9..1fabbc289f5 100644 --- a/mod/quiz/report/regrade/report.php +++ b/mod/quiz/report/regrade/report.php @@ -30,7 +30,7 @@ class quiz_report extends quiz_default_report { get_question_options($questions); /// Print heading - print_heading(get_string('regradingquiz', 'quiz', $quiz->name)); + print_heading(get_string('regradingquiz', 'quiz', format_string($quiz->name))); echo '

'; print_string('regradedisplayexplanation', 'quiz'); echo '
'; @@ -40,7 +40,13 @@ class quiz_report extends quiz_default_report { echo ''.get_string('regradingquestion', 'quiz', $question->name).' '.get_string('attempts', 'quiz').": \n"; foreach ($attempts as $attempt) { set_time_limit(30); - regrade_question_in_attempt($question, $attempt, $quiz, true); + $changed = regrade_question_in_attempt($question, $attempt, $quiz, true); + if ($changed) { + link_to_popup_window ('/mod/quiz/reviewquestion.php?attempt='.$attempt->id.'&question='.$question->id, + 'reviewquestion', ' #'.$attempt->id, 450, 550, get_string('reviewresponse', 'quiz')); + } else { + echo ' #'.$attempt->id; + } } echo '
'; // the following makes sure that the output is sent immediately. diff --git a/mod/quiz/review.php b/mod/quiz/review.php index 6dea7c363ae..723a1dfd63e 100644 --- a/mod/quiz/review.php +++ b/mod/quiz/review.php @@ -101,7 +101,12 @@ /// Print heading and tabs if this is part of a preview if ($isteacher) { - $currenttab = ($attempt->userid == $USER->id) ? 'preview' : ''; + if ($attempt->userid == $USER->id) { // this is the report on a preview + $currenttab = 'preview'; + } else { + $currenttab = 'reports'; + $mode = ''; + } include('tabs.php'); } else { print_heading(format_string($quiz->name)); diff --git a/mod/quiz/reviewquestion.php b/mod/quiz/reviewquestion.php index be9c077e3b4..b61e5e3e89d 100644 --- a/mod/quiz/reviewquestion.php +++ b/mod/quiz/reviewquestion.php @@ -24,7 +24,7 @@ if (! $state = get_record('question_states', 'id', $stateid)) { error('Invalid state id'); } - if (! $attempt = get_record('quiz_attempts', 'id', $state->attempt)) { + if (! $attempt = get_record('quiz_attempts', 'uniqueid', $state->attempt)) { error('No such attempt ID exists'); } } elseif ($attemptid) { diff --git a/mod/quiz/tabs.php b/mod/quiz/tabs.php index 3607a3ec29a..40a8eb3c1ff 100644 --- a/mod/quiz/tabs.php +++ b/mod/quiz/tabs.php @@ -30,9 +30,9 @@ $row[] = new tabobject('info', "$CFG->wwwroot/mod/quiz/view.php?q=$quiz->id", get_string('info', 'quiz')); $row[] = new tabobject('reports', "$CFG->wwwroot/mod/quiz/report.php?q=$quiz->id", get_string('results', 'quiz')); - $row[] = new tabobject('preview', "$CFG->wwwroot/mod/quiz/attempt.php?q=$quiz->id", get_string('preview', 'quiz'), get_string('previewquiz', 'quiz', format_string($quiz->name))); + $row[] = new tabobject('preview', "$CFG->wwwroot/mod/quiz/attempt.php?q=$quiz->id", get_string('preview', 'quiz')); if (isteacheredit($course->id)) { - $row[] = new tabobject('edit', "$CFG->wwwroot/mod/quiz/edit.php?quizid=$quiz->id", get_string('edit'), get_string('editquizquestions', 'quiz')); + $row[] = new tabobject('edit', "$CFG->wwwroot/mod/quiz/edit.php?quizid=$quiz->id", get_string('edit')); } $tabs[] = $row; @@ -75,7 +75,7 @@ $row[] = new tabobject('categories', "$CFG->wwwroot/question/category.php?id=$course->id", get_string('categories', 'quiz'), get_string('editqcats', 'quiz')); $row[] = new tabobject('import', "$CFG->wwwroot/question/import.php?course=$course->id", get_string('import', 'quiz'), get_string('importquestions', 'quiz')); $row[] = new tabobject('export', "$CFG->wwwroot/question/export.php?courseid=$course->id", get_string('export', 'quiz'), get_string('exportquestions', 'quiz')); - $row[] = new tabobject('update', "$CFG->wwwroot/course/mod.php?update=$cm->id&sesskey=$USER->sesskey", get_string('settings'), get_string('updatesettings')); + $row[] = new tabobject('update', "$CFG->wwwroot/course/mod.php?update=$cm->id&sesskey=$USER->sesskey", get_string('settings'), get_string('updatesettings', 'quiz')); $tabs[] = $row; } diff --git a/mod/quiz/view.php b/mod/quiz/view.php index 37681f19451..fac72b62b56 100644 --- a/mod/quiz/view.php +++ b/mod/quiz/view.php @@ -169,24 +169,26 @@ /// Now print table with existing attempts - if ($numattempts) { + if ($attempts) { /// prepare table header + $table->head = array($strattempt, $strtimecompleted); + $table->align = array("center", "left"); + $table->size = array("", ""); if ($quiz->grade and $quiz->sumgrades) { // Grades used so have more columns in table if ($quiz->grade <> $quiz->sumgrades) { - $table->head = array($strattempt, $strtimetaken, $strtimecompleted, "$strmarks / $quiz->sumgrades", "$strgrade / $quiz->grade"); - $table->align = array("center", "center", "left", "right", "right"); - $table->size = array("", "", "", "", ""); - } else { - $table->head = array($strattempt, $strtimetaken, $strtimecompleted, "$strgrade / $quiz->grade"); - $table->align = array("center", "center", "left", "right"); - $table->size = array("", "", "", ""); + $table->head[] = "$strmarks / $quiz->sumgrades"; + $table->align[] = 'right'; + $table->size[] = ''; } - - } else { // No grades are being used - $table->head = array($strattempt, $strtimetaken, $strtimecompleted); - $table->align = array("center", "center", "left"); - $table->size = array("", "", ""); + $table->head[] = "$strgrade / $quiz->grade"; + $table->align[] = 'right'; + $table->size[] = ''; + } + if (isset($quiz->showtimetaken)) { + $table->head[] = $strtimetaken; + $table->align[] = 'center'; + $table->size[] = ''; } /// One row for each attempt @@ -266,12 +268,10 @@ if ($quiz->grade <> $quiz->sumgrades) { $table->data[] = array( $attempt->attempt, - $timetaken, $datecompleted, $attemptmark, $attemptgrade); } else { $table->data[] = array( $attempt->attempt, - $timetaken, $datecompleted, $attemptgrade); } @@ -284,9 +284,11 @@ } } $table->data[] = array( $attempt->attempt, - $timetaken, $datecompleted); } + if (isset($quiz->showtimetaken)) { + $table->data[] = $timetaken; + } } print_table($table); } diff --git a/question/type/calculated/questiontype.php b/question/type/calculated/questiontype.php index 9026b4df868..539962d9e75 100644 --- a/question/type/calculated/questiontype.php +++ b/question/type/calculated/questiontype.php @@ -260,7 +260,7 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype return parent::grade_responses($numericalquestion, $state, $cmoptions); } - function response_summary($state, $length=80) { + function response_summary($question, $state, $length=80) { // The actual response is the bit after the hyphen return substr($state->answer, strpos($state->answer, '-')+1, $length); } diff --git a/question/type/description/question.html b/question/type/description/question.html index 241b9fa85ec..3b7bb048e9d 100644 --- a/question/type/description/question.html +++ b/question/type/description/question.html @@ -8,7 +8,7 @@ - + diff --git a/question/type/match/display.html b/question/type/match/display.html index 56d443e2b99..6435d5d99e0 100644 --- a/question/type/match/display.html +++ b/question/type/match/display.html @@ -3,7 +3,7 @@ - +
diff --git a/question/type/match/questiontype.php b/question/type/match/questiontype.php index 9596b522248..5e9be61862e 100644 --- a/question/type/match/questiontype.php +++ b/question/type/match/questiontype.php @@ -252,7 +252,7 @@ class question_match_qtype extends default_questiontype { and $options->correct_responses and isset($correctanswers[$subquestion->id]) and ($correctanswers[$subquestion->id] == $response)) { - $a->class = ' class="highlight" '; + $a->class = ' highlight '; } else { $a->class = ''; } @@ -334,6 +334,11 @@ class question_match_qtype extends default_questiontype { return null; } } + + function response_summary($question, $state, $length=80) { + // This should almost certainly be overridden + return substr(implode(',', $this->get_actual_response($question, $state)), 0, $length); + } /// BACKUP FUNCTIONS //////////////////////////// diff --git a/question/type/missingtype/display.html b/question/type/missingtype/display.html index a8337066960..31e01f59074 100644 --- a/question/type/missingtype/display.html +++ b/question/type/missingtype/display.html @@ -4,7 +4,7 @@
- +
@@ -21,4 +21,4 @@ -
\ No newline at end of file + diff --git a/question/type/multianswer/questiontype.php b/question/type/multianswer/questiontype.php index eed44afd3a0..e8cee24a387 100644 --- a/question/type/multianswer/questiontype.php +++ b/question/type/multianswer/questiontype.php @@ -59,12 +59,11 @@ class embedded_cloze_qtype extends default_questiontype { // will also create difficulties if questiontype specific tables reference the id. // First we get all the existing wrapped questions - if (!$oldwrappedids = get_records('question', 'parent', $question->id, '', 'id, id')) { - // We need to select 'id, id' because the first one is consumed by - // get_records. + if (!$oldwrappedids = get_field('question_multianswers', 'sequence', 'question', $question->id)) { $oldwrappedids = array(); + } else { + $oldwrappedids = explode(',', $oldwrappedids); } - $oldwrappedids = array_keys($oldwrappedids); $sequence = array(); foreach($question->options->questions as $wrapped) { // if we still have some old wrapped question ids, reuse the next of them diff --git a/question/type/multichoice/display.html b/question/type/multichoice/display.html index 0fddc3f8c86..de4f8fcbb74 100644 --- a/question/type/multichoice/display.html +++ b/question/type/multichoice/display.html @@ -3,7 +3,7 @@ - +
diff --git a/question/type/questiontype.php b/question/type/questiontype.php index 59dd70a2057..ba3bcbee766 100644 --- a/question/type/questiontype.php +++ b/question/type/questiontype.php @@ -510,6 +510,8 @@ class default_questiontype { $table->size = array ('', '', '', '', '', '', ''); $table->width = '100%'; foreach ($states as $st) { + $st->responses[''] = $st->answer; + $this->restore_session_and_responses($question, $st); $b = ($state->id == $st->id) ? '' : ''; $be = ($state->id == $st->id) ? '' : ''; if ($state->id == $st->id) { @@ -525,7 +527,7 @@ class default_questiontype { $table->data[] = array ( $link, $b.get_string('event'.$st->event, 'quiz').$be, - $b.$this->response_summary($st).$be, + $b.$this->response_summary($question, $st).$be, $b.userdate($st->timestamp, get_string('timestr', 'quiz')).$be, $b.round($st->raw_grade, $cmoptions->decimalpoints).$be, $b.round($st->penalty, $cmoptions->decimalpoints).$be, @@ -694,10 +696,11 @@ class default_questiontype { * summarizes the student's response in the given $state. This is used for * example in the response history table * @return string The summary of the student response + * @param object $question * @param object $state The state whose responses are to be summarized * @param int $length The maximum length of the returned string */ - function response_summary($state, $length=80) { + function response_summary($question, $state, $length=80) { // This should almost certainly be overridden return substr($state->answer, 0, $length); } diff --git a/question/type/random/questiontype.php b/question/type/random/questiontype.php index b9ba733f3eb..194e035ab20 100644 --- a/question/type/random/questiontype.php +++ b/question/type/random/questiontype.php @@ -7,7 +7,7 @@ /// QUESTION TYPE CLASS ////////////////// class random_qtype extends default_questiontype { - var $excludedtypes = array('random', 'randomsamatch', 'essay', 'description'); + var $excludedtypes = array("'random'", "'randomsamatch'", "'essay'", "'description'"); // Carries questions available as randoms sorted by category // This array is used when needed only diff --git a/question/type/shortanswer/display.html b/question/type/shortanswer/display.html index ae82508a773..2f82f62b801 100644 --- a/question/type/shortanswer/display.html +++ b/question/type/shortanswer/display.html @@ -3,7 +3,7 @@
- +
diff --git a/question/type/shortanswer/editquestion.php b/question/type/shortanswer/editquestion.php index 85acb6287a4..164b41e3af9 100644 --- a/question/type/shortanswer/editquestion.php +++ b/question/type/shortanswer/editquestion.php @@ -15,11 +15,12 @@ } } + $emptyanswer->answer = ''; $i = count($answers); $limit = QUESTION_NUMANS; $limit = $limit <= $i ? $i+1 : $limit; for (; $i < $limit; $i++) { - $answers[] = ""; // Make answer slots, default as blank + $answers[] = $emptyanswer; // Make answer slots, default as blank } print_heading_with_help(get_string("editingshortanswer", "quiz"), "shortanswer", "quiz"); diff --git a/question/type/truefalse/display.html b/question/type/truefalse/display.html index 10ec788967b..99d9688ba51 100644 --- a/question/type/truefalse/display.html +++ b/question/type/truefalse/display.html @@ -3,7 +3,7 @@
- +
diff --git a/question/type/truefalse/questiontype.php b/question/type/truefalse/questiontype.php index 1144a82e55f..e3d25c18da2 100644 --- a/question/type/truefalse/questiontype.php +++ b/question/type/truefalse/questiontype.php @@ -202,6 +202,15 @@ class question_truefalse_qtype extends default_questiontype { return true; } + function response_summary($question, $state, $length=80) { + if (isset($question->options->answers[$state->answer])) { + $responses = $question->options->answers[$state->answer]->answer; + } else { + $responses = ''; + } + return $responses; + } + function get_actual_response($question, $state) { if (isset($question->options->answers[$state->responses['']])) { $responses[] = $question->options->answers[$state->responses['']]->answer;