MDL-15648: Used existing functionality to ensure that forum 'mark read' only marks...
[moodle.git] / mod / quiz / review.php
CommitLineData
d1290cec 1<?php // $Id$
ee1fb969 2/**
f63a4ff2 3 * This page prints a review of a particular quiz attempt
4 *
4fc3d7e5 5 * @author Martin Dougiamas and many others.
f63a4ff2 6 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
7 * @package quiz
8 */
29d5d0b4 9
4fc3d7e5 10 require_once(dirname(__FILE__) . '/../../config.php');
c52c62d1 11 require_once($CFG->dirroot . '/mod/quiz/locallib.php');
29d5d0b4 12
4fc3d7e5 13 $attemptid = required_param('attempt', PARAM_INT);
14 $page = optional_param('page', 0, PARAM_INT);
ee1fb969 15 $showall = optional_param('showall', 0, PARAM_BOOL);
29d5d0b4 16
4fc3d7e5 17 $attemptobj = new quiz_attempt($attemptid);
18
19/// Check login.
20 require_login($attemptobj->get_courseid(), false, $attemptobj->get_cm());
77ed3ba5 21
29d5d0b4 22
c52c62d1 23/// Create an object to manage all the other (non-roles) access rules.
4fc3d7e5 24 $accessmanager = $attemptobj->get_access_manager(time());
25 $options = $attemptobj->get_review_options();
c52c62d1 26
27/// Work out if this is a student viewing their own attempt/teacher previewing,
28/// or someone with 'mod/quiz:viewreports' reviewing someone elses attempt.
4fc3d7e5 29 $reviewofownattempt = $attemptobj->get_userid() == $USER->id &&
30 (!$attemptobj->is_preview_user() || $attemptobj->is_preview());
c52c62d1 31
32/// Permissions checks for normal users who do not have quiz:viewreports capability.
4fc3d7e5 33 if (!$attemptobj->has_capability('mod/quiz:viewreports')) {
c52c62d1 34 /// Can't review during the attempt - send them back to the attempt page.
4fc3d7e5 35 if (!$attemptobj->is_finished()) {
36 redirect($attemptobj->attempt_url(0, $page));
29d5d0b4 37 }
c52c62d1 38 /// Can't review other users' attempts.
39 if (!$reviewofownattempt) {
40 quiz_error($quiz, 'reviewnotallowed');
41 }
42 /// Can't review unless Students may review -> Responses option is turned on.
a4faed69 43 if (!$options->responses) {
4fc3d7e5 44 $accessmanager->back_to_view_page($attemptobj->is_preview_user(),
c52c62d1 45 $accessmanager->cannot_review_message($options));
34283aa8 46 }
29d5d0b4 47 }
48
c52c62d1 49/// Log this review.
4fc3d7e5 50 add_to_log($attemptobj->get_courseid(), 'quiz', 'review', 'review.php?attempt=' .
51 $attemptobj->get_attemptid(), $attemptobj->get_quizid(), $attemptobj->get_cmid());
29d5d0b4 52
4fc3d7e5 53/// load the questions and states needed by this page.
c52c62d1 54 if ($showall) {
4fc3d7e5 55 $questionids = $attemptobj->get_question_ids();
c52c62d1 56 } else {
4fc3d7e5 57 $questionids = $attemptobj->get_question_ids($page);
58 }
59 $attemptobj->load_questions($questionids);
60 $attemptobj->load_question_states($questionids);
2d05b472 61
38e179a4 62/// Work out appropriate title.
4fc3d7e5 63 if ($attemptobj->is_preview_user() && $reviewofownattempt) {
38e179a4 64 $strreviewtitle = get_string('reviewofpreview', 'quiz');
65 } else {
b9b3aa94 66 $strreviewtitle = get_string('reviewofattempt', 'quiz', $attemptobj->get_attempt_number());
38e179a4 67 }
68
c52c62d1 69/// Print the page header
4fc3d7e5 70 $headtags = $attemptobj->get_html_head_contributions($page);
71 if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
c52c62d1 72 $accessmanager->setup_secure_page($course->shortname.': '.format_string($quiz->name), $headtags);
ee1fb969 73 } else {
4fc3d7e5 74 print_header_simple(format_string($attemptobj->get_quiz_name()), '', $attemptobj->navigation($strreviewtitle),
75 '', $headtags, true, $attemptobj->update_module_button());
ee1fb969 76 }
b7f35820 77 echo '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>'; // for overlib
78
c52c62d1 79/// Print tabs if they should be there.
4fc3d7e5 80 if ($attemptobj->is_preview_user()) {
c52c62d1 81 if ($reviewofownattempt) {
0a5b58af 82 $currenttab = 'preview';
83 } else {
84 $currenttab = 'reports';
85 $mode = '';
86 }
ee1fb969 87 include('tabs.php');
ee1fb969 88 }
c52c62d1 89
90/// Print heading.
38e179a4 91 print_heading(format_string($quiz->name));
4fc3d7e5 92 if ($attemptobj->is_preview_user() && $reviewofownattempt) {
78e7a3dd 93 $attemptobj->print_restart_preview_button();
99a1bf3d 94 }
38e179a4 95 print_heading($strreviewtitle);
99a1bf3d 96
c52c62d1 97/// Finish review link.
98 if ($reviewofownattempt) {
4fc3d7e5 99 $accessmanager->print_finish_review_link($attemptobj->is_preview_user());
99a1bf3d 100 }
ad1a74e0 101
4fc3d7e5 102/// Summary table start ============================================================================
103
9c22b42e 104/// Work out some time-related things.
4fc3d7e5 105 $attempt = $attemptobj->get_attempt();
106 $quiz = $attemptobj->get_quiz();
107 $timelimit = $quiz->timelimit * 60;
235987c5 108 $overtime = 0;
d4961620 109
ee1fb969 110 if ($attempt->timefinish) {
111 if ($timetaken = ($attempt->timefinish - $attempt->timestart)) {
112 if($timelimit && $timetaken > ($timelimit + 60)) {
113 $overtime = $timetaken - $timelimit;
114 $overtime = format_time($overtime);
115 }
116 $timetaken = format_time($timetaken);
117 } else {
118 $timetaken = "-";
d4961620 119 }
29d5d0b4 120 } else {
ee1fb969 121 $timetaken = get_string('unfinished', 'quiz');
29d5d0b4 122 }
9c22b42e 123
124/// Print summary table about the whole attempt.
125/// First we assemble all the rows that are appopriate to the current situation in
126/// an array, then later we only output the table if there are any rows to show.
127 $rows = array();
b9b3aa94 128 if ($attemptobj->get_userid() <> $USER->id) {
129 $student = $DB->get_record('user', array('id' => $attemptobj->get_userid()));
130 $picture = print_user_picture($student, $attemptobj->get_courseid(), $student->picture, false, true);
9c22b42e 131 $rows[] = '<tr><th scope="row" class="cell">' . $picture . '</th><td class="cell"><a href="' .
b9b3aa94 132 $CFG->wwwroot . '/user/view.php?id=' . $student->id . '&amp;course=' . $attemptobj->get_courseid() . '">' .
9c22b42e 133 fullname($student, true) . '</a></td></tr>';
76cacec8 134 }
9c22b42e 135 if (has_capability('mod/quiz:viewreports', $context) &&
9cf4a18b 136 count($attempts = $DB->get_records_select('quiz_attempts', "quiz = ? AND userid = ?", array($quiz->id, $attempt->userid), 'attempt ASC')) > 1) {
9c22b42e 137 /// List of all this user's attempts for people who can see reports.
9c22b42e 138 $attemptlist = array();
ee1fb969 139 foreach ($attempts as $at) {
9c22b42e 140 if ($at->id == $attempt->id) {
141 $attemptlist[] = '<strong>' . $at->attempt . '</strong>';
142 } else {
4fc3d7e5 143 $attemptlist[] = '<a href="' . $attemptobj->review_url(0, $page, $showall, $at->id) .
144 '">' . $at->attempt . '</a>';
9c22b42e 145 }
ee1fb969 146 }
9c22b42e 147 $rows[] = '<tr><th scope="row" class="cell">' . get_string('attempts', 'quiz') .
148 '</th><td class="cell">' . implode(', ', $attemptlist) . '</td></tr>';
ee1fb969 149 }
150
9c22b42e 151/// Timing information.
152 $rows[] = '<tr><th scope="row" class="cell">' . get_string('startedon', 'quiz') .
153 '</th><td class="cell">' . userdate($attempt->timestart) . '</td></tr>';
ee1fb969 154 if ($attempt->timefinish) {
9c22b42e 155 $rows[] = '<tr><th scope="row" class="cell">' . get_string('completedon', 'quiz') . '</th><td class="cell">' .
156 userdate($attempt->timefinish) . '</td></tr>';
157 $rows[] = '<tr><th scope="row" class="cell">' . get_string('timetaken', 'quiz') . '</th><td class="cell">' .
158 $timetaken . '</td></tr>';
ee1fb969 159 }
3a00dbfd 160 if (!empty($overtime)) {
9c22b42e 161 $rows[] = '<tr><th scope="row" class="cell">' . get_string('overdue', 'quiz') . '</th><td class="cell">' . $overtime . '</td></tr>';
d4961620 162 }
9c22b42e 163
164/// Show scores (if the user is allowed to see scores at the moment).
165 $grade = quiz_rescale_grade($attempt->sumgrades, $quiz);
15db443c 166 if ($options->scores) {
167 if ($quiz->grade and $quiz->sumgrades) {
168 if($overtime) {
169 $result->sumgrades = "0";
170 $result->grade = "0.0";
171 }
77ed3ba5 172
9c22b42e 173 /// Show raw marks only if they are different from the grade (like on the view page.
174 if ($quiz->grade != $quiz->sumgrades) {
175 $a = new stdClass;
176 $a->grade = round($attempt->sumgrades, $CFG->quiz_decimalpoints);
177 $a->maxgrade = $quiz->sumgrades;
178 $rows[] = '<tr><th scope="row" class="cell">' . get_string('marks', 'quiz') . '</th><td class="cell">' .
179 get_string('outofshort', 'quiz', $a) . '</td></tr>';
180 }
181
182 /// Now the scaled grade.
3b48ba9d 183 $a = new stdClass;
9c22b42e 184 $a->grade = '<b>' . $grade . '</b>';
3b48ba9d 185 $a->maxgrade = $quiz->grade;
9c22b42e 186 $a->percent = '<b>' . round(($attempt->sumgrades/$quiz->sumgrades)*100, 0) . '</b>';
187 $rows[] = '<tr><th scope="row" class="cell">' . get_string('grade') . '</th><td class="cell">' .
188 get_string('outofpercent', 'quiz', $a) . '</td></tr>';
d4961620 189 }
ee1fb969 190 }
9c22b42e 191
192/// Feedback if there is any, and the user is allowed to see it now.
193 $feedback = quiz_feedback_for_grade($grade, $attempt->quiz);
77ed3ba5 194 if ($options->overallfeedback && $feedback) {
9c22b42e 195 $rows[] = '<tr><th scope="row" class="cell">' . get_string('feedback', 'quiz') .
196 '</th><td class="cell">' . $feedback . '</td></tr>';
197 }
198
199/// Now output the summary table, if there are any rows to be shown.
200 if (!empty($rows)) {
201 echo '<table class="generaltable generalbox quizreviewsummary"><tbody>', "\n";
202 echo implode("\n", $rows);
203 echo "\n</tbody></table>\n";
9bc2d82a 204 }
205
4fc3d7e5 206/// Summary table end ==============================================================================
207
ee1fb969 208/// Print the navigation panel if required
4fc3d7e5 209 // TODO!!!
210 print_paging_bar($attemptobj->get_num_pages(), $page, 1, 'review.php?attempt='.$attempt->id.'&amp;');
211 echo '<div class="controls"><a href="review.php?attempt='.$attempt->id.'&amp;showall=true">';
212 print_string('showall', 'quiz');
213 echo '</a></div>';
29d5d0b4 214
ee1fb969 215/// Print all the questions
4fc3d7e5 216 if ($showall) {
217 $page = 'all';
ee1fb969 218 }
4fc3d7e5 219 foreach ($attemptobj->get_question_ids($page) as $id) {
220 $attemptobj->print_question($id);
29d5d0b4 221 }
222
ee1fb969 223 // print javascript button to close the window, if necessary
c52c62d1 224 if ($reviewofownattempt) {
4fc3d7e5 225 $accessmanager->print_finish_review_link($attemptobj->is_preview_user());
ee1fb969 226 }
29d5d0b4 227
4fc3d7e5 228 if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
c52c62d1 229 print_footer('empty');
230 } else {
ee1fb969 231 print_footer($course);
232 }
29d5d0b4 233?>