From cd06115fa768043ce0610db22bc6e6e2ca2a2250 Mon Sep 17 00:00:00 2001 From: tjhunt Date: Fri, 25 Aug 2006 16:03:54 +0000 Subject: [PATCH] Convert mod/quiz/view.php to roles, and further tidy up the code flow in there. This touches other files because I had to change a function in locallib that had an $isteacher parameter. I have not converted the rest of the quiz, and I don't intend to. I am hoping Moodle.com will do it. I hope this does not introduce any bugs, but view.php is so complicate (at least it is less complicated than it was) and the quiz has so many options, that it is hard to be sure. This needs lots of testing before 1.7 is released. --- mod/quiz/db/access.php | 116 ++++++ mod/quiz/locallib.php | 28 +- mod/quiz/report/grading/report.php | 5 +- mod/quiz/review.php | 2 +- mod/quiz/reviewquestion.php | 10 +- mod/quiz/tabs.php | 14 +- mod/quiz/version.php | 2 +- mod/quiz/view.php | 555 +++++++++++++++-------------- 8 files changed, 440 insertions(+), 292 deletions(-) create mode 100644 mod/quiz/db/access.php diff --git a/mod/quiz/db/access.php b/mod/quiz/db/access.php new file mode 100644 index 0000000000..87ead77be6 --- /dev/null +++ b/mod/quiz/db/access.php @@ -0,0 +1,116 @@ + array( + + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'guest' => CAP_ALLOW, + 'student' => CAP_ALLOW, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'coursecreator' => CAP_ALLOW, + 'admin' => CAP_ALLOW + ) + ), + + // Ability to do the quiz as a 'student'. + 'mod/quiz:attempt' => array( + + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'guest' => CAP_PREVENT, + 'student' => CAP_ALLOW, + 'teacher' => CAP_PREVENT, + 'editingteacher' => CAP_PREVENT, + 'coursecreator' => CAP_PREVENT, + 'admin' => CAP_PREVENT + ) + ), + + // Edit the quiz settings, add and remove questions. + 'mod/quiz:manage' => array( + + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'guest' => CAP_PREVENT, + 'student' => CAP_PREVENT, + 'teacher' => CAP_PREVENT, + 'editingteacher' => CAP_ALLOW, + 'coursecreator' => CAP_ALLOW, + 'admin' => CAP_ALLOW + ) + ), + + // Preview the quiz. + 'mod/quiz:preview' => array( + + 'captype' => 'write', // Only just a write. + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'guest' => CAP_PREVENT, + 'student' => CAP_PREVENT, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'coursecreator' => CAP_ALLOW, + 'admin' => CAP_ALLOW + ) + ), + + // Manually grade and comment on student attempts at a question. + 'mod/quiz:grade' => array( + + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'guest' => CAP_PREVENT, + 'student' => CAP_PREVENT, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'coursecreator' => CAP_ALLOW, + 'admin' => CAP_ALLOW + ) + ), + + // View the quiz reports. + 'mod/quiz:viewreports' => array( + + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'guest' => CAP_PREVENT, + 'student' => CAP_PREVENT, + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'coursecreator' => CAP_ALLOW, + 'admin' => CAP_ALLOW + ) + ), + + // Delete attempts using the overview report. + 'mod/quiz:deleteattempts' => array( + + 'captype' => 'write', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'guest' => CAP_PREVENT, + 'student' => CAP_PREVENT, + 'teacher' => CAP_PREVENT, + 'editingteacher' => CAP_ALLOW, + 'coursecreator' => CAP_ALLOW, + 'admin' => CAP_ALLOW + ) + ) +); + +?> \ No newline at end of file diff --git a/mod/quiz/locallib.php b/mod/quiz/locallib.php index d69f186f0c..365af7172c 100644 --- a/mod/quiz/locallib.php +++ b/mod/quiz/locallib.php @@ -78,9 +78,17 @@ function quiz_create_attempt($quiz, $attemptnumber) { return $attempt; } +/** + * Returns an unfinished attempt (if there is one) for the given + * user on the given quiz. This function does not return preview attempts. + * + * @param integer $quizid the id of the quiz. + * @param integer $userid the id of the user. + * + * @return mixed the unfinished attempt if there is one, false if not. + */ function quiz_get_user_attempt_unfinished($quizid, $userid) { -// Returns an object containing an unfinished attempt (if there is one) - return get_record("quiz_attempts", "quiz", $quizid, "userid", $userid, "timefinish", 0); + return get_record_select("quiz_attempts", "quiz = $quizid AND userid = $userid AND timefinish = 0 AND preview = 0"); } /** @@ -623,16 +631,24 @@ function quiz_get_renderoptions($reviewoptions, $state) { /** -* Determine review options -*/ -function quiz_get_reviewoptions($quiz, $attempt, $isteacher=false) { + * Determine review options + * + * @param object $quiz the quiz instance. + * @param object $attempt the attempt in question. + * @param $context the roles and permissions context, + * normally the context for the quiz module instance. + * + * @return object an object with boolean fields responses, scores, feedback, + * correct_responses, solutions and commentary + */ +function quiz_get_reviewoptions($quiz, $attempt, $context=null) { $options = new stdClass; $options->readonly = true; // Provide the links to the question review and comment script $options->questionreviewlink = '/mod/quiz/reviewquestion.php'; - if ($isteacher and !$attempt->preview) { + if ($context && has_capability('mod/quiz:viewreports'. $context) and !$attempt->preview) { // The teacher should be shown everything except during preview when the teachers // wants to see just what the students see $options->responses = true; diff --git a/mod/quiz/report/grading/report.php b/mod/quiz/report/grading/report.php index 9400bbf520..a95729865a 100644 --- a/mod/quiz/report/grading/report.php +++ b/mod/quiz/report/grading/report.php @@ -321,6 +321,9 @@ class quiz_report extends quiz_default_report { $userid = optional_param('userid', 0, PARAM_INT); $attemptid = optional_param('attemptid', 0, PARAM_INT); + // TODO get the context, and put in proper roles an permissions checks. + $context = NULL; + $questions[$question->id] = &$question; $usehtmleditor = can_use_richtext_editor(); $users = get_course_students($quiz->course); @@ -365,7 +368,7 @@ class quiz_report extends quiz_default_report { // with only one question there is only one entry in this array $state = &$states[$question->id]; - $options = quiz_get_reviewoptions($quiz, $attempt, true); + $options = quiz_get_reviewoptions($quiz, $attempt, $context); unset($options->questioncommentlink); $copy = $state->manualcomment; $state->manualcomment = ''; diff --git a/mod/quiz/review.php b/mod/quiz/review.php index ef267c76ae..d4dcb460ff 100644 --- a/mod/quiz/review.php +++ b/mod/quiz/review.php @@ -43,7 +43,7 @@ $context = get_context_instance(CONTEXT_MODULE, $cm->id); $coursecontext = get_context_instance(CONTEXT_COURSE, $cm->course); $isteacher = isteacher($course->id); - $options = quiz_get_reviewoptions($quiz, $attempt, $isteacher); + $options = quiz_get_reviewoptions($quiz, $attempt, $context); $popup = $isteacher ? 0 : $quiz->popup; // Controls whether this is shown in a javascript-protected window. // this capability is not correct, need to find the right one diff --git a/mod/quiz/reviewquestion.php b/mod/quiz/reviewquestion.php index 24cda7a7e8..c260d14428 100644 --- a/mod/quiz/reviewquestion.php +++ b/mod/quiz/reviewquestion.php @@ -58,9 +58,9 @@ } require_login($course->id, false, $cm); - $isteacher = isteacher($course->id); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); - if (!$isteacher) { + if (!has_capability('mod/quiz:viewreports', $context)) { if (!$attempt->timefinish) { redirect('attempt.php?q='.$quiz->id); } @@ -112,9 +112,9 @@ restore_question_state($question, $state); $state->last_graded = $state; - $options = quiz_get_reviewoptions($quiz, $attempt, $isteacher); + $options = quiz_get_reviewoptions($quiz, $attempt, $context); $options->validation = ($state->event == QUESTION_EVENTVALIDATE); - $options->history = ($isteacher and !$attempt->preview) ? 'all' : 'graded'; + $options->history = (has_capability('mod/quiz:viewreports', $context) and !$attempt->preview) ? 'all' : 'graded'; /// Print infobox $table->align = array("right", "left"); @@ -126,7 +126,7 @@ } // print quiz name $table->data[] = array(get_string('modulename', 'quiz').':', format_string($quiz->name)); - if ($isteacher and count($attempts = get_records_select('quiz_attempts', "quiz = '$quiz->id' AND userid = '$attempt->userid'", 'attempt ASC')) > 1) { + if (has_capability('mod/quiz:viewreports', $context) and count($attempts = get_records_select('quiz_attempts', "quiz = '$quiz->id' AND userid = '$attempt->userid'", 'attempt ASC')) > 1) { // print list of attempts $attemptlist = ''; foreach ($attempts as $at) { diff --git a/mod/quiz/tabs.php b/mod/quiz/tabs.php index f4c5367418..0866d8e433 100644 --- a/mod/quiz/tabs.php +++ b/mod/quiz/tabs.php @@ -29,18 +29,24 @@ $row = array(); $inactive = array(); - if (has_capability('mod/quiz:viewreports', $context)) { + if (has_capability('mod/quiz:view', $context)) { $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')); } if (has_capability('mod/quiz:viewreports', $context)) { - $row[] = new tabobject('preview', "$CFG->wwwroot/mod/quiz/attempt.php?q=$quiz->id", get_string('preview', 'quiz')); + $row[] = new tabobject('reports', "$CFG->wwwroot/mod/quiz/report.php?q=$quiz->id", get_string('results', 'quiz')); } if (has_capability('mod/quiz:preview', $context)) { + $row[] = new tabobject('preview', "$CFG->wwwroot/mod/quiz/attempt.php?q=$quiz->id", get_string('preview', 'quiz')); + } + if (has_capability('mod/quiz:manage', $context)) { $row[] = new tabobject('edit', "$CFG->wwwroot/mod/quiz/edit.php?quizid=$quiz->id", get_string('edit')); } - $tabs[] = $row; + if ($currenttab == 'info' && count($row) == 1) { + // Don't show only an info tab (e.g. to students). + } else { + $tabs[] = $row; + } if ($currenttab == 'reports' and isset($mode)) { $inactive[] = 'reports'; diff --git a/mod/quiz/version.php b/mod/quiz/version.php index a9c4f46ea0..be8dcd05a3 100644 --- a/mod/quiz/version.php +++ b/mod/quiz/version.php @@ -5,7 +5,7 @@ // This fragment is called by moodle_needs_upgrading() and /admin/index.php //////////////////////////////////////////////////////////////////////////////// -$module->version = 2006082400; // The (date) version of this module +$module->version = 2006082500; // The (date) version of this module $module->requires = 2006080900; // Requires this Moodle version $module->cron = 0; // How often should cron check this module (seconds)? diff --git a/mod/quiz/view.php b/mod/quiz/view.php index ef34ea0730..913037e072 100644 --- a/mod/quiz/view.php +++ b/mod/quiz/view.php @@ -10,7 +10,7 @@ $id = optional_param('id', 0, PARAM_INT); // Course Module ID, or $q = optional_param('q', 0, PARAM_INT); // quiz ID $edit = optional_param('edit', -1, PARAM_BOOL); - + if ($id) { if (! $cm = get_coursemodule_from_id('quiz', $id)) { error("There is no coursemodule with id $id"); @@ -36,18 +36,18 @@ } } + // Check login and get context. require_login($course->id, false, $cm); - $isteacher = isteacher($course->id); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + require_capability('mod/quiz:view', $context); // if no questions have been set up yet redirect to edit.php - if (!$quiz->questions and isteacheredit($course->id)) { + if (!$quiz->questions and has_capability('mod/quiz:manage', $context)) { redirect('edit.php?quizid='.$quiz->id); } add_to_log($course->id, "quiz", "view", "view.php?id=$cm->id", $quiz->id, $cm->id); - $timenow = time(); - // Initialize $PAGE, compute blocks $PAGE = page_create_instance($quiz->id); $pageblocks = blocks_setup($PAGE); @@ -59,8 +59,8 @@ } //only check pop ups if the user is not a teacher, and popup is set - - $bodytags = (isteacher($course->id) or !$quiz->popup)?'':'onload="popupchecker(\'This section of the test is in secure mode, this means that you need to take the quiz in a secure window. Please turn off your popup blocker. Thank you.\');"'; + + $bodytags = (has_capability('mod/quiz:attempt', $context) && $quiz->popup)?'onload="popupchecker(\'This section of the test is in secure mode, this means that you need to take the quiz in a secure window. Please turn off your popup blocker. Thank you.\');"':''; $PAGE->print_header($course->shortname.': %fullname%','',$bodytags); echo ''; @@ -73,16 +73,12 @@ echo '
'; - $available = ($quiz->timeopen < $timenow and ($timenow < $quiz->timeclose or !$quiz->timeclose)) || $isteacher; - // Print the main part of the page - // Print heading and tabs for teacher - if ($isteacher) { - $currenttab = 'info'; - include('tabs.php'); - } - + // Print heading and tabs (if there is more than one). + $currenttab = 'info'; + include('tabs.php'); + // Print quiz name and description. print_heading(format_string($quiz->name)); @@ -94,12 +90,14 @@ // Print information about number of attempts and grading method. if ($quiz->attempts > 1) { echo "

".get_string("attemptsallowed", "quiz").": $quiz->attempts

"; - } + } if ($quiz->attempts != 1) { echo "

".get_string("grademethod", "quiz").": ".$QUIZ_GRADE_METHOD[$quiz->grademethod]."

"; } - + // Print information about timings. + $timenow = time(); + $available = ($quiz->timeopen < $timenow and ($timenow < $quiz->timeclose or !$quiz->timeclose)); if ($available) { if ($quiz->timelimit) { echo "

".get_string("quiztimelimit","quiz", format_time($quiz->timelimit * 60))."

"; @@ -111,299 +109,278 @@ echo "

".get_string("quizclosed", "quiz", userdate($quiz->timeclose)); } - - // This is all the teacher will get - if ($isteacher) { + // Show number of attempts summary to those who can view reports. + if (has_capability('mod/quiz:viewreports', $context)) { if ($a->attemptnum = count_records('quiz_attempts', 'quiz', $quiz->id, 'preview', 0)) { $a->studentnum = count_records_select('quiz_attempts', "quiz = '$quiz->id' AND preview = '0'", 'COUNT(DISTINCT userid)'); $a->studentstring = $course->students; - + notify("id\">".get_string('numattempts', 'quiz', $a).''); } - - end_page($course); - exit; } - // Guests can't do a quiz, so offer them a choice of logging in going back. + // Guests can't do a quiz, so offer them a choice of logging in or going back. + + // TODO, work out what to do about this under roles and permissions. + // You have to be logged in to do a quiz, because attempts are tied to + // userid, and so if guests were allowed to attempt quizzes, all guests + // would see all attempts, and it would be confusing. + // + // So for courses that allow guest access, it is good to offer people an easy + // way to log in at this point if they have got this far before logging in. if (isguest()) { $loginurl = $CFG->wwwroot.'/login/index.php'; if (!empty($CFG->loginhttps)) { $loginurl = str_replace('http:','https:', $loginurl); } - notice_yesno('

' . get_string('guestsno', 'quiz') . "

\n\n

" . + notice_yesno('

' . get_string('guestsno', 'quiz') . "

\n\n

" . get_string('liketologin') . '

', $loginurl, $_SERVER['HTTP_REFERER']); - - end_page($course); - exit; } - // Get this user's attempts. - $attempts = quiz_get_user_attempts($quiz->id, $USER->id); - $unfinished = false; - if ($unfinishedattempt = quiz_get_user_attempt_unfinished($quiz->id, $USER->id)) { - $attempts[] = $unfinishedattempt; - $unfinished = true; - } - $numattempts = count($attempts); + if (has_capability('mod/quiz:attempt', $context)) { - $strattempt = get_string("attempt", "quiz"); - $strtimetaken = get_string("timetaken", "quiz"); - $strtimecompleted = get_string("timecompleted", "quiz"); - $strgrade = get_string("grade"); - $strmarks = get_string('marks', 'quiz'); - $strfeedback = get_string('feedback', 'quiz'); + // Get this user's attempts. + $attempts = quiz_get_user_attempts($quiz->id, $USER->id); + $unfinished = false; + if ($unfinishedattempt = quiz_get_user_attempt_unfinished($quiz->id, $USER->id)) { + $attempts[] = $unfinishedattempt; + $unfinished = true; + } + $numattempts = count($attempts); + + $mygrade = quiz_get_best_grade($quiz, $USER->id); - $mygrade = quiz_get_best_grade($quiz, $USER->id); + // Get some strings. + $strattempt = get_string("attempt", "quiz"); + $strtimetaken = get_string("timetaken", "quiz"); + $strtimecompleted = get_string("timecompleted", "quiz"); + $strgrade = get_string("grade"); + $strmarks = get_string('marks', 'quiz'); + $strfeedback = get_string('feedback', 'quiz'); - if ($attempts) { // Print table with existing attempts + if ($attempts) { - // Work out which columns we need, taking account what data is available in each attempt. - $gradecolumn = 0; - $overallstats = 1; - foreach ($attempts as $attempt) { - $attemptoptions = quiz_get_reviewoptions($quiz, $attempt, $isteacher); - if ($attemptoptions->scores) { - $gradecolumn = 1; - } else { - $overallstats = 0; + // Work out which columns we need, taking account what data is available in each attempt. + $gradecolumn = 0; + $overallstats = 1; + foreach ($attempts as $attempt) { + $attemptoptions = quiz_get_reviewoptions($quiz, $attempt, $context); + if ($attemptoptions->scores) { + $gradecolumn = 1; + } else { + $overallstats = 0; + } + } + $gradecolumn = $gradecolumn && $quiz->grade && $quiz->sumgrades; + $markcolumn = $gradecolumn && ($quiz->grade <> $quiz->sumgrades); + $feedbackcolumn = quiz_has_feedback($quiz->id); + + // prepare table header + $table->head = array($strattempt, $strtimecompleted); + $table->align = array("center", "left"); + $table->size = array("", ""); + if ($markcolumn) { + $table->head[] = "$strmarks / $quiz->sumgrades"; + $table->align[] = 'right'; + $table->size[] = ''; + } + if ($gradecolumn) { + $table->head[] = "$strgrade / $quiz->grade"; + $table->align[] = 'right'; + $table->size[] = ''; + } + if ($feedbackcolumn) { + $table->head[] = $strfeedback; + $table->align[] = 'left'; + $table->size[] = ''; + } + if (isset($quiz->showtimetaken)) { + $table->head[] = $strtimetaken; + $table->align[] = 'left'; + $table->size[] = ''; } - } - $gradecolumn = $gradecolumn && $quiz->grade && $quiz->sumgrades; - $markcolumn = $gradecolumn && ($quiz->grade <> $quiz->sumgrades); - $feedbackcolumn = quiz_has_feedback($quiz->id); - - // prepare table header - $table->head = array($strattempt, $strtimecompleted); - $table->align = array("center", "left"); - $table->size = array("", ""); - if ($markcolumn) { - $table->head[] = "$strmarks / $quiz->sumgrades"; - $table->align[] = 'right'; - $table->size[] = ''; - } - if ($gradecolumn) { - $table->head[] = "$strgrade / $quiz->grade"; - $table->align[] = 'right'; - $table->size[] = ''; - } - if ($feedbackcolumn) { - $table->head[] = $strfeedback; - $table->align[] = 'left'; - $table->size[] = ''; - } - if (isset($quiz->showtimetaken)) { - $table->head[] = $strtimetaken; - $table->align[] = 'left'; - $table->size[] = ''; - } - // One row for each attempt - foreach ($attempts as $attempt) { - $attemptoptions = quiz_get_reviewoptions($quiz, $attempt, $isteacher); - $row = array(); - - // Add the attempt number, making it a link, if appropriate. - $row[] = make_review_link('#' . $attempt->attempt, $quiz, $attempt); - - // prepare strings for time taken and date completed - $timetaken = ''; - $datecompleted = ''; - if ($attempt->timefinish > 0) { - // attempt has finished - $timetaken = format_time($attempt->timefinish - $attempt->timestart); - $datecompleted = userdate($attempt->timefinish); - } else if ($available) { - // The attempt is still in progress. - $timetaken = format_time(time() - $attempt->timestart); - $datecompleted = ''; - } else if ($quiz->timeclose) { - // The attempt was not completed but is also not available any more becuase the quiz is closed. - $timetaken = format_time($quiz->timeclose - $attempt->timestart); - $datecompleted = userdate($quiz->timeclose); - } else { - // Something wheird happened. + // One row for each attempt + foreach ($attempts as $attempt) { + $attemptoptions = quiz_get_reviewoptions($quiz, $attempt, $context); + $row = array(); + + // Add the attempt number, making it a link, if appropriate. + $row[] = make_review_link('#' . $attempt->attempt, $quiz, $attempt); + + // prepare strings for time taken and date completed $timetaken = ''; $datecompleted = ''; - } - $row[] = $datecompleted; - - if ($markcolumn) { - if ($attemptoptions->scores) { - $row[] = make_review_link(round($attempt->sumgrades, $quiz->decimalpoints), $quiz, $attempt); + if ($attempt->timefinish > 0) { + // attempt has finished + $timetaken = format_time($attempt->timefinish - $attempt->timestart); + $datecompleted = userdate($attempt->timefinish); + } else if ($available) { + // The attempt is still in progress. + $timetaken = format_time(time() - $attempt->timestart); + $datecompleted = ''; + } else if ($quiz->timeclose) { + // The attempt was not completed but is also not available any more becuase the quiz is closed. + $timetaken = format_time($quiz->timeclose - $attempt->timestart); + $datecompleted = userdate($quiz->timeclose); } else { - $row[] = ''; + // Something wheird happened. + $timetaken = ''; + $datecompleted = ''; } - } + $row[] = $datecompleted; - // Ouside the if becuase we may be showing feedback but not grades. - $attemptgrade = quiz_rescale_grade($attempt->sumgrades, $quiz); - if ($gradecolumn) { - if ($attemptoptions->scores) { - // highlight the highest grade if appropriate - if ($overallstats && !is_null($mygrade) && $attemptgrade == $mygrade && $quiz->grademethod == QUIZ_GRADEHIGHEST) { - $formattedgrade = "$attemptgrade"; + if ($markcolumn) { + if ($attemptoptions->scores) { + $row[] = make_review_link(round($attempt->sumgrades, $quiz->decimalpoints), $quiz, $attempt); } else { - $formattedgrade = $attemptgrade; + $row[] = ''; } - - $row[] = make_review_link($formattedgrade, $quiz, $attempt); - } else { - $row[] = ''; } - } - - if ($feedbackcolumn) { - if ($attemptoptions->feedback) { - $row[] = quiz_feedback_for_grade($attemptgrade, $quiz->id); - } else { - $row[] = ''; + + // Ouside the if because we may be showing feedback but not grades. + $attemptgrade = quiz_rescale_grade($attempt->sumgrades, $quiz); + + if ($gradecolumn) { + if ($attemptoptions->scores) { + // highlight the highest grade if appropriate + if ($overallstats && !is_null($mygrade) && $attemptgrade == $mygrade && $quiz->grademethod == QUIZ_GRADEHIGHEST) { + $formattedgrade = "$attemptgrade"; + } else { + $formattedgrade = $attemptgrade; + } + + $row[] = make_review_link($formattedgrade, $quiz, $attempt); + } else { + $row[] = ''; + } } - } - - if (isset($quiz->showtimetaken)) { - $row[] = $timetaken; - } - - $table->data[] = $row; + + if ($feedbackcolumn) { + if ($attemptoptions->feedback) { + $row[] = quiz_feedback_for_grade($attemptgrade, $quiz->id); + } else { + $row[] = ''; + } + } + + if (isset($quiz->showtimetaken)) { + $row[] = $timetaken; + } + + $table->data[] = $row; + } // End of loop over attempts. + print_table($table); } - print_table($table); - } - // Print information about the student's best score for this quiz if possible. - $moreattempts = $numattempts < $quiz->attempts || $quiz->attempts == 0; - if (!$moreattempts) { - print_heading(get_string("nomoreattempts", "quiz")); - } - - if ($numattempts && $quiz->sumgrades) { - if (!is_null($mygrade)) { - if ($available && $moreattempts) { - $strbestgrade = $QUIZ_GRADE_METHOD[$quiz->grademethod]; - $grademessage = "$strbestgrade: $mygrade / $quiz->grade."; - } else { - $grademessage = get_string("yourfinalgradeis", "quiz", "$mygrade / $quiz->grade"); - } - - if ($overallstats) { - print_heading($grademessage); + // Print information about the student's best score for this quiz if possible. + $moreattempts = $unfinished || $numattempts < $quiz->attempts || $quiz->attempts == 0; + if (!$moreattempts) { + print_heading(get_string("nomoreattempts", "quiz")); + } + + if ($numattempts && $quiz->sumgrades) { + if (!is_null($mygrade)) { + if ($available && $moreattempts) { + $strbestgrade = $QUIZ_GRADE_METHOD[$quiz->grademethod]; + $grademessage = "$strbestgrade: $mygrade / $quiz->grade."; + } else { + $grademessage = get_string("yourfinalgradeis", "quiz", "$mygrade / $quiz->grade"); + } + + if ($overallstats) { + print_heading($grademessage); + } + + if ($feedbackcolumn) { + echo '

', quiz_feedback_for_grade($mygrade, $quiz->id), '

'; + } } - - if ($feedbackcolumn) { - echo '

', quiz_feedback_for_grade($mygrade, $quiz->id), '

'; + + if (!($moreattempts && $available)) { + print_continue($CFG->webroot . '/course/view.php?id=' . $course->id); } } - if (!($moreattempts && $available)) { - print_continue($CFG->webroot . '/course/view.php?id=' . $course->id); - } - } - - if ($quiz->questions) { - // Print a button to start the quiz if appropriate. - if ($available && $moreattempts) { + // Print a button to start/continue an attempt, if appropriate. + if ($quiz->questions && $available && $moreattempts) { + echo "
"; echo "
"; - if ($quiz->delay1 or $quiz->delay2) { - //quiz enforced time delay - $lastattempt_obj = get_record_select('quiz_attempts', "quiz = $quiz->id AND attempt = $numattempts AND userid = $USER->id", 'timefinish'); - if ($lastattempt_obj) { - $lastattempt = $lastattempt_obj->timefinish; - } - if($numattempts == 1 && $quiz->delay1) { - if ($timenow - $quiz->delay1 > $lastattempt) { - print_start_quiz_button($quiz, $attempts, $numattempts, $unfinished, $cm); - } else { - $notify_msg = get_string('temporaryblocked', 'quiz') . ''. userdate($lastattempt + $quiz->delay1). ''; - print_simple_box($notify_msg, "center"); - } - } else if($numattempts > 1 && $quiz->delay2) { - if ($timenow - $quiz->delay2 > $lastattempt) { - print_start_quiz_button($quiz, $attempts, $numattempts, $unfinished, $cm); - } else { - $notify_msg = get_string('temporaryblocked', 'quiz') . ''. userdate($lastattempt + $quiz->delay2). ''; - print_simple_box($notify_msg, "center"); - } - } else { - print_start_quiz_button($quiz, $attempts, $numattempts, $unfinished, $cm); - } + + if ($unfinished) { + $buttontext = get_string('continueattemptquiz', 'quiz'); } else { - print_start_quiz_button($quiz, $attempts, $numattempts, $unfinished, $cm); - } - echo "
\n"; - } - } else { - // No questions in quiz. - print_heading(get_string("noquestions", "quiz")); - } - // Finish the page - this needs to be the same as in the if teacher block above. - echo '
'; - print_footer($course); + // Work out the appropriate button caption. + if ($numattempts == 0) { + $buttontext = get_string('attemptquiznow', 'quiz'); + } else { + $buttontext = get_string('reattemptquiz', 'quiz'); + } -// Utility functions ================================================================= + // Work out if the quiz is temporarily unavailable becuase of the delay option. + if (!empty($attempts)) { + $tempunavailable = ''; + $lastattempttime = end($attempts)->timefinish; + if ($numattempts == 1 && $quiz->delay1 && $timenow <= $lastattempttime + $quiz->delay1) { + $tempunavailable = get_string('temporaryblocked', 'quiz') . + ''. userdate($lastattempt + $quiz->delay1). ''; + } else if ($numattempts > 1 && $quiz->delay2 && $timenow <= $lastattempttime + $quiz->delay2) { + $tempunavailable = get_string('temporaryblocked', 'quiz') . + ''. userdate($lastattempt + $quiz->delay2). ''; + } -function quiz_review_allowed($quiz) { - // If not even responses are to be shown in review then we - // don't allow any review - if (!($quiz->review & QUIZ_REVIEW_RESPONSES)) { - return false; - } - if ((!$quiz->timeclose or time() < $quiz->timeclose) and !($quiz->review & QUIZ_REVIEW_OPEN)) { - return false; - } - if (($quiz->timeclose and time() > $quiz->timeclose) and !($quiz->review & QUIZ_REVIEW_CLOSED)) { - return false; - } - return true; -} + // If so, display a message and prevent the start button from appearing. + if ($tempunavailable) { + print_simple_box($tempunavailable, "center"); + $buttontext = ''; + } + } + } + // Actually print the start button. + if ($buttontext) { + $buttontext = htmlspecialchars($buttontext, ENT_QUOTES); + + // Do we need a confirm javascript alert? + $strconfirmstartattempt = ''; + if ($quiz->timelimit && $quiz->attempts) { + $strconfirmstartattempt = addslashes(get_string('confirmstartattempttimelimit','quiz', $quiz->attempts)); + } else if ($quiz->timelimit) { + $strconfirmstartattempt = addslashes(get_string('confirmstarttimelimit','quiz')); + } else if ($quiz->attempts) { + $strconfirmstartattempt = addslashes(get_string('confirmstartattemptlimit','quiz', $quiz->attempts)); + } -function print_start_quiz_button($quiz, $attempts, $numattempts, $unfinished, $cm) { - $strconfirmstartattempt = ''; - - if ($unfinished) { - $buttontext = get_string('continueattemptquiz', 'quiz'); - } else { - if ($numattempts) { - $buttontext = get_string('reattemptquiz', 'quiz'); - } else { - $buttontext = get_string('attemptquiznow', 'quiz'); - } - if ($quiz->timelimit && $quiz->attempts) { - $strconfirmstartattempt = addslashes(get_string('confirmstartattempttimelimit','quiz', $quiz->attempts)); - } else if ($quiz->timelimit) { - $strconfirmstartattempt = addslashes(get_string('confirmstarttimelimit','quiz')); - } else if ($quiz->attempts) { - $strconfirmstartattempt = addslashes(get_string('confirmstartattemptlimit','quiz', $quiz->attempts)); - } - } - $buttontext = htmlspecialchars($buttontext, ENT_QUOTES); - - if (!empty($quiz->popup)) { - $window = 'quizpopup'; - $windowoptions = "left=0, top=0, height='+window.screen.height+', " . - "width='+window.screen.width+', channelmode=yes, fullscreen=yes, " . - "scrollbars=yes, resizeable=no, directories=no, toolbar=no, " . - "titlebar=no, location=no, status=no, menubar=no"; - } else { - $window = '_self'; - $windowoptions = ''; - } + // Prepare options depending on whether the quiz should be a popup. + if (!empty($quiz->popup)) { + $window = 'quizpopup'; + $windowoptions = "left=0, top=0, height='+window.screen.height+', " . + "width='+window.screen.width+', channelmode=yes, fullscreen=yes, " . + "scrollbars=yes, resizeable=no, directories=no, toolbar=no, " . + "titlebar=no, location=no, status=no, menubar=no"; + } else { + $window = '_self'; + $windowoptions = ''; + } - $attempturl = "attempt.php?id=$cm->id"; - if (!empty($CFG->usesid) && !isset($_COOKIE[session_name()])) { - $attempturl = sid_process_url($attempturl); - } + // Determine the URL to use. + $attempturl = "attempt.php?id=$cm->id"; + if (!empty($CFG->usesid) && !isset($_COOKIE[session_name()])) { + $attempturl = sid_process_url($attempturl); + } + + // TODO eliminate this nasty JavaScript that prints the button. ?> @@ -411,27 +388,57 @@ document.write('\n"; - if ($attempt->timefinish && quiz_review_allowed($quiz)) { - $url = "review.php?q=$quiz->id&attempt=$attempt->id"; - if ($quiz->popup) { - $link = link_to_popup_window('/mod/quiz/' . $url, 'quizpopup', $linktext, '+window.screen.height+', '+window.screen.width+', '', $windowoptions, true); - } else { - $link = "$linktext"; + } else if (!$quiz->questions) { + print_heading(get_string("noquestions", "quiz")); } } - return $link; -} + // Should we not be seeing if we need to print right-hand-side blocks? -function end_page($course) { + // Finish the page. echo ''; print_footer($course); + +// Utility functions ================================================================= + +function quiz_review_allowed($quiz) { + return true; +} + +/** Make some text into a link to review the quiz, if that is appropriate. */ +function make_review_link($linktext, $quiz, $attempt) { + // If not even responses are to be shown in review then we don't allow any review + if (!($quiz->review & QUIZ_REVIEW_RESPONSES)) { + return $linktext; + } + + // If the quiz is still open, are reviews allowed? + if ((!$quiz->timeclose or time() < $quiz->timeclose) and !($quiz->review & QUIZ_REVIEW_OPEN)) { + // If not, don't link. + return $linktext; + } + + // If the quiz is closed, are reviews allowed? + if (($quiz->timeclose and time() > $quiz->timeclose) and !($quiz->review & QUIZ_REVIEW_CLOSED)) { + // If not, don't link. + return $linktext; + } + + // If the attempt is still open, don't link. + if ($attempt->timefinish) { + return $linktext; + } + + $url = "review.php?q=$quiz->id&attempt=$attempt->id"; + if ($quiz->popup) { + $windowoptions = "left=0, top=0, channelmode=yes, fullscreen=yes, scrollbars=yes, resizeable=no, directories=no, toolbar=no, titlebar=no, location=no, status=no, menubar=no"; + return link_to_popup_window('/mod/quiz/' . $url, 'quizpopup', $linktext, '+window.screen.height+', '+window.screen.width+', '', $windowoptions, true); + } else { + return "$linktext"; + } } ?> -- 2.39.5