blocks/quiz_results: MDL-21284 - dont strip leading zeros from idnumbers
[moodle.git] / blocks / quiz_results / block_quiz_results.php
CommitLineData
4ca6cfbf 1<?php
98ad7484 2
85311ca8 3define('B_QUIZRESULTS_NAME_FORMAT_FULL', 1);
4define('B_QUIZRESULTS_NAME_FORMAT_ID', 2);
5define('B_QUIZRESULTS_NAME_FORMAT_ANON', 3);
6define('B_QUIZRESULTS_GRADE_FORMAT_PCT', 1);
7define('B_QUIZRESULTS_GRADE_FORMAT_FRA', 2);
8define('B_QUIZRESULTS_GRADE_FORMAT_ABS', 3);
98ad7484 9
10class block_quiz_results extends block_base {
11 function init() {
12 $this->title = get_string('formaltitle', 'block_quiz_results');
433c242f 13 $this->version = 2007101509;
98ad7484 14 }
15
63927672 16 function applicable_formats() {
76d37688 17 return array('course' => true, 'mod-quiz' => true);
63927672 18 }
19
c6084d31 20 /**
21 * If this block belongs to a quiz context, then return that quiz's id.
22 * Otherwise, return 0.
23 * @return integer the quiz id.
24 */
25 public function get_owning_quiz() {
26 if (empty($this->instance->parentcontextid)) {
27 return 0;
28 }
29 $parentcontext = get_context_instance_by_id($this->instance->parentcontextid);
30 if ($parentcontext->contextlevel != CONTEXT_MODULE) {
31 return 0;
32 }
33 $cm = get_coursemodule_from_id('quiz', $parentcontext->instanceid);
34 if (!$cm) {
35 return 0;
36 }
37 return $cm->instance;
38 }
39
40 function instance_config_save($data) {
41 if (empty($data->quizid)) {
42 $data->quizid = $this->get_owning_quiz();
43 }
44 parent::instance_config_save($data);
45 }
46
98ad7484 47 function get_content() {
44e1b7d7 48 global $USER, $CFG, $DB;
98ad7484 49
50 if ($this->content !== NULL) {
51 return $this->content;
52 }
98ad7484 53
54 $this->content = new stdClass;
55 $this->content->text = '';
56 $this->content->footer = '';
57
164e3054 58 if (empty($this->instance)) {
59 return $this->content;
60 }
61
c6084d31 62 if ($this->page->activityname == 'quiz' && $this->page->context->id == $this->instance->parentcontextid) {
3179b000 63 $quiz = $this->page->activityrecord;
64 $quizid = $quiz->id;
65 $courseid = $this->page->course->id;
66 $inquiz = true;
67 } else if (!empty($this->config->quizid)) {
68 $quizid = $this->config->quizid;
69 $quiz = $DB->get_record('quiz', array('id' => $quizid));
70 if (empty($quiz)) {
71 $this->content->text = get_string('error_emptyquizrecord', 'block_quiz_results');
72 return $this->content;
0144a0a7 73 }
3179b000 74 $courseid = $quiz->course;
75 $inquiz = false;
76 } else {
77 $quizid = 0;
98ad7484 78 }
79
f28f2d90 80 if (empty($quizid)) {
6b4dc5a3 81 $this->content->text = get_string('error_emptyquizid', 'block_quiz_results');
98ad7484 82 return $this->content;
83 }
84
3179b000 85 if (empty($this->config->showbest) && empty($this->config->showworst)) {
86 $this->content->text = get_string('configuredtoshownothing', 'block_quiz_results');
98ad7484 87 return $this->content;
88 }
89
90 // Get the grades for this quiz
7192011c 91 $grades = $DB->get_records('quiz_grades', array('quiz' => $quizid), 'grade, timemodified DESC');
98ad7484 92
f28f2d90 93 if (empty($grades)) {
98ad7484 94 // No grades, sorry
6b4dc5a3 95 // The block will hide itself in this case
00a4237f 96 return $this->content;
98ad7484 97 }
98
6b4dc5a3 99 $groupmode = NOGROUPS;
100 $best = array();
101 $worst = array();
98ad7484 102
3179b000 103 if (!empty($this->config->nameformat)) {
104 $nameformat = $this->config->nameformat;
105 } else {
106 $nameformat = B_QUIZRESULTS_NAME_FORMAT_FULL;
107 }
85311ca8 108
3179b000 109 if (!empty($this->config->usegroups)) {
110 if ($inquiz) {
111 $cm = $this->page->cm;
e92c286c 112 $context = $this->page->context;
3179b000 113 } else {
114 $cm = get_coursemodule_from_instance('quiz', $quizid, $courseid);
e92c286c 115 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
3179b000 116 }
117 $groupmode = groups_get_activity_groupmode($cm);
6b4dc5a3 118
e92c286c 119 if ($groupmode == SEPARATEGROUPS && has_capability('moodle/site:accessallgroups', $context)) {
120 // We 'll make an exception in this case
121 $groupmode = VISIBLEGROUPS;
122 }
b35bc4d8 123 }
6b4dc5a3 124
3179b000 125 switch ($groupmode) {
b35bc4d8 126 case VISIBLEGROUPS:
127 // Display group-mode results
2c386f82 128 $groups = groups_get_all_groups($courseid);
6b4dc5a3 129
130 if(empty($groups)) {
131 // No groups exist, sorry
132 $this->content->text = get_string('error_nogroupsexist', 'block_quiz_results');
133 return $this->content;
134 }
135
136 // Find out all the userids which have a submitted grade
137 $userids = array();
7192011c 138 $gradeforuser = array();
3179b000 139 foreach ($grades as $grade) {
6b4dc5a3 140 $userids[] = $grade->userid;
7192011c 141 $gradeforuser[$grade->userid] = (float)$grade->grade;
6b4dc5a3 142 }
143
144 // Now find which groups these users belong in
7192011c 145 list($usertest, $params) = $DB->get_in_or_equal($userids);
146 $params[] = $courseid;
147 $usergroups = $DB->get_records_sql('
148 SELECT gm.id, gm.userid, gm.groupid, g.name
149 FROM {groups} g
150 LEFT JOIN {groups_members} gm ON g.id = gm.groupid
151 WHERE gm.userid ' . $usertest . ' AND g.courseid = ?', $params);
152
153 // Now, iterate the grades again and sum them up for each group
6b4dc5a3 154 $groupgrades = array();
7192011c 155 foreach ($usergroups as $usergroup) {
156 if (!isset($groupgrades[$usergroup->groupid])) {
157 $groupgrades[$usergroup->groupid] = array(
158 'sum' => (float)$gradeforuser[$usergroup->userid],
159 'number' => 1,
160 'group' => $usergroup->name);
161 } else {
162 $groupgrades[$usergroup->groupid]['sum'] += $gradeforuser[$usergroup->userid];
163 $groupgrades[$usergroup->groupid]['number'] += 1;
6b4dc5a3 164 }
165 }
166
3779fd55 167 foreach($groupgrades as $groupid => $groupgrade) {
168 $groupgrades[$groupid]['average'] = $groupgrades[$groupid]['sum'] / $groupgrades[$groupid]['number'];
169 }
170
171 // Sort groupgrades according to average grade, ascending
172 uasort($groupgrades, create_function('$a, $b', 'if($a["average"] == $b["average"]) return 0; return ($a["average"] > $b["average"] ? 1 : -1);'));
6b4dc5a3 173
174 // How many groups do we have with graded member submissions to show?
175 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($groupgrades));
176 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($groupgrades) - $numbest);
177
178 // Collect all the group results we are going to use in $best and $worst
179 $remaining = $numbest;
180 $groupgrade = end($groupgrades);
3179b000 181 while ($remaining--) {
3779fd55 182 $best[key($groupgrades)] = $groupgrade['average'];
6b4dc5a3 183 $groupgrade = prev($groupgrades);
184 }
185
186 $remaining = $numworst;
187 $groupgrade = reset($groupgrades);
3179b000 188 while ($remaining--) {
3779fd55 189 $worst[key($groupgrades)] = $groupgrade['average'];
6b4dc5a3 190 $groupgrade = next($groupgrades);
191 }
192
193 // Ready for output!
85311ca8 194 $gradeformat = intval(empty($this->config->gradeformat) ? B_QUIZRESULTS_GRADE_FORMAT_PCT : $this->config->gradeformat);
6b4dc5a3 195
3179b000 196 if (!$inquiz) {
f58a15de 197 // Don't show header and link to the quiz if we ARE at the quiz...
198 $this->content->text .= '<h1><a href="'.$CFG->wwwroot.'/mod/quiz/view.php?q='.$quizid.'">'.$quiz->name.'</a></h1>';
199 }
6b4dc5a3 200
9d6c4e80 201 if ($nameformat = B_QUIZRESULTS_NAME_FORMAT_FULL) {
202 if (has_capability('moodle/course:managegroups', $context)) {
3d05fc13 203 $grouplink = $CFG->wwwroot.'/group/overview.php?id='.$courseid.'&amp;group=';
9d6c4e80 204 } else if (has_capability('moodle/course:viewparticipants', $context)) {
205 $grouplink = $CFG->wwwroot.'/user/index.php?id='.$courseid.'&amp;group=';
206 } else {
207 $grouplink = '';
208 }
209 }
210
6b4dc5a3 211 $rank = 0;
212 if(!empty($best)) {
d9f7e051 213 $this->content->text .= '<table class="grades"><caption>';
214 $this->content->text .= ($numbest == 1?get_string('bestgroupgrade', 'block_quiz_results'):get_string('bestgroupgrades', 'block_quiz_results', $numbest));
215 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>';
6b4dc5a3 216 foreach($best as $groupid => $averagegrade) {
85311ca8 217 switch($nameformat) {
218 case B_QUIZRESULTS_NAME_FORMAT_ANON:
219 case B_QUIZRESULTS_NAME_FORMAT_ID:
220 $thisname = get_string('group');
221 break;
222 default:
223 case B_QUIZRESULTS_NAME_FORMAT_FULL:
9d6c4e80 224 if ($grouplink) {
225 $thisname = '<a href="'.$grouplink.$groupid.'">'.$groupgrades[$groupid]['group'].'</a>';
226 } else {
227 $thisname = $groupgrades[$groupid]['group'];
228 }
85311ca8 229 break;
230 }
231 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>';
6b4dc5a3 232 switch($gradeformat) {
85311ca8 233 case B_QUIZRESULTS_GRADE_FORMAT_FRA:
f88fb62c 234 $this->content->text .= quiz_format_grade($quiz, $averagegrade).'/'.$quiz->grade;
6b4dc5a3 235 break;
85311ca8 236 case B_QUIZRESULTS_GRADE_FORMAT_ABS:
f88fb62c 237 $this->content->text .= quiz_format_grade($quiz, $averagegrade);
6b4dc5a3 238 break;
239 default:
85311ca8 240 case B_QUIZRESULTS_GRADE_FORMAT_PCT:
090cf95a 241 $this->content->text .= round((float)$averagegrade / (float)$quiz->grade * 100).'%';
6b4dc5a3 242 break;
243 }
244 $this->content->text .= '</td></tr>';
245 }
246 $this->content->text .= '</tbody></table>';
247 }
248
249 $rank = 0;
250 if(!empty($worst)) {
251 $worst = array_reverse($worst, true);
d9f7e051 252 $this->content->text .= '<table class="grades"><caption>';
253 $this->content->text .= ($numworst == 1?get_string('worstgroupgrade', 'block_quiz_results'):get_string('worstgroupgrades', 'block_quiz_results', $numworst));
254 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>';
6b4dc5a3 255 foreach($worst as $groupid => $averagegrade) {
85311ca8 256 switch($nameformat) {
257 case B_QUIZRESULTS_NAME_FORMAT_ANON:
258 case B_QUIZRESULTS_NAME_FORMAT_ID:
259 $thisname = get_string('group');
260 break;
261 default:
262 case B_QUIZRESULTS_NAME_FORMAT_FULL:
263 $thisname = '<a href="'.$CFG->wwwroot.'/course/group.php?group='.$groupid.'&amp;id='.$courseid.'">'.$groupgrades[$groupid]['group'].'</a>';
264 break;
265 }
266 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>';
6b4dc5a3 267 switch($gradeformat) {
85311ca8 268 case B_QUIZRESULTS_GRADE_FORMAT_FRA:
f88fb62c 269 $this->content->text .= quiz_format_grade($quiz, $averagegrade).'/'.$quiz->grade;
6b4dc5a3 270 break;
85311ca8 271 case B_QUIZRESULTS_GRADE_FORMAT_ABS:
f88fb62c 272 $this->content->text .= quiz_format_grade($quiz, $averagegrade);
6b4dc5a3 273 break;
274 default:
85311ca8 275 case B_QUIZRESULTS_GRADE_FORMAT_PCT:
090cf95a 276 $this->content->text .= round((float)$averagegrade / (float)$quiz->grade * 100).'%';
6b4dc5a3 277 break;
278 }
279 $this->content->text .= '</td></tr>';
280 }
281 $this->content->text .= '</tbody></table>';
282 }
b35bc4d8 283 break;
6b4dc5a3 284
285
b35bc4d8 286 case SEPARATEGROUPS:
287 // This is going to be just like no-groups mode, only we 'll filter
288 // out the grades from people not in our group.
289 if(empty($USER) || empty($USER->id)) {
290 // Not logged in, so show nothing
291 return $this->content;
292 }
293
2c386f82 294 $mygroups = groups_get_all_groups($courseid, $USER->id);
b35bc4d8 295 if(empty($mygroups)) {
296 // Not member of a group, show nothing
297 return $this->content;
298 }
299
7192011c 300 // Get users from the same groups as me.
301 list($grouptest, $params) = $DB->get_in_or_equal(array_keys($mygroups));
302 $mygroupsusers = $DB->get_records_sql_menu(
303 'SELECT DISTINCT userid, 1 FROM {groups_members} WHERE groupid ' . $grouptest,
304 $params);
b35bc4d8 305
7192011c 306 // Filter out the grades belonging to other users, and proceed as if there were no groups
307 foreach ($grades as $key => $grade) {
308 if (!isset($mygroupsusers[$grade->userid])) {
309 unset($grades[$key]);
310 }
311 }
b35bc4d8 312
7192011c 313 // No break, fall through to the default case now we have filtered the $grades array.
b35bc4d8 314 default:
315 case NOGROUPS:
98ad7484 316 // Single user mode
6b4dc5a3 317 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($grades));
318 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($grades) - $numbest);
98ad7484 319
320 // Collect all the usernames we are going to need
321 $remaining = $numbest;
322 $grade = end($grades);
323 while($remaining--) {
324 $best[$grade->userid] = $grade->id;
325 $grade = prev($grades);
326 }
327
328 $remaining = $numworst;
329 $grade = reset($grades);
330 while($remaining--) {
331 $worst[$grade->userid] = $grade->id;
332 $grade = next($grades);
333 }
334
335 if(empty($best) && empty($worst)) {
336 // Nothing to show, for some reason...
337 return $this->content;
338 }
339
340 // Now grab all the users from the database
341 $userids = array_merge(array_keys($best), array_keys($worst));
44e1b7d7 342 $users = $DB->get_records_list('user', 'id', $userids, '', 'id, firstname, lastname, idnumber');
98ad7484 343
344 // Ready for output!
345
85311ca8 346 $gradeformat = intval(empty($this->config->gradeformat) ? B_QUIZRESULTS_GRADE_FORMAT_PCT : $this->config->gradeformat);
98ad7484 347
3179b000 348 if(!$inquiz) {
f58a15de 349 // Don't show header and link to the quiz if we ARE at the quiz...
350 $this->content->text .= '<h1><a href="'.$CFG->wwwroot.'/mod/quiz/view.php?q='.$quizid.'">'.$quiz->name.'</a></h1>';
351 }
98ad7484 352
353 $rank = 0;
354 if(!empty($best)) {
d9f7e051 355 $this->content->text .= '<table class="grades"><caption>';
356 $this->content->text .= ($numbest == 1?get_string('bestgrade', 'block_quiz_results'):get_string('bestgrades', 'block_quiz_results', $numbest));
357 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>';
98ad7484 358 foreach($best as $userid => $gradeid) {
85311ca8 359 switch($nameformat) {
360 case B_QUIZRESULTS_NAME_FORMAT_ID:
41cfe004 361 $thisname = get_string('user').' '.$users[$userid]->idnumber;
85311ca8 362 break;
363 case B_QUIZRESULTS_NAME_FORMAT_ANON:
9101efd3 364 $thisname = get_string('user');
85311ca8 365 break;
366 default:
367 case B_QUIZRESULTS_NAME_FORMAT_FULL:
368 $thisname = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'&amp;course='.$courseid.'">'.fullname($users[$userid]).'</a>';
369 break;
370 }
371 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>';
98ad7484 372 switch($gradeformat) {
85311ca8 373 case B_QUIZRESULTS_GRADE_FORMAT_FRA:
f88fb62c 374 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade).'/'.$quiz->grade;
98ad7484 375 break;
85311ca8 376 case B_QUIZRESULTS_GRADE_FORMAT_ABS:
f88fb62c 377 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade);
98ad7484 378 break;
379 default:
85311ca8 380 case B_QUIZRESULTS_GRADE_FORMAT_PCT:
f64fdf3f 381 if ($quiz->grade) {
382 $this->content->text .= round((float)$grades[$gradeid]->grade / (float)$quiz->grade * 100).'%';
383 } else {
384 $this->content->text .= '--%';
385 }
98ad7484 386 break;
387 }
388 $this->content->text .= '</td></tr>';
389 }
390 $this->content->text .= '</tbody></table>';
391 }
392
393 $rank = 0;
394 if(!empty($worst)) {
395 $worst = array_reverse($worst, true);
d9f7e051 396 $this->content->text .= '<table class="grades"><caption>';
397 $this->content->text .= ($numworst == 1?get_string('worstgrade', 'block_quiz_results'):get_string('worstgrades', 'block_quiz_results', $numworst));
398 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>';
98ad7484 399 foreach($worst as $userid => $gradeid) {
85311ca8 400 switch($nameformat) {
401 case B_QUIZRESULTS_NAME_FORMAT_ID:
41cfe004 402 $thisname = get_string('user').' '.$users[$userid]->idnumber;
85311ca8 403 break;
404 case B_QUIZRESULTS_NAME_FORMAT_ANON:
9101efd3 405 $thisname = get_string('user');
85311ca8 406 break;
407 default:
408 case B_QUIZRESULTS_NAME_FORMAT_FULL:
409 $thisname = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'&amp;course='.$courseid.'">'.fullname($users[$userid]).'</a>';
410 break;
411 }
412 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>';
98ad7484 413 switch($gradeformat) {
85311ca8 414 case B_QUIZRESULTS_GRADE_FORMAT_FRA:
f88fb62c 415 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade).'/'.$quiz->grade;
98ad7484 416 break;
85311ca8 417 case B_QUIZRESULTS_GRADE_FORMAT_ABS:
f88fb62c 418 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade);
98ad7484 419 break;
420 default:
85311ca8 421 case B_QUIZRESULTS_GRADE_FORMAT_PCT:
090cf95a 422 $this->content->text .= round((float)$grades[$gradeid]->grade / (float)$quiz->grade * 100).'%';
98ad7484 423 break;
424 }
425 $this->content->text .= '</td></tr>';
426 }
427 $this->content->text .= '</tbody></table>';
428 }
b35bc4d8 429 break;
98ad7484 430 }
431
98ad7484 432 return $this->content;
433 }
434
63927672 435 function instance_allow_multiple() {
98ad7484 436 return true;
437 }
438}
439
4ca6cfbf 440