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