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 | |
11 | require_once($CFG->libdir.'/tablelib.php'); |
7bbe08a2 |
12 | |
13 | class quiz_report extends quiz_default_report { |
14 | |
2c3968c4 |
15 | /** |
16 | * Display the report. |
17 | */ |
18 | function display($quiz, $cm, $course) { |
1f21cc88 |
19 | global $CFG, $db; |
7bbe08a2 |
20 | |
2c3968c4 |
21 | // Define some strings |
7bbe08a2 |
22 | $strreallydel = addslashes(get_string('deleteattemptcheck','quiz')); |
7bbe08a2 |
23 | $strtimeformat = get_string('strftimedatetime'); |
24 | $strreviewquestion = get_string('reviewresponse', 'quiz'); |
25 | |
07a7d859 |
26 | $context = get_context_instance(CONTEXT_MODULE, $cm->id); |
27 | |
2c3968c4 |
28 | // Only print headers if not asked to download data |
970d0fe0 |
29 | if (!$download = optional_param('download', NULL)) { |
30 | $this->print_header_and_tabs($cm, $course, $quiz, $reportmode="overview"); |
31 | } |
7bbe08a2 |
32 | |
2c3968c4 |
33 | // Deal with actions |
34 | $action = optional_param('action', '', PARAM_ACTION); |
dbc72c99 |
35 | |
7bbe08a2 |
36 | switch($action) { |
2c3968c4 |
37 | case 'delete': // Some attempts need to be deleted |
07a7d859 |
38 | require_capability('mod/quiz:deleteattempts', $context); |
2c3968c4 |
39 | $attemptids = optional_param('attemptid', array(), PARAM_INT); |
dbc72c99 |
40 | |
7bbe08a2 |
41 | foreach($attemptids as $attemptid) { |
01600b51 |
42 | add_to_log($course->id, 'quiz', 'delete attempt', 'report.php?id=' . $cm->id, |
43 | $attemptid, $cm->id); |
ff51d646 |
44 | quiz_delete_attempt($attemptid, $quiz); |
7bbe08a2 |
45 | } |
46 | break; |
47 | } |
18dfa593 |
48 | |
de266537 |
49 | // Set of format options for teacher-created content, for example overall feedback. |
50 | $nocleanformatoptions = new stdClass; |
51 | $nocleanformatoptions->noclean = true; |
52 | |
129b80c5 |
53 | // Prepare list of available actions to perform on attempts - we only want to show the checkbox. |
54 | // Column on the table if there are options. |
55 | $attemptactions = array(); |
56 | if (has_capability('mod/quiz:deleteattempts', $context)) { |
57 | $attemptactions['delete'] = get_string('delete'); |
58 | } |
59 | |
01600b51 |
60 | // Work out some display options - whether there is feedback, and whether scores should be shown. |
61 | $hasfeedback = quiz_has_feedback($quiz->id) && $quiz->grade > 1.e-7 && $quiz->sumgrades > 1.e-7; |
62 | $fakeattempt = new stdClass(); |
63 | $fakeattempt->preview = false; |
64 | $fakeattempt->timefinish = $quiz->timeopen; |
65 | $reviewoptions = quiz_get_reviewoptions($quiz, $fakeattempt, $context); |
66 | $showgrades = $quiz->grade && $quiz->sumgrades && $reviewoptions->scores; |
67 | |
be161556 |
68 | // Set table options |
69 | $noattempts = optional_param('noattempts', 0, PARAM_INT); |
70 | $detailedmarks = optional_param('detailedmarks', 0, PARAM_INT); |
f33c438e |
71 | $pagesize = optional_param('pagesize', 0, PARAM_INT); |
be161556 |
72 | $reporturl = $CFG->wwwroot.'/mod/quiz/report.php?mode=overview'; |
01600b51 |
73 | if ($pagesize < 1) { |
f33c438e |
74 | $pagesize = QUIZ_REPORT_DEFAULT_PAGE_SIZE; |
01600b51 |
75 | } |
76 | if (!$reviewoptions->scores) { |
77 | $detailedmarks = 0; |
78 | } |
be161556 |
79 | $reporturlwithoptions = $reporturl . '&id=' . $cm->id . '&noattempts=' . $noattempts . |
80 | '&detailedmarks=' . $detailedmarks . '&pagesize=' . $pagesize; |
01600b51 |
81 | |
19faed1a |
82 | /// find out current groups mode |
5ada3c8e |
83 | $currentgroup = groups_get_activity_group($cm, true); |
01600b51 |
84 | |
5ada3c8e |
85 | if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used |
970d0fe0 |
86 | if (!$download) { |
5ada3c8e |
87 | groups_print_activity_menu($cm, $reporturlwithoptions); |
970d0fe0 |
88 | } |
2d7617c6 |
89 | } |
dbc72c99 |
90 | |
2a13e454 |
91 | // Print information on the number of existing attempts |
92 | if (!$download) { //do not print notices when downloading |
93 | if ($strattemptnum = quiz_num_attempt_summary($quiz, $cm, false, $currentgroup)) { |
94 | echo '<div class="quizattemptcounts">' . $strattemptnum . '</div>'; |
95 | } |
96 | } |
97 | |
2c3968c4 |
98 | // Now check if asked download of data |
970d0fe0 |
99 | if ($download) { |
100 | $filename = clean_filename("$course->shortname ".format_string($quiz->name,true)); |
101 | $sort = ''; |
970d0fe0 |
102 | } |
dbc72c99 |
103 | |
2c3968c4 |
104 | // Define table columns |
129b80c5 |
105 | $tablecolumns = array('picture', 'fullname', 'timestart', 'timefinish', 'duration'); |
106 | $tableheaders = array('', get_string('name'), get_string('startedon', 'quiz'), |
01600b51 |
107 | get_string('timecompleted','quiz'), get_string('attemptduration', 'quiz')); |
dbc72c99 |
108 | |
129b80c5 |
109 | if (!empty($attemptactions)) { |
110 | array_unshift($tablecolumns, 'checkbox'); |
111 | array_unshift($tableheaders, NULL); |
112 | } |
113 | |
01600b51 |
114 | if ($showgrades) { |
7bbe08a2 |
115 | $tablecolumns[] = 'sumgrades'; |
116 | $tableheaders[] = get_string('grade', 'quiz').'/'.$quiz->grade; |
117 | } |
dbc72c99 |
118 | |
129b80c5 |
119 | if ($detailedmarks) { |
7bbe08a2 |
120 | // we want to display marks for all questions |
121 | // Start by getting all questions |
122 | $questionlist = quiz_questions_in_quiz($quiz->questions); |
123 | $questionids = explode(',', $questionlist); |
124 | $sql = "SELECT q.*, i.grade AS maxgrade, i.id AS instance". |
2c3968c4 |
125 | " FROM {$CFG->prefix}question q,". |
126 | " {$CFG->prefix}quiz_question_instances i". |
127 | " WHERE i.quiz = '$quiz->id' AND q.id = i.question". |
128 | " AND q.id IN ($questionlist)"; |
7bbe08a2 |
129 | if (!$questions = get_records_sql($sql)) { |
5a2a5331 |
130 | print_error('No questions found'); |
7bbe08a2 |
131 | } |
132 | $number = 1; |
129b80c5 |
133 | foreach ($questionids as $key => $id) { |
7bbe08a2 |
134 | if ($questions[$id]->length) { |
135 | // Only print questions of non-zero length |
136 | $tablecolumns[] = '$'.$id; |
137 | $tableheaders[] = '#'.$number; |
138 | $questions[$id]->number = $number; |
139 | $number += $questions[$id]->length; |
140 | } else { |
141 | // get rid of zero length questions |
142 | unset($questions[$id]); |
143 | unset($questionids[$key]); |
144 | } |
145 | } |
146 | } |
dbc72c99 |
147 | |
212b7b8c |
148 | if ($hasfeedback) { |
2ac5177a |
149 | $tablecolumns[] = 'feedbacktext'; |
212b7b8c |
150 | $tableheaders[] = get_string('feedback', 'quiz'); |
151 | } |
18dfa593 |
152 | |
970d0fe0 |
153 | if (!$download) { |
154 | // Set up the table |
dbc72c99 |
155 | |
970d0fe0 |
156 | $table = new flexible_table('mod-quiz-report-overview-report'); |
dbc72c99 |
157 | |
970d0fe0 |
158 | $table->define_columns($tablecolumns); |
159 | $table->define_headers($tableheaders); |
be161556 |
160 | $table->define_baseurl($reporturlwithoptions); |
dbc72c99 |
161 | |
970d0fe0 |
162 | $table->sortable(true); |
163 | $table->collapsible(true); |
dbc72c99 |
164 | |
970d0fe0 |
165 | $table->column_suppress('picture'); |
166 | $table->column_suppress('fullname'); |
dbc72c99 |
167 | |
970d0fe0 |
168 | $table->column_class('picture', 'picture'); |
dbc72c99 |
169 | |
970d0fe0 |
170 | $table->set_attribute('cellspacing', '0'); |
171 | $table->set_attribute('id', 'attempts'); |
172 | $table->set_attribute('class', 'generaltable generalbox'); |
dbc72c99 |
173 | |
970d0fe0 |
174 | // Start working -- this is necessary as soon as the niceties are over |
175 | $table->setup(); |
77c7f0f5 |
176 | } else if ($download =='ODS') { |
177 | require_once("$CFG->libdir/odslib.class.php"); |
178 | |
179 | $filename .= ".ods"; |
180 | // Creating a workbook |
181 | $workbook = new MoodleODSWorkbook("-"); |
182 | // Sending HTTP headers |
183 | $workbook->send($filename); |
184 | // Creating the first worksheet |
185 | $sheettitle = get_string('reportoverview','quiz'); |
186 | $myxls =& $workbook->add_worksheet($sheettitle); |
187 | // format types |
188 | $format =& $workbook->add_format(); |
189 | $format->set_bold(0); |
190 | $formatbc =& $workbook->add_format(); |
191 | $formatbc->set_bold(1); |
192 | $formatbc->set_align('center'); |
193 | $formatb =& $workbook->add_format(); |
194 | $formatb->set_bold(1); |
195 | $formaty =& $workbook->add_format(); |
196 | $formaty->set_bg_color('yellow'); |
197 | $formatc =& $workbook->add_format(); |
198 | $formatc->set_align('center'); |
199 | $formatr =& $workbook->add_format(); |
200 | $formatr->set_bold(1); |
201 | $formatr->set_color('red'); |
202 | $formatr->set_align('center'); |
203 | $formatg =& $workbook->add_format(); |
204 | $formatg->set_bold(1); |
205 | $formatg->set_color('green'); |
206 | $formatg->set_align('center'); |
207 | // Here starts workshhet headers |
208 | |
01600b51 |
209 | $headers = array(get_string('name'), get_string('startedon', 'quiz'), |
210 | get_string('timecompleted', 'quiz'), get_string('attemptduration', 'quiz')); |
77c7f0f5 |
211 | |
01600b51 |
212 | if ($showgrades) { |
77c7f0f5 |
213 | $headers[] = get_string('grade', 'quiz').'/'.$quiz->grade; |
214 | } |
215 | if($detailedmarks) { |
216 | foreach ($questionids as $id) { |
217 | $headers[] = '#'.$questions[$id]->number; |
218 | } |
219 | } |
220 | if ($hasfeedback) { |
221 | $headers[] = get_string('feedback', 'quiz'); |
222 | } |
223 | $colnum = 0; |
224 | foreach ($headers as $item) { |
225 | $myxls->write(0,$colnum,$item,$formatbc); |
226 | $colnum++; |
227 | } |
228 | $rownum=1; |
2c3968c4 |
229 | } else if ($download =='Excel') { |
8867a3bb |
230 | require_once("$CFG->libdir/excellib.class.php"); |
dbc72c99 |
231 | |
970d0fe0 |
232 | $filename .= ".xls"; |
2c3968c4 |
233 | // Creating a workbook |
8867a3bb |
234 | $workbook = new MoodleExcelWorkbook("-"); |
2c3968c4 |
235 | // Sending HTTP headers |
8867a3bb |
236 | $workbook->send($filename); |
2c3968c4 |
237 | // Creating the first worksheet |
6d456aa2 |
238 | $sheettitle = get_string('reportoverview','quiz'); |
970d0fe0 |
239 | $myxls =& $workbook->add_worksheet($sheettitle); |
2c3968c4 |
240 | // format types |
970d0fe0 |
241 | $format =& $workbook->add_format(); |
242 | $format->set_bold(0); |
243 | $formatbc =& $workbook->add_format(); |
244 | $formatbc->set_bold(1); |
245 | $formatbc->set_align('center'); |
246 | $formatb =& $workbook->add_format(); |
247 | $formatb->set_bold(1); |
248 | $formaty =& $workbook->add_format(); |
249 | $formaty->set_bg_color('yellow'); |
250 | $formatc =& $workbook->add_format(); |
251 | $formatc->set_align('center'); |
252 | $formatr =& $workbook->add_format(); |
253 | $formatr->set_bold(1); |
254 | $formatr->set_color('red'); |
255 | $formatr->set_align('center'); |
256 | $formatg =& $workbook->add_format(); |
257 | $formatg->set_bold(1); |
258 | $formatg->set_color('green'); |
259 | $formatg->set_align('center'); |
260 | // Here starts workshhet headers |
261 | |
01600b51 |
262 | $headers = array(get_string('name'), get_string('startedon', 'quiz'), |
263 | get_string('timecompleted', 'quiz'), get_string('attemptduration', 'quiz')); |
970d0fe0 |
264 | |
01600b51 |
265 | if ($showgrades) { |
970d0fe0 |
266 | $headers[] = get_string('grade', 'quiz').'/'.$quiz->grade; |
267 | } |
268 | if($detailedmarks) { |
404518eb |
269 | foreach ($questionids as $id) { |
fcf5aebf |
270 | $headers[] = '#'.$questions[$id]->number; |
970d0fe0 |
271 | } |
272 | } |
212b7b8c |
273 | if ($hasfeedback) { |
274 | $headers[] = get_string('feedback', 'quiz'); |
275 | } |
970d0fe0 |
276 | $colnum = 0; |
277 | foreach ($headers as $item) { |
278 | $myxls->write(0,$colnum,$item,$formatbc); |
279 | $colnum++; |
280 | } |
281 | $rownum=1; |
2c3968c4 |
282 | } else if ($download=='CSV') { |
970d0fe0 |
283 | $filename .= ".txt"; |
284 | |
dbc72c99 |
285 | header("Content-Type: application/download\n"); |
970d0fe0 |
286 | header("Content-Disposition: attachment; filename=\"$filename\""); |
287 | header("Expires: 0"); |
288 | header("Cache-Control: must-revalidate,post-check=0,pre-check=0"); |
289 | header("Pragma: public"); |
290 | |
01600b51 |
291 | $headers = get_string('name')."\t".get_string('startedon', 'quiz')."\t". |
292 | get_string('timecompleted', 'quiz')."\t".get_string('attemptduration', 'quiz'); |
970d0fe0 |
293 | |
01600b51 |
294 | if ($showgrades) { |
970d0fe0 |
295 | $headers .= "\t".get_string('grade', 'quiz')."/".$quiz->grade; |
296 | } |
297 | if($detailedmarks) { |
404518eb |
298 | foreach ($questionids as $id) { |
299 | $headers .= "\t#".$questions[$id]->number; |
970d0fe0 |
300 | } |
301 | } |
212b7b8c |
302 | if ($hasfeedback) { |
303 | $headers .= "\t" . get_string('feedback', 'quiz'); |
304 | } |
970d0fe0 |
305 | echo $headers." \n"; |
306 | } |
18dfa593 |
307 | |
2018fb15 |
308 | // Get users with quiz attempt capability 'students'. |
309 | // don't need to do this expensive call if we are listing all attempts though. |
310 | if ( $noattempts != 3 ) { |
311 | if (empty($currentgroup)) { |
312 | |
313 | // all users who can attempt quizzes |
314 | $allowed = join(',',array_keys(get_users_by_capability($context, 'mod/quiz:attempt','','','','','','',false))); |
315 | } else { |
316 | |
317 | // all users who can attempt quizzes and who are in the currently selected group |
318 | $allowed = join(',',array_keys(get_users_by_capability($context, 'mod/quiz:attempt','','','','',$currentgroup,'',false))); |
319 | } |
86a1f1d5 |
320 | } |
970d0fe0 |
321 | |
7bbe08a2 |
322 | // Construct the SQL |
27176468 |
323 | $select = 'SELECT '.sql_concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).' AS uniqueid, '. |
86a1f1d5 |
324 | 'qa.uniqueid AS attemptuniqueid, qa.id AS attempt, u.id AS userid, u.firstname, u.lastname, u.picture, '. |
e366107f |
325 | 'qa.sumgrades, qa.timefinish, qa.timestart, qa.timefinish - qa.timestart AS duration '; |
86a1f1d5 |
326 | |
327 | // This part is the same for all cases - join users and quiz_attempts tables |
328 | $from = 'FROM '.$CFG->prefix.'user u '; |
329 | $from .= 'LEFT JOIN '.$CFG->prefix.'quiz_attempts qa ON qa.userid = u.id AND qa.quiz = '.$quiz->id; |
330 | |
331 | if ( $noattempts == 3 ) { // Show all attempts, including students who are no longer in the course |
332 | |
333 | $where = ' WHERE qa.id IS NOT NULL'; |
334 | // Comment out the following line to include preview attempts in the 'show all attempts' filter |
335 | $where .= ' AND qa.preview = 0'; |
336 | } else { // All non-admin users with quiz attempt capabilites - e.g. students |
337 | |
338 | $where = ' WHERE u.id IN (' .$allowed. ') AND (qa.preview = 0 OR qa.preview IS NULL)'; |
339 | |
340 | if ( empty( $noattempts )) { // Show only students with attempts |
341 | $where .= ' AND qa.id IS NOT NULL'; |
342 | } else if ( $noattempts == 1 ) { // Show only students without attempts |
343 | $where .= ' AND qa.id IS NULL'; |
39a27614 |
344 | } |
7bbe08a2 |
345 | } |
86a1f1d5 |
346 | |
347 | $countsql = 'SELECT COUNT(DISTINCT('.sql_concat('u.id', '\'#\'', $db->IfNull('qa.attempt', '0')).')) '.$from.$where; |
348 | |
970d0fe0 |
349 | if (!$download) { |
350 | // Add extra limits due to initials bar |
351 | if($table->get_sql_where()) { |
39a27614 |
352 | $where .= ' AND '.$table->get_sql_where(); |
970d0fe0 |
353 | } |
dbc72c99 |
354 | |
970d0fe0 |
355 | // Count the records NOW, before funky question grade sorting messes up $from |
39a27614 |
356 | if (!empty($countsql)) { |
357 | $totalinitials = count_records_sql($countsql); |
358 | if ($table->get_sql_where()) { |
359 | $countsql .= ' AND '.$table->get_sql_where(); |
360 | } |
361 | $total = count_records_sql($countsql); |
18dfa593 |
362 | |
39a27614 |
363 | } |
dbc72c99 |
364 | |
970d0fe0 |
365 | // Add extra limits due to sorting by question grade |
366 | if($sort = $table->get_sql_sort()) { |
367 | $sortparts = explode(',', $sort); |
368 | $newsort = array(); |
369 | $questionsort = false; |
370 | foreach($sortparts as $sortpart) { |
371 | $sortpart = trim($sortpart); |
372 | if(substr($sortpart, 0, 1) == '$') { |
373 | if(!$questionsort) { |
374 | $qid = intval(substr($sortpart, 1)); |
375 | $select .= ', grade '; |
be41c836 |
376 | $from .= ' LEFT JOIN '.$CFG->prefix.'question_sessions qns ON qns.attemptid = qa.id '. |
4f48fb42 |
377 | 'LEFT JOIN '.$CFG->prefix.'question_states qs ON qs.id = qns.newgraded '; |
04419703 |
378 | $where .= ' AND (qns.questionid IS NULL OR qns.questionid = '.$qid.')'; |
970d0fe0 |
379 | $newsort[] = 'grade '.(strpos($sortpart, 'ASC')? 'ASC' : 'DESC'); |
380 | $questionsort = true; |
381 | } |
2c3968c4 |
382 | } else { |
970d0fe0 |
383 | $newsort[] = $sortpart; |
7bbe08a2 |
384 | } |
385 | } |
dbc72c99 |
386 | |
970d0fe0 |
387 | // Reconstruct the sort string |
388 | $sort = ' ORDER BY '.implode(', ', $newsort); |
389 | } |
dbc72c99 |
390 | |
2f5fe552 |
391 | // Fix some wired sorting |
392 | if (empty($sort)) { |
393 | $sort = ' ORDER BY uniqueid'; |
394 | } |
18dfa593 |
395 | |
970d0fe0 |
396 | $table->pagesize($pagesize, $total); |
7bbe08a2 |
397 | } |
970d0fe0 |
398 | |
212b7b8c |
399 | // If there is feedback, include it in the query. |
400 | if ($hasfeedback) { |
401 | $factor = $quiz->grade/$quiz->sumgrades; |
402 | $select .= ', qf.feedbacktext '; |
86a1f1d5 |
403 | $from .= " LEFT JOIN {$CFG->prefix}quiz_feedback qf ON " . |
212b7b8c |
404 | "qf.quizid = $quiz->id AND qf.mingrade <= qa.sumgrades * $factor AND qa.sumgrades * $factor < qf.maxgrade"; |
405 | } |
406 | |
2c3968c4 |
407 | // Fetch the attempts |
39a27614 |
408 | if (!empty($from)) { // if we're in the site course and displaying no attempts, it makes no sense to do the query. |
78675b3e |
409 | if (!$download) { |
410 | $attempts = get_records_sql($select.$from.$where.$sort, |
18dfa593 |
411 | $table->get_page_start(), $table->get_page_size()); |
78675b3e |
412 | } else { |
413 | $attempts = get_records_sql($select.$from.$where.$sort); |
414 | } |
39a27614 |
415 | } else { |
416 | $attempts = array(); |
417 | } |
dbc72c99 |
418 | |
2c3968c4 |
419 | // Build table rows |
39a27614 |
420 | if (!$download) { |
421 | $table->initialbars($totalinitials>20); |
422 | } |
129b80c5 |
423 | |
39a27614 |
424 | if(!empty($attempts) || !empty($noattempts)) { |
193b2839 |
425 | if ($attempts) { |
426 | foreach ($attempts as $attempt) { |
18dfa593 |
427 | |
193b2839 |
428 | $picture = print_user_picture($attempt->userid, $course->id, $attempt->picture, false, true); |
18dfa593 |
429 | |
2018fb15 |
430 | $userlink = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$attempt->userid. |
431 | '&course='.$course->id.'">'.fullname($attempt).'</a>'; |
01600b51 |
432 | |
433 | // Username columns. |
434 | $row = array(); |
970d0fe0 |
435 | if (!$download) { |
129b80c5 |
436 | if (!empty($attemptactions)) { |
437 | $row[] = '<input type="checkbox" name="attemptid[]" value="'.$attempt->attempt.'" />'; |
438 | } |
01600b51 |
439 | $row[] = $picture; |
440 | $row[] = $userlink; |
2c3968c4 |
441 | } else { |
01600b51 |
442 | $row[] = fullname($attempt); |
970d0fe0 |
443 | } |
18dfa593 |
444 | |
01600b51 |
445 | // Timing columns. |
446 | if ($attempt->attempt) { |
447 | $startdate = userdate($attempt->timestart, $strtimeformat); |
193b2839 |
448 | if (!$download) { |
01600b51 |
449 | $row[] = '<a href="review.php?q='.$quiz->id.'&attempt='.$attempt->attempt.'">'.$startdate.'</a>'; |
2c3968c4 |
450 | } else { |
01600b51 |
451 | $row[] = $startdate; |
7bbe08a2 |
452 | } |
01600b51 |
453 | if ($attempt->timefinish) { |
454 | $timefinish = userdate($attempt->timefinish, $strtimeformat); |
455 | $duration = format_time($attempt->duration); |
456 | if (!$download) { |
01600b51 |
457 | $row[] = '<a href="review.php?q='.$quiz->id.'&attempt='.$attempt->attempt.'">'.$timefinish.'</a>'; |
c711a7ae |
458 | } else { |
459 | $row[] = $timefinish; |
01600b51 |
460 | } |
461 | $row[] = $duration; |
462 | } else { |
463 | $row[] = '-'; |
464 | $row[] = get_string('unfinished', 'quiz'); |
465 | } |
466 | } else { |
467 | $row[] = '-'; |
468 | $row[] = '-'; |
469 | $row[] = '-'; |
470 | } |
471 | |
472 | // Grades columns. |
02e48901 |
473 | if ($showgrades) { |
474 | if ($attempt->timefinish) { |
b7b4f8bd |
475 | $grade = quiz_rescale_grade($attempt->sumgrades, $quiz); |
02e48901 |
476 | if (!$download) { |
477 | $row[] = '<a href="review.php?q='.$quiz->id.'&attempt='.$attempt->attempt.'">'.$grade.'</a>'; |
478 | } else { |
479 | $row[] = $grade; |
480 | } |
01600b51 |
481 | } else { |
02e48901 |
482 | $row[] = '-'; |
01600b51 |
483 | } |
7bbe08a2 |
484 | } |
02e48901 |
485 | |
193b2839 |
486 | if($detailedmarks) { |
487 | if(empty($attempt->attempt)) { |
488 | foreach($questionids as $questionid) { |
489 | $row[] = '-'; |
970d0fe0 |
490 | } |
2c3968c4 |
491 | } else { |
193b2839 |
492 | foreach($questionids as $questionid) { |
01600b51 |
493 | $gradedstateid = get_field('question_sessions', 'newgraded', 'attemptid', |
494 | $attempt->attemptuniqueid, 'questionid', $questionid); |
495 | if ($gradedstateid) { |
496 | $grade = round(get_field('question_states', 'grade', 'id', |
497 | $gradedstateid), $quiz->decimalpoints); |
193b2839 |
498 | } else { |
7befd018 |
499 | $grade = '--'; |
193b2839 |
500 | } |
501 | if (!$download) { |
01600b51 |
502 | $row[] = link_to_popup_window('/mod/quiz/reviewquestion.php?state='. |
503 | $gradedstateid.'&number='.$questions[$questionid]->number, |
504 | 'reviewquestion', $grade, 450, 650, $strreviewquestion, 'none', true); |
2c3968c4 |
505 | } else { |
fb72e817 |
506 | $row[] = $grade; |
193b2839 |
507 | } |
970d0fe0 |
508 | } |
7bbe08a2 |
509 | } |
510 | } |
01600b51 |
511 | |
512 | // Feedback column. |
212b7b8c |
513 | if ($hasfeedback) { |
514 | if ($attempt->timefinish) { |
de266537 |
515 | $row[] = format_text($attempt->feedbacktext, FORMAT_MOODLE, $nocleanformatoptions); |
212b7b8c |
516 | } else { |
517 | $row[] = '-'; |
518 | } |
519 | } |
193b2839 |
520 | if (!$download) { |
521 | $table->add_data($row); |
77c7f0f5 |
522 | } else if ($download == 'Excel' or $download == 'ODS') { |
193b2839 |
523 | $colnum = 0; |
524 | foreach($row as $item){ |
525 | $myxls->write($rownum,$colnum,$item,$format); |
526 | $colnum++; |
527 | } |
528 | $rownum++; |
2c3968c4 |
529 | } else if ($download=='CSV') { |
193b2839 |
530 | $text = implode("\t", $row); |
531 | echo $text." \n"; |
970d0fe0 |
532 | } |
970d0fe0 |
533 | } |
7bbe08a2 |
534 | } |
dbc72c99 |
535 | if (!$download) { |
2c3968c4 |
536 | // Start form |
970d0fe0 |
537 | echo '<div id="tablecontainer">'; |
01600b51 |
538 | echo '<form id="attemptsform" method="post" action="' . $reporturlwithoptions . |
539 | '" onsubmit="var menu = document.getElementById(\'menuaction\'); ' . |
540 | 'return (menu.options[menu.selectedIndex].value == \'delete\' ? confirm(\''. |
541 | $strreallydel.'\') : true);">'; |
375ec5a5 |
542 | echo '<div>'; |
dbc72c99 |
543 | |
2c3968c4 |
544 | // Print table |
970d0fe0 |
545 | $table->print_html(); |
546 | |
2c3968c4 |
547 | // Print "Select all" etc. |
129b80c5 |
548 | if (!empty($attempts) && !empty($attemptactions)) { |
39a27614 |
549 | echo '<table id="commands">'; |
550 | echo '<tr><td>'; |
01600b51 |
551 | echo '<a href="javascript:select_all_in(\'DIV\',null,\'tablecontainer\');">'. |
552 | get_string('selectall', 'quiz').'</a> / '; |
553 | echo '<a href="javascript:deselect_all_in(\'DIV\',null,\'tablecontainer\');">'. |
554 | get_string('selectnone', 'quiz').'</a> '; |
39a27614 |
555 | echo ' '; |
129b80c5 |
556 | choose_from_menu($attemptactions, 'action', '', get_string('withselected', 'quiz'), |
01600b51 |
557 | 'if(this.selectedIndex > 0) submitFormById(\'attemptsform\');'); |
09275894 |
558 | echo '<noscript id="noscriptmenuaction" style="display: inline;"><div>'; |
559 | echo '<input type="submit" value="'.get_string('go').'" /></div></noscript>'; |
01600b51 |
560 | echo '<script type="text/javascript"> |
561 | <!-- |
562 | document.getElementById("noscriptmenuaction").style.display = "none"; |
563 | --> |
564 | </script>'; |
39a27614 |
565 | echo '</td></tr></table>'; |
566 | } |
2c3968c4 |
567 | // Close form |
375ec5a5 |
568 | echo '</div>'; |
970d0fe0 |
569 | echo '</form></div>'; |
18dfa593 |
570 | |
39a27614 |
571 | if (!empty($attempts)) { |
09275894 |
572 | echo '<table class="boxaligncenter"><tr>'; |
77c7f0f5 |
573 | $options = array(); |
be161556 |
574 | $options["id"] = $cm->id; |
575 | $options["q"] = $quiz->id; |
39a27614 |
576 | $options['sesskey'] = sesskey(); |
577 | $options["noheader"] = "yes"; |
19faed1a |
578 | $options['noattempts'] = $noattempts; |
579 | $options['detailedmarks'] = $detailedmarks; |
39a27614 |
580 | echo '<td>'; |
77c7f0f5 |
581 | $options["download"] = "ODS"; |
be161556 |
582 | print_single_button($reporturl, $options, get_string("downloadods")); |
77c7f0f5 |
583 | echo "</td>\n"; |
584 | echo '<td>'; |
39a27614 |
585 | $options["download"] = "Excel"; |
be161556 |
586 | print_single_button($reporturl, $options, get_string("downloadexcel")); |
39a27614 |
587 | echo "</td>\n"; |
588 | echo '<td>'; |
589 | $options["download"] = "CSV"; |
be161556 |
590 | print_single_button($reporturl, $options, get_string("downloadtext")); |
39a27614 |
591 | echo "</td>\n"; |
592 | echo "<td>"; |
c358d620 |
593 | helpbutton('overviewdownload', get_string('overviewdownload', 'quiz_overview'), 'quiz'); |
39a27614 |
594 | echo "</td>\n"; |
595 | echo '</tr></table>'; |
596 | } |
77c7f0f5 |
597 | } else if ($download == 'Excel' or $download == 'ODS') { |
970d0fe0 |
598 | $workbook->close(); |
cebf9a83 |
599 | exit; |
2c3968c4 |
600 | } else if ($download == 'CSV') { |
970d0fe0 |
601 | exit; |
602 | } |
603 | |
2c3968c4 |
604 | } else { |
970d0fe0 |
605 | if (!$download) { |
606 | $table->print_html(); |
607 | } |
7bbe08a2 |
608 | } |
2c3968c4 |
609 | // Print display options |
78517b5a |
610 | echo '<div class="controls">'; |
be161556 |
611 | echo '<form id="options" action="' . $reporturl . '" method="get">'; |
862c219a |
612 | echo '<div>'; |
78517b5a |
613 | echo '<p>'.get_string('displayoptions', 'quiz').': </p>'; |
614 | echo '<input type="hidden" name="id" value="'.$cm->id.'" />'; |
615 | echo '<input type="hidden" name="q" value="'.$quiz->id.'" />'; |
78517b5a |
616 | echo '<input type="hidden" name="noattempts" value="0" />'; |
617 | echo '<input type="hidden" name="detailedmarks" value="0" />'; |
09275894 |
618 | echo '<table id="overview-options" class="boxaligncenter">'; |
78517b5a |
619 | echo '<tr align="left">'; |
620 | echo '<td><label for="pagesize">'.get_string('pagesize', 'quiz').'</label></td>'; |
807ae30a |
621 | echo '<td><input type="text" id="pagesize" name="pagesize" size="3" value="'.$pagesize.'" /></td>'; |
78517b5a |
622 | echo '</tr>'; |
623 | echo '<tr align="left">'; |
624 | echo '<td colspan="2">'; |
d6d29245 |
625 | $options = array(0 => get_string('attemptsonly','quiz_overview', $course->students)); |
78517b5a |
626 | if ($course->id != SITEID) { |
d6d29245 |
627 | $options[1] = get_string('noattemptsonly', 'quiz_overview', $course->students); |
628 | $options[2] = get_string('allstudents','quiz_overview', $course->students); |
629 | $options[3] = get_string('allattempts','quiz_overview'); |
78517b5a |
630 | } |
631 | choose_from_menu($options,'noattempts',$noattempts,''); |
632 | echo '</td></tr>'; |
633 | echo '<tr align="left">'; |
01600b51 |
634 | echo '<td colspan="2">'; |
635 | echo '<input type="checkbox" id="checkdetailedmarks" name="detailedmarks" '. |
636 | ($detailedmarks?'checked="checked" ':'').'value="1" /> '; |
637 | echo '<label for="checkdetailedmarks">'.get_string('showdetailedmarks', 'quiz').'</label> '; |
78517b5a |
638 | echo '</td></tr>'; |
639 | echo '<tr><td colspan="2" align="center">'; |
640 | echo '<input type="submit" value="'.get_string('go').'" />'; |
641 | echo '</td></tr></table>'; |
862c219a |
642 | echo '</div>'; |
78517b5a |
643 | echo '</form>'; |
644 | echo '</div>'; |
645 | echo "\n"; |
646 | |
7bbe08a2 |
647 | return true; |
648 | } |
649 | } |
650 | |
04419703 |
651 | ?> |