MDL-21250 capital letters removal
[moodle.git] / blocks / quiz_results / block_quiz_results.php
bloba6bb6027ceb269048711e0bcef9b9fed755822cb
1 <?php
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);
10 class block_quiz_results extends block_base {
11 function init() {
12 $this->title = get_string('pluginname', 'block_quiz_results');
15 function applicable_formats() {
16 return array('course' => true, 'mod-quiz' => true);
19 /**
20 * If this block belongs to a quiz context, then return that quiz's id.
21 * Otherwise, return 0.
22 * @return integer the quiz id.
24 public function get_owning_quiz() {
25 if (empty($this->instance->parentcontextid)) {
26 return 0;
28 $parentcontext = get_context_instance_by_id($this->instance->parentcontextid);
29 if ($parentcontext->contextlevel != CONTEXT_MODULE) {
30 return 0;
32 $cm = get_coursemodule_from_id('quiz', $parentcontext->instanceid);
33 if (!$cm) {
34 return 0;
36 return $cm->instance;
39 function instance_config_save($data) {
40 if (empty($data->quizid)) {
41 $data->quizid = $this->get_owning_quiz();
43 parent::instance_config_save($data);
46 function get_content() {
47 global $USER, $CFG, $DB;
49 if ($this->content !== NULL) {
50 return $this->content;
53 $this->content = new stdClass;
54 $this->content->text = '';
55 $this->content->footer = '';
57 if (empty($this->instance)) {
58 return $this->content;
61 if ($this->page->activityname == 'quiz' && $this->page->context->id == $this->instance->parentcontextid) {
62 $quiz = $this->page->activityrecord;
63 $quizid = $quiz->id;
64 $courseid = $this->page->course->id;
65 $inquiz = true;
66 } else if (!empty($this->config->quizid)) {
67 $quizid = $this->config->quizid;
68 $quiz = $DB->get_record('quiz', array('id' => $quizid));
69 if (empty($quiz)) {
70 $this->content->text = get_string('error_emptyquizrecord', 'block_quiz_results');
71 return $this->content;
73 $courseid = $quiz->course;
74 $inquiz = false;
75 } else {
76 $quizid = 0;
79 if (empty($quizid)) {
80 $this->content->text = get_string('error_emptyquizid', 'block_quiz_results');
81 return $this->content;
84 if (empty($this->config->showbest) && empty($this->config->showworst)) {
85 $this->content->text = get_string('configuredtoshownothing', 'block_quiz_results');
86 return $this->content;
89 // Get the grades for this quiz
90 $grades = $DB->get_records('quiz_grades', array('quiz' => $quizid), 'grade, timemodified DESC');
92 if (empty($grades)) {
93 // No grades, sorry
94 // The block will hide itself in this case
95 return $this->content;
98 $groupmode = NOGROUPS;
99 $best = array();
100 $worst = array();
102 if (!empty($this->config->nameformat)) {
103 $nameformat = $this->config->nameformat;
104 } else {
105 $nameformat = B_QUIZRESULTS_NAME_FORMAT_FULL;
108 if (!empty($this->config->usegroups)) {
109 if ($inquiz) {
110 $cm = $this->page->cm;
111 $context = $this->page->context;
112 } else {
113 $cm = get_coursemodule_from_instance('quiz', $quizid, $courseid);
114 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
116 $groupmode = groups_get_activity_groupmode($cm);
118 if ($groupmode == SEPARATEGROUPS && has_capability('moodle/site:accessallgroups', $context)) {
119 // We 'll make an exception in this case
120 $groupmode = VISIBLEGROUPS;
124 switch ($groupmode) {
125 case VISIBLEGROUPS:
126 // Display group-mode results
127 $groups = groups_get_all_groups($courseid);
129 if(empty($groups)) {
130 // No groups exist, sorry
131 $this->content->text = get_string('error_nogroupsexist', 'block_quiz_results');
132 return $this->content;
135 // Find out all the userids which have a submitted grade
136 $userids = array();
137 $gradeforuser = array();
138 foreach ($grades as $grade) {
139 $userids[] = $grade->userid;
140 $gradeforuser[$grade->userid] = (float)$grade->grade;
143 // Now find which groups these users belong in
144 list($usertest, $params) = $DB->get_in_or_equal($userids);
145 $params[] = $courseid;
146 $usergroups = $DB->get_records_sql('
147 SELECT gm.id, gm.userid, gm.groupid, g.name
148 FROM {groups} g
149 LEFT JOIN {groups_members} gm ON g.id = gm.groupid
150 WHERE gm.userid ' . $usertest . ' AND g.courseid = ?', $params);
152 // Now, iterate the grades again and sum them up for each group
153 $groupgrades = array();
154 foreach ($usergroups as $usergroup) {
155 if (!isset($groupgrades[$usergroup->groupid])) {
156 $groupgrades[$usergroup->groupid] = array(
157 'sum' => (float)$gradeforuser[$usergroup->userid],
158 'number' => 1,
159 'group' => $usergroup->name);
160 } else {
161 $groupgrades[$usergroup->groupid]['sum'] += $gradeforuser[$usergroup->userid];
162 $groupgrades[$usergroup->groupid]['number'] += 1;
166 foreach($groupgrades as $groupid => $groupgrade) {
167 $groupgrades[$groupid]['average'] = $groupgrades[$groupid]['sum'] / $groupgrades[$groupid]['number'];
170 // Sort groupgrades according to average grade, ascending
171 uasort($groupgrades, create_function('$a, $b', 'if($a["average"] == $b["average"]) return 0; return ($a["average"] > $b["average"] ? 1 : -1);'));
173 // How many groups do we have with graded member submissions to show?
174 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($groupgrades));
175 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($groupgrades) - $numbest);
177 // Collect all the group results we are going to use in $best and $worst
178 $remaining = $numbest;
179 $groupgrade = end($groupgrades);
180 while ($remaining--) {
181 $best[key($groupgrades)] = $groupgrade['average'];
182 $groupgrade = prev($groupgrades);
185 $remaining = $numworst;
186 $groupgrade = reset($groupgrades);
187 while ($remaining--) {
188 $worst[key($groupgrades)] = $groupgrade['average'];
189 $groupgrade = next($groupgrades);
192 // Ready for output!
193 $gradeformat = intval(empty($this->config->gradeformat) ? B_QUIZRESULTS_GRADE_FORMAT_PCT : $this->config->gradeformat);
195 if (!$inquiz) {
196 // Don't show header and link to the quiz if we ARE at the quiz...
197 $this->content->text .= '<h1><a href="'.$CFG->wwwroot.'/mod/quiz/view.php?q='.$quizid.'">'.$quiz->name.'</a></h1>';
200 if ($nameformat = B_QUIZRESULTS_NAME_FORMAT_FULL) {
201 if (has_capability('moodle/course:managegroups', $context)) {
202 $grouplink = $CFG->wwwroot.'/group/overview.php?id='.$courseid.'&amp;group=';
203 } else if (has_capability('moodle/course:viewparticipants', $context)) {
204 $grouplink = $CFG->wwwroot.'/user/index.php?id='.$courseid.'&amp;group=';
205 } else {
206 $grouplink = '';
210 $rank = 0;
211 if(!empty($best)) {
212 $this->content->text .= '<table class="grades"><caption>';
213 $this->content->text .= ($numbest == 1?get_string('bestgroupgrade', 'block_quiz_results'):get_string('bestgroupgrades', 'block_quiz_results', $numbest));
214 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>';
215 foreach($best as $groupid => $averagegrade) {
216 switch($nameformat) {
217 case B_QUIZRESULTS_NAME_FORMAT_ANON:
218 case B_QUIZRESULTS_NAME_FORMAT_ID:
219 $thisname = get_string('group');
220 break;
221 default:
222 case B_QUIZRESULTS_NAME_FORMAT_FULL:
223 if ($grouplink) {
224 $thisname = '<a href="'.$grouplink.$groupid.'">'.$groupgrades[$groupid]['group'].'</a>';
225 } else {
226 $thisname = $groupgrades[$groupid]['group'];
228 break;
230 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>';
231 switch($gradeformat) {
232 case B_QUIZRESULTS_GRADE_FORMAT_FRA:
233 $this->content->text .= quiz_format_grade($quiz, $averagegrade).'/'.$quiz->grade;
234 break;
235 case B_QUIZRESULTS_GRADE_FORMAT_ABS:
236 $this->content->text .= quiz_format_grade($quiz, $averagegrade);
237 break;
238 default:
239 case B_QUIZRESULTS_GRADE_FORMAT_PCT:
240 $this->content->text .= round((float)$averagegrade / (float)$quiz->grade * 100).'%';
241 break;
243 $this->content->text .= '</td></tr>';
245 $this->content->text .= '</tbody></table>';
248 $rank = 0;
249 if(!empty($worst)) {
250 $worst = array_reverse($worst, true);
251 $this->content->text .= '<table class="grades"><caption>';
252 $this->content->text .= ($numworst == 1?get_string('worstgroupgrade', 'block_quiz_results'):get_string('worstgroupgrades', 'block_quiz_results', $numworst));
253 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>';
254 foreach($worst as $groupid => $averagegrade) {
255 switch($nameformat) {
256 case B_QUIZRESULTS_NAME_FORMAT_ANON:
257 case B_QUIZRESULTS_NAME_FORMAT_ID:
258 $thisname = get_string('group');
259 break;
260 default:
261 case B_QUIZRESULTS_NAME_FORMAT_FULL:
262 $thisname = '<a href="'.$CFG->wwwroot.'/course/group.php?group='.$groupid.'&amp;id='.$courseid.'">'.$groupgrades[$groupid]['group'].'</a>';
263 break;
265 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>';
266 switch($gradeformat) {
267 case B_QUIZRESULTS_GRADE_FORMAT_FRA:
268 $this->content->text .= quiz_format_grade($quiz, $averagegrade).'/'.$quiz->grade;
269 break;
270 case B_QUIZRESULTS_GRADE_FORMAT_ABS:
271 $this->content->text .= quiz_format_grade($quiz, $averagegrade);
272 break;
273 default:
274 case B_QUIZRESULTS_GRADE_FORMAT_PCT:
275 $this->content->text .= round((float)$averagegrade / (float)$quiz->grade * 100).'%';
276 break;
278 $this->content->text .= '</td></tr>';
280 $this->content->text .= '</tbody></table>';
282 break;
285 case SEPARATEGROUPS:
286 // This is going to be just like no-groups mode, only we 'll filter
287 // out the grades from people not in our group.
288 if (!isloggedin()) {
289 // Not logged in, so show nothing
290 return $this->content;
293 $mygroups = groups_get_all_groups($courseid, $USER->id);
294 if(empty($mygroups)) {
295 // Not member of a group, show nothing
296 return $this->content;
299 // Get users from the same groups as me.
300 list($grouptest, $params) = $DB->get_in_or_equal(array_keys($mygroups));
301 $mygroupsusers = $DB->get_records_sql_menu(
302 'SELECT DISTINCT userid, 1 FROM {groups_members} WHERE groupid ' . $grouptest,
303 $params);
305 // Filter out the grades belonging to other users, and proceed as if there were no groups
306 foreach ($grades as $key => $grade) {
307 if (!isset($mygroupsusers[$grade->userid])) {
308 unset($grades[$key]);
312 // No break, fall through to the default case now we have filtered the $grades array.
313 default:
314 case NOGROUPS:
315 // Single user mode
316 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($grades));
317 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($grades) - $numbest);
319 // Collect all the usernames we are going to need
320 $remaining = $numbest;
321 $grade = end($grades);
322 while($remaining--) {
323 $best[$grade->userid] = $grade->id;
324 $grade = prev($grades);
327 $remaining = $numworst;
328 $grade = reset($grades);
329 while($remaining--) {
330 $worst[$grade->userid] = $grade->id;
331 $grade = next($grades);
334 if(empty($best) && empty($worst)) {
335 // Nothing to show, for some reason...
336 return $this->content;
339 // Now grab all the users from the database
340 $userids = array_merge(array_keys($best), array_keys($worst));
341 $users = $DB->get_records_list('user', 'id', $userids, '', 'id, firstname, lastname, idnumber');
343 // Ready for output!
345 $gradeformat = intval(empty($this->config->gradeformat) ? B_QUIZRESULTS_GRADE_FORMAT_PCT : $this->config->gradeformat);
347 if(!$inquiz) {
348 // Don't show header and link to the quiz if we ARE at the quiz...
349 $this->content->text .= '<h1><a href="'.$CFG->wwwroot.'/mod/quiz/view.php?q='.$quizid.'">'.$quiz->name.'</a></h1>';
352 $rank = 0;
353 if(!empty($best)) {
354 $this->content->text .= '<table class="grades"><caption>';
355 $this->content->text .= ($numbest == 1?get_string('bestgrade', 'block_quiz_results'):get_string('bestgrades', 'block_quiz_results', $numbest));
356 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>';
357 foreach($best as $userid => $gradeid) {
358 switch($nameformat) {
359 case B_QUIZRESULTS_NAME_FORMAT_ID:
360 $thisname = get_string('user').' '.$users[$userid]->idnumber;
361 break;
362 case B_QUIZRESULTS_NAME_FORMAT_ANON:
363 $thisname = get_string('user');
364 break;
365 default:
366 case B_QUIZRESULTS_NAME_FORMAT_FULL:
367 $thisname = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'&amp;course='.$courseid.'">'.fullname($users[$userid]).'</a>';
368 break;
370 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>';
371 switch($gradeformat) {
372 case B_QUIZRESULTS_GRADE_FORMAT_FRA:
373 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade).'/'.$quiz->grade;
374 break;
375 case B_QUIZRESULTS_GRADE_FORMAT_ABS:
376 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade);
377 break;
378 default:
379 case B_QUIZRESULTS_GRADE_FORMAT_PCT:
380 if ($quiz->grade) {
381 $this->content->text .= round((float)$grades[$gradeid]->grade / (float)$quiz->grade * 100).'%';
382 } else {
383 $this->content->text .= '--%';
385 break;
387 $this->content->text .= '</td></tr>';
389 $this->content->text .= '</tbody></table>';
392 $rank = 0;
393 if(!empty($worst)) {
394 $worst = array_reverse($worst, true);
395 $this->content->text .= '<table class="grades"><caption>';
396 $this->content->text .= ($numworst == 1?get_string('worstgrade', 'block_quiz_results'):get_string('worstgrades', 'block_quiz_results', $numworst));
397 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>';
398 foreach($worst as $userid => $gradeid) {
399 switch($nameformat) {
400 case B_QUIZRESULTS_NAME_FORMAT_ID:
401 $thisname = get_string('user').' '.$users[$userid]->idnumber;
402 break;
403 case B_QUIZRESULTS_NAME_FORMAT_ANON:
404 $thisname = get_string('user');
405 break;
406 default:
407 case B_QUIZRESULTS_NAME_FORMAT_FULL:
408 $thisname = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'&amp;course='.$courseid.'">'.fullname($users[$userid]).'</a>';
409 break;
411 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>';
412 switch($gradeformat) {
413 case B_QUIZRESULTS_GRADE_FORMAT_FRA:
414 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade).'/'.$quiz->grade;
415 break;
416 case B_QUIZRESULTS_GRADE_FORMAT_ABS:
417 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade);
418 break;
419 default:
420 case B_QUIZRESULTS_GRADE_FORMAT_PCT:
421 $this->content->text .= round((float)$grades[$gradeid]->grade / (float)$quiz->grade * 100).'%';
422 break;
424 $this->content->text .= '</td></tr>';
426 $this->content->text .= '</tbody></table>';
428 break;
431 return $this->content;
434 function instance_allow_multiple() {
435 return true;