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 . '&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.'&'); |
211 | echo '<div class="controls"><a href="review.php?attempt='.$attempt->id.'&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 | ?> |