MDL-15350
[moodle.git] / mod / quiz / report / overview / report.php
CommitLineData
2c3968c4 1<?php
2/**
3 * This script lists student attempts
4 *
5 * @version $Id$
6 * @author Martin Dougiamas, Tim Hunt and others.
7 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
8 * @package quiz
9 *//** */
10
11require_once($CFG->libdir.'/tablelib.php');
0217f932 12require_once($CFG->dirroot.'/mod/quiz/report/overview/overviewsettings_form.php');
c35f3afc 13require_once($CFG->dirroot.'/mod/quiz/report/overview/overview_table.php');
7bbe08a2 14
c386eaa3 15class quiz_overview_report extends quiz_default_report {
7bbe08a2 16
2c3968c4 17 /**
18 * Display the report.
19 */
20 function display($quiz, $cm, $course) {
9cf4a18b 21 global $CFG, $COURSE, $DB;
7bbe08a2 22
07a7d859 23 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
24
c35f3afc 25 // Work out some display options - whether there is feedback, and whether scores should be shown.
26 $hasfeedback = quiz_has_feedback($quiz->id) && $quiz->grade > 1.e-7 && $quiz->sumgrades > 1.e-7;
27 $fakeattempt = new stdClass();
28 $fakeattempt->preview = false;
29 $fakeattempt->timefinish = $quiz->timeopen;
30 $reviewoptions = quiz_get_reviewoptions($quiz, $fakeattempt, $context);
31 $showgrades = $quiz->grade && $quiz->sumgrades && $reviewoptions->scores;
32
33 $download = optional_param('download', '', PARAM_ALPHA);
7bbe08a2 34
2fecd85b 35 if($attemptids = optional_param('attemptid', array(), PARAM_INT)) {
36 //attempts need to be deleted
37 require_capability('mod/quiz:deleteattempts', $context);
38 $attemptids = optional_param('attemptid', array(), PARAM_INT);
39 foreach($attemptids as $attemptid) {
40 add_to_log($course->id, 'quiz', 'delete attempt', 'report.php?id=' . $cm->id,
41 $attemptid, $cm->id);
42 quiz_delete_attempt($attemptid, $quiz);
43 }
44 //No need for a redirect, any attemptids that do not exist are ignored.
45 //So no problem if the user refreshes and tries to delete the same attempts
46 //twice.
7bbe08a2 47 }
18dfa593 48
01600b51 49
0217f932 50 $pageoptions = array();
51 $pageoptions['id'] = $cm->id;
52 $pageoptions['q'] = $quiz->id;
53 $pageoptions['mode'] = 'overview';
54
55 $reporturl = new moodle_url($CFG->wwwroot.'/mod/quiz/report.php', $pageoptions);
334edb71 56 $qmsubselect = quiz_report_qm_filter_select($quiz);
57
58
9cf4a18b 59
7660aa80 60 /// find out current groups mode
61 $currentgroup = groups_get_activity_group($cm, true);
62
63 $mform = new mod_quiz_report_overview_settings($reporturl, array('qmsubselect'=> $qmsubselect, 'quiz'=>$quiz, 'currentgroup'=>$currentgroup));
0217f932 64 if ($fromform = $mform->get_data()){
65 $attemptsmode = $fromform->attemptsmode;
4469159e 66 if ($qmsubselect){
67 //control is not on the form if
9cf4a18b 68 //the grading method is not set
4469159e 69 //to grade one attempt per user eg. for average attempt grade.
70 $qmfilter = $fromform->qmfilter;
71 } else {
72 $qmfilter = 0;
73 }
0217f932 74 set_user_preference('quiz_report_overview_detailedmarks', $fromform->detailedmarks);
75 set_user_preference('quiz_report_pagesize', $fromform->pagesize);
76 $detailedmarks = $fromform->detailedmarks;
77 $pagesize = $fromform->pagesize;
78 } else {
4469159e 79 $qmfilter = optional_param('qmfilter', 0, PARAM_INT);
7660aa80 80 $attemptsmode = optional_param('attemptsmode', null, PARAM_INT);
81 if ($attemptsmode === null){
82 //default
83 $attemptsmode = QUIZ_REPORT_ATTEMPTS_ALL;
84 } else if ($currentgroup){
85 //default for when a group is selected
86 if ($attemptsmode === null || $attemptsmode == QUIZ_REPORT_ATTEMPTS_ALL){
87 $attemptsmode = QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH;
88 }
89 } else if (!$currentgroup && $course->id == SITEID) {
90 //force report on front page to show all, unless a group is selected.
91 $attemptsmode = QUIZ_REPORT_ATTEMPTS_ALL;
92 }
0217f932 93 $detailedmarks = get_user_preferences('quiz_report_overview_detailedmarks', 1);
94 $pagesize = get_user_preferences('quiz_report_pagesize', 0);
95 }
ca359748 96 if (!$reviewoptions->scores) {
97 $detailedmarks = 0;
98 }
0217f932 99 if ($pagesize < 1) {
100 $pagesize = QUIZ_REPORT_DEFAULT_PAGE_SIZE;
101 }
2fecd85b 102 // We only want to show the checkbox to delete attempts
103 // if the user has permissions and if the report mode is showing attempts.
9cf4a18b 104 $candelete = has_capability('mod/quiz:deleteattempts', $context)
2fecd85b 105 && ($attemptsmode!= QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH_NO);
106
0217f932 107
108 $displayoptions = array();
109 $displayoptions['attemptsmode'] = $attemptsmode;
4469159e 110 $displayoptions['qmfilter'] = $qmfilter;
01600b51 111
c35f3afc 112 //work out the sql for this table.
a4ee9a60 113 if (!$students = get_users_by_capability($context, 'mod/quiz:attempt','','','','','','',false)){
114 $students = array();
8673a566 115 } else {
116 $students = array_keys($students);
a4ee9a60 117 }
9cf4a18b 118
c35f3afc 119 if (empty($currentgroup)) {
120 // all users who can attempt quizzes
8673a566 121 $allowed = $students;
122 $groupstudents = array();
c35f3afc 123 } else {
124 // all users who can attempt quizzes and who are in the currently selected group
a4ee9a60 125 if (!$groupstudents = get_users_by_capability($context, 'mod/quiz:attempt','','','','',$currentgroup,'',false)){
126 $groupstudents = array();
8673a566 127 } else {
128 $groupstudents = array_keys($groupstudents);
a4ee9a60 129 }
8673a566 130 $allowed = $groupstudents;
c35f3afc 131 }
a4ee9a60 132
c35f3afc 133 if ($detailedmarks) {
134 $questions = quiz_report_load_questions($quiz);
135 } else {
136 $questions = array();
137 }
8673a566 138 $table = new quiz_report_overview_table($quiz , $qmsubselect, $groupstudents,
139 $students, $detailedmarks, $questions, $candelete, $reporturl, $displayoptions);
c35f3afc 140 $table->is_downloading($download, get_string('reportoverview','quiz'),
141 "$COURSE->shortname ".format_string($quiz->name,true));
142 if (!$table->is_downloading()) {
143 // Only print headers if not asked to download data
144 $this->print_header_and_tabs($cm, $course, $quiz, "overview");
145 }
146
5ada3c8e 147 if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used
c35f3afc 148 if (!$table->is_downloading()) {
149 groups_print_activity_menu($cm, $reporturl->out(false, $displayoptions));
970d0fe0 150 }
2d7617c6 151 }
2a13e454 152 // Print information on the number of existing attempts
c35f3afc 153 if (!$table->is_downloading()) { //do not print notices when downloading
aa17ea53 154 if ($strattemptnum = quiz_num_attempt_summary($quiz, $cm, true, $currentgroup)) {
2a13e454 155 echo '<div class="quizattemptcounts">' . $strattemptnum . '</div>';
156 }
157 }
abe67b24 158 $nostudents = false;
159 if (!$students){
160 notify(get_string('nostudentsyet'));
161 $nostudents = true;
162 }else if ($currentgroup && !$groupstudents){
163 notify(get_string('nostudentsingroup'));
164 $nostudents = true;
165 }
95758992 166 if (!$table->is_downloading()) {
167 // Print display options
168 $mform->set_data($displayoptions +compact('detailedmarks', 'pagesize'));
169 $mform->display();
170 }
9cf4a18b 171
abe67b24 172 if (!$nostudents || ($attemptsmode == QUIZ_REPORT_ATTEMPTS_ALL)){
173 // Print information on the grading method and whether we are displaying
174 //
175 if (!$table->is_downloading()) { //do not print notices when downloading
176 if ($strattempthighlight = quiz_report_highlighting_grading_method($quiz, $qmsubselect, $qmfilter)) {
177 echo '<div class="quizattemptcounts">' . $strattempthighlight . '</div>';
178 }
179 }
180
181
182 $showgrades = $quiz->grade && $quiz->sumgrades && $reviewoptions->scores;
183 $hasfeedback = quiz_has_feedback($quiz->id) && $quiz->grade > 1.e-7 && $quiz->sumgrades > 1.e-7;
184
185
186 // Construct the SQL
187 $fields = $DB->sql_concat('u.id', '\'#\'', 'COALESCE(qa.attempt, \'0\')').' AS uniqueid, '.
334edb71 188 ($qmsubselect?"($qmsubselect) AS gradedattempt, ":'').
abe67b24 189 'qa.uniqueid AS attemptuniqueid, qa.id AS attempt, u.id AS userid, u.idnumber, u.firstname, u.lastname, u.picture, '.
190 'qa.sumgrades, qa.timefinish, qa.timestart, qa.timefinish - qa.timestart AS duration ';
191
192 // This part is the same for all cases - join users and quiz_attempts tables
193 $from = '{user} u ';
194 $from .= 'LEFT JOIN {quiz_attempts} qa ON qa.userid = u.id AND qa.quiz = :quizid';
195 $params = array('quizid' => $quiz->id);
196
197 if ($qmsubselect && $qmfilter){
198 $from .= ' AND '.$qmsubselect;
199 }
200 switch ($attemptsmode){
201 case QUIZ_REPORT_ATTEMPTS_ALL:
202 // Show all attempts, including students who are no longer in the course
203 $where = 'qa.id IS NOT NULL AND qa.preview = 0';
204 break;
205 case QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH:
206 // Show only students with attempts
207 list($allowed_usql, $allowed_params) = $DB->get_in_or_equal($allowed, SQL_PARAMS_NAMED, 'u0000');
208 $params += $allowed_params;
209 $where = "u.id $allowed_usql AND qa.preview = 0 AND qa.id IS NOT NULL";
210 break;
211 case QUIZ_REPORT_ATTEMPTS_STUDENTS_WITH_NO:
212 // Show only students without attempts
213 list($allowed_usql, $allowed_params) = $DB->get_in_or_equal($allowed, SQL_PARAMS_NAMED, 'u0000');
214 $params += $allowed_params;
215 $where = "u.id $allowed_usql AND qa.id IS NULL";
216 break;
217 case QUIZ_REPORT_ATTEMPTS_ALL_STUDENTS:
218 // Show all students with or without attempts
219 list($allowed_usql, $allowed_params) = $DB->get_in_or_equal($allowed, SQL_PARAMS_NAMED, 'u0000');
220 $params += $allowed_params;
221 $where = "u.id $allowed_usql AND (qa.preview = 0 OR qa.preview IS NULL)";
222 break;
223 }
224
225 $table->set_count_sql("SELECT COUNT(1) FROM $from WHERE $where", $params);
226
227
228
229 $table->set_sql($fields, $from, $where, $params);
230
231 // Define table columns
232 $columns = array();
233 $headers = array();
234
235
236 if (!$table->is_downloading() && $candelete) {
237 $columns[]= 'checkbox';
238 $headers[]= NULL;
239 }
240
241 if (!$table->is_downloading() && $CFG->grade_report_showuserimage) {
242 $columns[]= 'picture';
243 $headers[]= '';
244 }
245 if (!$table->is_downloading()){
246 $columns[]= 'fullname';
247 $headers[]= get_string('name');
248 } else {
249 $columns[]= 'lastname';
250 $headers[]= get_string('lastname');
251 $columns[]= 'firstname';
252 $headers[]= get_string('firstname');
253 }
254
255 if ($CFG->grade_report_showuseridnumber) {
256 $columns[]= 'idnumber';
257 $headers[]= get_string('idnumber');
258 }
259
260 $columns[]= 'timestart';
261 $headers[]= get_string('startedon', 'quiz');
262
263 $columns[]= 'timefinish';
264 $headers[]= get_string('timecompleted','quiz');
265
266 $columns[]= 'duration';
267 $headers[]= get_string('attemptduration', 'quiz');
268
269 if ($detailedmarks) {
270 foreach ($questions as $id => $question) {
271 // Ignore questions of zero length
272 $columns[] = 'qsgrade'.$id;
273 $headers[] = '#'.$question->number;
274 }
275 }
276
277 if ($showgrades) {
278 $columns[] = 'sumgrades';
279 $headers[] = get_string('grade', 'quiz').'/'.$quiz->grade;
280 }
281
282 if ($hasfeedback) {
283 $columns[] = 'feedbacktext';
284 $headers[] = get_string('feedback', 'quiz');
c35f3afc 285 }
abe67b24 286
287 $table->define_columns($columns);
288 $table->define_headers($headers);
289 $table->sortable(true, 'uniqueid');
290
291 // Set up the table
292 $table->define_baseurl($reporturl->out(false, $displayoptions));
293
294 $table->collapsible(true);
295
296 $table->column_suppress('picture');
297 $table->column_suppress('fullname');
298 $table->column_suppress('idnumber');
299
300 $table->no_sorting('feedbacktext');
301
302 $table->column_class('picture', 'picture');
303 $table->column_class('lastname', 'bold');
304 $table->column_class('firstname', 'bold');
305 $table->column_class('fullname', 'bold');
306 $table->column_class('sumgrades', 'bold');
307
308 $table->set_attribute('id', 'attempts');
309
310 $table->out($pagesize, true);
7bbe08a2 311 }
c35f3afc 312 if (!$table->is_downloading()) {
8b2f8253 313 //should be quicker than a COUNT to test if there is at least one record :
314 if ($DB->get_records('quiz_grades', array('quiz'=> $quiz->id), '', '*', 0, 1)){
c35f3afc 315 $imageurl = $CFG->wwwroot.'/mod/quiz/report/overview/overviewgraph.php?id='.$quiz->id;
316 print_heading(get_string('overviewreportgraph', 'quiz_overview'));
317 echo '<div class="mdl-align"><img src="'.$imageurl.'" alt="'.get_string('overviewreportgraph', 'quiz_overview').'" /></div>';
aad5b0fc 318 }
78517b5a 319 }
7bbe08a2 320 return true;
321 }
c35f3afc 322
7bbe08a2 323}
324
c35f3afc 325
04419703 326?>