98ad7484 |
1 | <?php //$Id$ |
2 | |
85311ca8 |
3 | define('B_QUIZRESULTS_NAME_FORMAT_FULL', 1); |
4 | define('B_QUIZRESULTS_NAME_FORMAT_ID', 2); |
5 | define('B_QUIZRESULTS_NAME_FORMAT_ANON', 3); |
6 | define('B_QUIZRESULTS_GRADE_FORMAT_PCT', 1); |
7 | define('B_QUIZRESULTS_GRADE_FORMAT_FRA', 2); |
8 | define('B_QUIZRESULTS_GRADE_FORMAT_ABS', 3); |
98ad7484 |
9 | |
10 | class 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.'&group='; |
9d6c4e80 |
178 | } else if (has_capability('moodle/course:viewparticipants', $context)) { |
179 | $grouplink = $CFG->wwwroot.'/user/index.php?id='.$courseid.'&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.'&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.'&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.'&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 | ?> |