4ca6cfbf |
1 | <?php |
98ad7484 |
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 | |
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.'&group='; |
9d6c4e80 |
204 | } else if (has_capability('moodle/course:viewparticipants', $context)) { |
205 | $grouplink = $CFG->wwwroot.'/user/index.php?id='.$courseid.'&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.'&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.'&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.'&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 | |