questions MDL-20276 Fixed minor issue with URL handling within the paging bar for...
[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');
bbf4f440 12 require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
29d5d0b4 13
4fc3d7e5 14 $attemptid = required_param('attempt', PARAM_INT);
15 $page = optional_param('page', 0, PARAM_INT);
ee1fb969 16 $showall = optional_param('showall', 0, PARAM_BOOL);
29d5d0b4 17
4fc3d7e5 18 $attemptobj = new quiz_attempt($attemptid);
19
20/// Check login.
21 require_login($attemptobj->get_courseid(), false, $attemptobj->get_cm());
96c7d771 22 $attemptobj->check_review_capability();
77ed3ba5 23
c52c62d1 24/// Create an object to manage all the other (non-roles) access rules.
4fc3d7e5 25 $accessmanager = $attemptobj->get_access_manager(time());
26 $options = $attemptobj->get_review_options();
c52c62d1 27
c52c62d1 28/// Permissions checks for normal users who do not have quiz:viewreports capability.
4fc3d7e5 29 if (!$attemptobj->has_capability('mod/quiz:viewreports')) {
82fd2e8b 30 /// Can't review other users' attempts.
31 if (!$attemptobj->is_own_attempt()) {
32 quiz_error($attemptobj->get_quiz(), 'notyourattempt');
33 }
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 unless Students may review -> Responses option is turned on.
a4faed69 39 if (!$options->responses) {
4fc3d7e5 40 $accessmanager->back_to_view_page($attemptobj->is_preview_user(),
c52c62d1 41 $accessmanager->cannot_review_message($options));
34283aa8 42 }
29d5d0b4 43 }
44
f62040ed 45/// Load the questions and states needed by this page.
c52c62d1 46 if ($showall) {
4fc3d7e5 47 $questionids = $attemptobj->get_question_ids();
c52c62d1 48 } else {
4fc3d7e5 49 $questionids = $attemptobj->get_question_ids($page);
50 }
51 $attemptobj->load_questions($questionids);
52 $attemptobj->load_question_states($questionids);
2d05b472 53
f62040ed 54/// Save the flag states, if they are being changed.
55 if ($options->flags == QUESTION_FLAGSEDITABLE && optional_param('savingflags', false, PARAM_BOOL)) {
56 confirm_sesskey();
57 $formdata = data_submitted();
58
59 question_save_flags($formdata, $attemptid, $questionids);
60 redirect($attemptobj->review_url(0, $page, $showall));
61 }
62
b55797b8 63/// Log this review.
64 add_to_log($attemptobj->get_courseid(), 'quiz', 'review', 'review.php?attempt=' .
65 $attemptobj->get_attemptid(), $attemptobj->get_quizid(), $attemptobj->get_cmid());
66
38e179a4 67/// Work out appropriate title.
b55797b8 68 if ($attemptobj->is_preview_user() && $attemptobj->is_own_attempt()) {
38e179a4 69 $strreviewtitle = get_string('reviewofpreview', 'quiz');
70 } else {
b9b3aa94 71 $strreviewtitle = get_string('reviewofattempt', 'quiz', $attemptobj->get_attempt_number());
38e179a4 72 }
73
d4a03c00 74/// Arrange for the navigation to be displayed.
d18675a8 75 $navbc = $attemptobj->get_navigation_panel('quiz_review_nav_panel', $page, $showall);
d4a03c00 76 $firstregion = reset($PAGE->blocks->get_regions());
77 $PAGE->blocks->add_pretend_block($navbc, $firstregion);
78
c52c62d1 79/// Print the page header
4fc3d7e5 80 $headtags = $attemptobj->get_html_head_contributions($page);
81 if ($accessmanager->securewindow_required($attemptobj->is_preview_user())) {
f330327c 82 $accessmanager->setup_secure_page($attemptobj->get_course()->shortname.': '.format_string($attemptobj->get_quiz_name()), $headtags);
ee1fb969 83 } else {
03da0c39 84 $attemptobj->navigation($strreviewtitle);
85 $PAGE->set_title(format_string($attemptobj->get_quiz_name()));
86 $PAGE->set_button($attemptobj->update_module_button());
87 echo $OUTPUT->header();
ee1fb969 88 }
b7f35820 89 echo '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>'; // for overlib
90
c52c62d1 91/// Print tabs if they should be there.
4fc3d7e5 92 if ($attemptobj->is_preview_user()) {
b55797b8 93 if ($attemptobj->is_own_attempt()) {
0a5b58af 94 $currenttab = 'preview';
95 } else {
96 $currenttab = 'reports';
97 $mode = '';
98 }
ee1fb969 99 include('tabs.php');
ee1fb969 100 }
c52c62d1 101
102/// Print heading.
b55797b8 103 if ($attemptobj->is_preview_user() && $attemptobj->is_own_attempt()) {
78e7a3dd 104 $attemptobj->print_restart_preview_button();
99a1bf3d 105 }
90cd54cb 106 echo $OUTPUT->heading($strreviewtitle);
99a1bf3d 107
4fc3d7e5 108/// Summary table start ============================================================================
109
9c22b42e 110/// Work out some time-related things.
4fc3d7e5 111 $attempt = $attemptobj->get_attempt();
112 $quiz = $attemptobj->get_quiz();
235987c5 113 $overtime = 0;
d4961620 114
ee1fb969 115 if ($attempt->timefinish) {
116 if ($timetaken = ($attempt->timefinish - $attempt->timestart)) {
84e628a0 117 if($quiz->timelimit && $timetaken > ($quiz->timelimit + 60)) {
118 $overtime = $timetaken - $quiz->timelimit;
ee1fb969 119 $overtime = format_time($overtime);
120 }
121 $timetaken = format_time($timetaken);
122 } else {
123 $timetaken = "-";
d4961620 124 }
29d5d0b4 125 } else {
ee1fb969 126 $timetaken = get_string('unfinished', 'quiz');
29d5d0b4 127 }
9c22b42e 128
129/// Print summary table about the whole attempt.
130/// First we assemble all the rows that are appopriate to the current situation in
131/// an array, then later we only output the table if there are any rows to show.
132 $rows = array();
a733c4b9 133 if (!$attemptobj->get_quiz()->showuserpicture && $attemptobj->get_userid() <> $USER->id) {
134 /// If showuserpicture is true, the picture is shown elsewhere, so don't repeat it.
b9b3aa94 135 $student = $DB->get_record('user', array('id' => $attemptobj->get_userid()));
39e37019 136 $picture = $OUTPUT->user_picture(moodle_user_picture::make($student, $attemptobj->get_courseid()));
9c22b42e 137 $rows[] = '<tr><th scope="row" class="cell">' . $picture . '</th><td class="cell"><a href="' .
b9b3aa94 138 $CFG->wwwroot . '/user/view.php?id=' . $student->id . '&amp;course=' . $attemptobj->get_courseid() . '">' .
9c22b42e 139 fullname($student, true) . '</a></td></tr>';
76cacec8 140 }
b55797b8 141 if ($attemptobj->has_capability('mod/quiz:viewreports')) {
142 $attemptlist = $attemptobj->links_to_other_attempts($attemptobj->review_url(0, $page, $showall));
143 if ($attemptlist) {
144 $rows[] = '<tr><th scope="row" class="cell">' . get_string('attempts', 'quiz') .
145 '</th><td class="cell">' . $attemptlist . '</td></tr>';
ee1fb969 146 }
ee1fb969 147 }
148
9c22b42e 149/// Timing information.
150 $rows[] = '<tr><th scope="row" class="cell">' . get_string('startedon', 'quiz') .
151 '</th><td class="cell">' . userdate($attempt->timestart) . '</td></tr>';
ee1fb969 152 if ($attempt->timefinish) {
9c22b42e 153 $rows[] = '<tr><th scope="row" class="cell">' . get_string('completedon', 'quiz') . '</th><td class="cell">' .
154 userdate($attempt->timefinish) . '</td></tr>';
155 $rows[] = '<tr><th scope="row" class="cell">' . get_string('timetaken', 'quiz') . '</th><td class="cell">' .
156 $timetaken . '</td></tr>';
ee1fb969 157 }
3a00dbfd 158 if (!empty($overtime)) {
9c22b42e 159 $rows[] = '<tr><th scope="row" class="cell">' . get_string('overdue', 'quiz') . '</th><td class="cell">' . $overtime . '</td></tr>';
d4961620 160 }
9c22b42e 161
162/// Show scores (if the user is allowed to see scores at the moment).
163 $grade = quiz_rescale_grade($attempt->sumgrades, $quiz);
15db443c 164 if ($options->scores) {
739b0711 165 if (quiz_has_grades($quiz)) {
15db443c 166 if($overtime) {
167 $result->sumgrades = "0";
168 $result->grade = "0.0";
169 }
77ed3ba5 170
9c22b42e 171 /// Show raw marks only if they are different from the grade (like on the view page.
172 if ($quiz->grade != $quiz->sumgrades) {
173 $a = new stdClass;
f88fb62c 174 $a->grade = quiz_format_grade($quiz, $attempt->sumgrades);
175 $a->maxgrade = quiz_format_grade($quiz, $attempt->sumgrades);
9c22b42e 176 $rows[] = '<tr><th scope="row" class="cell">' . get_string('marks', 'quiz') . '</th><td class="cell">' .
177 get_string('outofshort', 'quiz', $a) . '</td></tr>';
178 }
179
180 /// Now the scaled grade.
3b48ba9d 181 $a = new stdClass;
9c22b42e 182 $a->grade = '<b>' . $grade . '</b>';
f88fb62c 183 $a->maxgrade = quiz_format_grade($quiz, $quiz->grade);
9c22b42e 184 $a->percent = '<b>' . round(($attempt->sumgrades/$quiz->sumgrades)*100, 0) . '</b>';
185 $rows[] = '<tr><th scope="row" class="cell">' . get_string('grade') . '</th><td class="cell">' .
186 get_string('outofpercent', 'quiz', $a) . '</td></tr>';
d4961620 187 }
ee1fb969 188 }
9c22b42e 189
190/// Feedback if there is any, and the user is allowed to see it now.
191 $feedback = quiz_feedback_for_grade($grade, $attempt->quiz);
77ed3ba5 192 if ($options->overallfeedback && $feedback) {
9c22b42e 193 $rows[] = '<tr><th scope="row" class="cell">' . get_string('feedback', 'quiz') .
194 '</th><td class="cell">' . $feedback . '</td></tr>';
195 }
196
197/// Now output the summary table, if there are any rows to be shown.
198 if (!empty($rows)) {
199 echo '<table class="generaltable generalbox quizreviewsummary"><tbody>', "\n";
200 echo implode("\n", $rows);
201 echo "\n</tbody></table>\n";
9bc2d82a 202 }
203
4fc3d7e5 204/// Summary table end ==============================================================================
205
f62040ed 206/// Form for saving flags if necessary.
207 if ($options->flags == QUESTION_FLAGSEDITABLE) {
d4ad9adf 208 echo '<form action="' . s($attemptobj->review_url(0, $page, $showall)) .
f62040ed 209 '" method="post"><div>';
210 echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';
211 }
212
213/// Print all the questions.
4fc3d7e5 214 if ($showall) {
baef998b 215 $thispage = 'all';
216 $lastpage = true;
217 } else {
218 $thispage = $page;
219 $lastpage = $attemptobj->is_last_page($page);
ee1fb969 220 }
baef998b 221 foreach ($attemptobj->get_question_ids($thispage) as $id) {
aafdb447 222 $attemptobj->print_question($id, true, $attemptobj->review_url($id, $page, $showall));
29d5d0b4 223 }
224
f62040ed 225/// Close form if we opened it.
226 if ($options->flags == QUESTION_FLAGSEDITABLE) {
227 echo '<div class="submitbtns">' . "\n" .
228 '<input type="submit" id="savingflagssubmit" name="savingflags" value="' .
229 get_string('saveflags', 'question') . '" />' .
230 "</div>\n" .
29305001 231 "\n</div></form>\n";
cf615522 232 $PAGE->requires->js_function_call('question_flag_changer.init_flag_save_form', array('savingflagssubmit'));
f62040ed 233 }
234
baef998b 235/// Print a link to the next page.
236 echo '<div class="submitbtns">';
237 if ($lastpage) {
4fc3d7e5 238 $accessmanager->print_finish_review_link($attemptobj->is_preview_user());
baef998b 239 } else {
d18675a8 240 echo link_arrow_right(get_string('next'), s($attemptobj->review_url(0, $page + 1)));
ee1fb969 241 }
baef998b 242 echo "</div>";
243
867847e3 244 echo $OUTPUT->footer();
29d5d0b4 245?>