MDL-3030 quiz overdue handling: display message on the summary page.
[moodle.git] / mod / quiz / review.php
CommitLineData
83192608 1<?php
b2607ccc
TH
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
ee1fb969 17/**
f63a4ff2 18 * This page prints a review of a particular quiz attempt
19 *
b2607ccc
TH
20 * It is used either by the student whose attempts this is, after the attempt,
21 * or by a teacher reviewing another's attempt during or afterwards.
22 *
ba643847 23 * @package mod
b2607ccc 24 * @subpackage quiz
ba643847
TH
25 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
f63a4ff2 27 */
29d5d0b4 28
ba643847 29
b2607ccc
TH
30require_once(dirname(__FILE__) . '/../../config.php');
31require_once($CFG->dirroot . '/mod/quiz/locallib.php');
32require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
33
34$attemptid = required_param('attempt', PARAM_INT);
35$page = optional_param('page', 0, PARAM_INT);
36$showall = optional_param('showall', 0, PARAM_BOOL);
37
38$url = new moodle_url('/mod/quiz/review.php', array('attempt'=>$attemptid));
39if ($page !== 0) {
40 $url->param('page', $page);
41}
42if ($showall !== 0) {
43 $url->param('showall', $showall);
44}
45$PAGE->set_url($url);
46
47$attemptobj = quiz_attempt::create($attemptid);
48
49// Check login.
50require_login($attemptobj->get_course(), false, $attemptobj->get_cm());
51$attemptobj->check_review_capability();
52
53// Create an object to manage all the other (non-roles) access rules.
54$accessmanager = $attemptobj->get_access_manager(time());
55$options = $attemptobj->get_display_options(true);
56
8032cd79
TH
57// Check permissions.
58if ($attemptobj->is_own_attempt()) {
b2607ccc 59 if (!$attemptobj->is_finished()) {
45e5fbe1 60 redirect($attemptobj->attempt_url(null, $page));
d755b0f5 61
8032cd79 62 } else if (!$options->attempt) {
d755b0f5
TH
63 $accessmanager->back_to_view_page($PAGE->get_renderer('mod_quiz'),
64 $attemptobj->cannot_review_message());
83192608 65 }
8032cd79
TH
66
67} else if (!$attemptobj->is_review_allowed()) {
68 throw new moodle_quiz_exception($attemptobj->get_quizobj(), 'noreviewattempt');
b2607ccc
TH
69}
70
71// Load the questions and states needed by this page.
72if ($showall) {
73 $questionids = $attemptobj->get_slots();
74} else {
75 $questionids = $attemptobj->get_slots($page);
76}
77
78// Save the flag states, if they are being changed.
cbe87543
DL
79if ($options->flags == question_display_options::EDITABLE && optional_param('savingflags', false,
80 PARAM_BOOL)) {
b2607ccc
TH
81 require_sesskey();
82 $attemptobj->save_question_flags();
918776f4 83 redirect($attemptobj->review_url(null, $page, $showall));
b2607ccc
TH
84}
85
86// Log this review.
87add_to_log($attemptobj->get_courseid(), 'quiz', 'review', 'review.php?attempt=' .
88 $attemptobj->get_attemptid(), $attemptobj->get_quizid(), $attemptobj->get_cmid());
89
90// Work out appropriate title and whether blocks should be shown
91if ($attemptobj->is_preview_user() && $attemptobj->is_own_attempt()) {
92 $strreviewtitle = get_string('reviewofpreview', 'quiz');
93 navigation_node::override_active_url($attemptobj->start_attempt_url());
94
95} else {
96 $strreviewtitle = get_string('reviewofattempt', 'quiz', $attemptobj->get_attempt_number());
97 if (empty($attemptobj->get_quiz()->showblocks) && !$attemptobj->is_preview_user()) {
98 $PAGE->blocks->show_only_fake_blocks();
f62040ed 99 }
b2607ccc
TH
100}
101
b3782c71 102// Set up the page header
b2607ccc 103$headtags = $attemptobj->get_html_head_contributions($page, $showall);
d755b0f5
TH
104$PAGE->set_title(format_string($attemptobj->get_quiz_name()));
105$PAGE->set_heading($attemptobj->get_course()->fullname);
106$accessmanager->setup_attempt_page($PAGE);
b2607ccc 107
b2607ccc
TH
108// Summary table start ============================================================================
109
110// Work out some time-related things.
111$attempt = $attemptobj->get_attempt();
112$quiz = $attemptobj->get_quiz();
113$overtime = 0;
114
115if ($attempt->timefinish) {
116 if ($timetaken = ($attempt->timefinish - $attempt->timestart)) {
b3782c71 117 if ($quiz->timelimit && $timetaken > ($quiz->timelimit + 60)) {
b2607ccc
TH
118 $overtime = $timetaken - $quiz->timelimit;
119 $overtime = format_time($overtime);
56ed242b 120 }
b2607ccc 121 $timetaken = format_time($timetaken);
ee1fb969 122 } else {
b2607ccc 123 $timetaken = "-";
99a1bf3d 124 }
b2607ccc
TH
125} else {
126 $timetaken = get_string('unfinished', 'quiz');
127}
128
3a5da40b 129// Prepare summary informat about the whole attempt.
b3782c71 130$summarydata = array();
b2607ccc
TH
131if (!$attemptobj->get_quiz()->showuserpicture && $attemptobj->get_userid() != $USER->id) {
132 // If showuserpicture is true, the picture is shown elsewhere, so don't repeat it.
133 $student = $DB->get_record('user', array('id' => $attemptobj->get_userid()));
b3782c71
TH
134 $usrepicture = new user_picture($student);
135 $usrepicture->courseid = $attemptobj->get_courseid();
136 $summarydata['user'] = array(
137 'title' => $usrepicture,
138 'content' => new action_link(new moodle_url('/user/view.php', array(
139 'id' => $student->id, 'course' => $attemptobj->get_courseid())),
140 fullname($student, true)),
141 );
b2607ccc
TH
142}
143if ($attemptobj->has_capability('mod/quiz:viewreports')) {
918776f4 144 $attemptlist = $attemptobj->links_to_other_attempts($attemptobj->review_url(null, $page,
cbe87543 145 $showall));
b2607ccc 146 if ($attemptlist) {
b3782c71
TH
147 $summarydata['attemptlist'] = array(
148 'title' => get_string('attempts', 'quiz'),
149 'content' => $attemptlist,
150 );
29d5d0b4 151 }
b2607ccc
TH
152}
153
b3782c71
TH
154// Timing information.
155$summarydata['startedon'] = array(
156 'title' => get_string('startedon', 'quiz'),
157 'content' => userdate($attempt->timestart),
158);
b2607ccc 159
b3782c71
TH
160if ($attempt->timefinish) {
161 $summarydata['completedon'] = array(
162 'title' => get_string('completedon', 'quiz'),
163 'content' => userdate($attempt->timefinish),
164 );
165 $summarydata['timetaken'] = array(
166 'title' => get_string('timetaken', 'quiz'),
b2817f80 167 'content' => $timetaken,
b3782c71
TH
168 );
169}
b2607ccc 170
b3782c71
TH
171if (!empty($overtime)) {
172 $summarydata['overdue'] = array(
173 'title' => get_string('overdue', 'quiz'),
98754195 174 'content' => $overtime,
b3782c71
TH
175 );
176}
9c22b42e 177
b3782c71
TH
178// Show marks (if the user is allowed to see marks at the moment).
179$grade = quiz_rescale_grade($attempt->sumgrades, $quiz, false);
180if ($options->marks >= question_display_options::MARK_AND_MAX && quiz_has_grades($quiz)) {
4fc3d7e5 181
b3782c71
TH
182 if (!$attempt->timefinish) {
183 $summarydata['grade'] = array(
184 'title' => get_string('grade', 'quiz'),
185 'content' => get_string('attemptstillinprogress', 'quiz'),
186 );
187
188 } else if (is_null($grade)) {
189 $summarydata['grade'] = array(
190 'title' => get_string('grade', 'quiz'),
191 'content' => quiz_format_grade($quiz, $grade),
192 );
193
194 } else {
195 // Show raw marks only if they are different from the grade (like on the view page).
196 if ($quiz->grade != $quiz->sumgrades) {
f39cf78c 197 $a = new stdClass();
b3782c71
TH
198 $a->grade = quiz_format_grade($quiz, $attempt->sumgrades);
199 $a->maxgrade = quiz_format_grade($quiz, $quiz->sumgrades);
200 $summarydata['marks'] = array(
201 'title' => get_string('marks', 'quiz'),
202 'content' => get_string('outofshort', 'quiz', $a),
203 );
b2607ccc 204 }
b2607ccc 205
b3782c71
TH
206 // Now the scaled grade.
207 $a = new stdClass();
208 $a->grade = html_writer::tag('b', quiz_format_grade($quiz, $grade));
209 $a->maxgrade = quiz_format_grade($quiz, $quiz->grade);
210 if ($quiz->grade != 100) {
211 $a->percent = html_writer::tag('b', format_float(
212 $attempt->sumgrades * 100 / $quiz->sumgrades, 0));
213 $formattedgrade = get_string('outofpercent', 'quiz', $a);
214 } else {
215 $formattedgrade = get_string('outof', 'quiz', $a);
216 }
217 $summarydata['grade'] = array(
218 'title' => get_string('grade', 'quiz'),
219 'content' => $formattedgrade,
220 );
f39cf78c 221 }
b2607ccc
TH
222}
223
b3782c71
TH
224// Feedback if there is any, and the user is allowed to see it now.
225$feedback = $attemptobj->get_overall_feedback($grade);
226if ($options->overallfeedback && $feedback) {
227 $summarydata['feedback'] = array(
228 'title' => get_string('feedback', 'quiz'),
229 'content' => $feedback,
230 );
b2607ccc
TH
231}
232
233// Summary table end ==============================================================================
234
b2607ccc 235if ($showall) {
b3782c71 236 $slots = $attemptobj->get_slots();
b2607ccc
TH
237 $lastpage = true;
238} else {
b3782c71 239 $slots = $attemptobj->get_slots($page);
b2607ccc
TH
240 $lastpage = $attemptobj->is_last_page($page);
241}
b2607ccc 242
b3782c71 243$output = $PAGE->get_renderer('mod_quiz');
b2607ccc 244
b3782c71
TH
245// Arrange for the navigation to be displayed.
246$navbc = $attemptobj->get_navigation_panel($output, 'quiz_review_nav_panel', $page, $showall);
34b037de
TH
247$regions = $PAGE->blocks->get_regions();
248$PAGE->blocks->add_fake_block($navbc, reset($regions));
b3782c71
TH
249
250echo $output->review_page($attemptobj, $slots, $page, $showall, $lastpage, $options, $summarydata);