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