|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00027 defined('MOODLE_INTERNAL') || die(); 00028 00029 require_once($CFG->dirroot . '/mod/quiz/lib.php'); 00030 00031 00043 define('B_QUIZRESULTS_NAME_FORMAT_FULL', 1); 00044 define('B_QUIZRESULTS_NAME_FORMAT_ID', 2); 00045 define('B_QUIZRESULTS_NAME_FORMAT_ANON', 3); 00046 define('B_QUIZRESULTS_GRADE_FORMAT_PCT', 1); 00047 define('B_QUIZRESULTS_GRADE_FORMAT_FRA', 2); 00048 define('B_QUIZRESULTS_GRADE_FORMAT_ABS', 3); 00049 00050 class block_quiz_results extends block_base { 00051 function init() { 00052 $this->title = get_string('pluginname', 'block_quiz_results'); 00053 } 00054 00055 function applicable_formats() { 00056 return array('course' => true, 'mod-quiz' => true); 00057 } 00058 00064 public function get_owning_quiz() { 00065 if (empty($this->instance->parentcontextid)) { 00066 return 0; 00067 } 00068 $parentcontext = get_context_instance_by_id($this->instance->parentcontextid); 00069 if ($parentcontext->contextlevel != CONTEXT_MODULE) { 00070 return 0; 00071 } 00072 $cm = get_coursemodule_from_id('quiz', $parentcontext->instanceid); 00073 if (!$cm) { 00074 return 0; 00075 } 00076 return $cm->instance; 00077 } 00078 00079 function instance_config_save($data) { 00080 if (empty($data->quizid)) { 00081 $data->quizid = $this->get_owning_quiz(); 00082 } 00083 parent::instance_config_save($data); 00084 } 00085 00086 function get_content() { 00087 global $USER, $CFG, $DB; 00088 00089 if ($this->content !== NULL) { 00090 return $this->content; 00091 } 00092 00093 $this->content = new stdClass; 00094 $this->content->text = ''; 00095 $this->content->footer = ''; 00096 00097 if (empty($this->instance)) { 00098 return $this->content; 00099 } 00100 00101 if ($this->page->activityname == 'quiz' && $this->page->context->id == $this->instance->parentcontextid) { 00102 $quiz = $this->page->activityrecord; 00103 $quizid = $quiz->id; 00104 $courseid = $this->page->course->id; 00105 $inquiz = true; 00106 } else if (!empty($this->config->quizid)) { 00107 $quizid = $this->config->quizid; 00108 $quiz = $DB->get_record('quiz', array('id' => $quizid)); 00109 if (empty($quiz)) { 00110 $this->content->text = get_string('error_emptyquizrecord', 'block_quiz_results'); 00111 return $this->content; 00112 } 00113 $courseid = $quiz->course; 00114 $inquiz = false; 00115 } else { 00116 $quizid = 0; 00117 } 00118 00119 if (empty($quizid)) { 00120 $this->content->text = get_string('error_emptyquizid', 'block_quiz_results'); 00121 return $this->content; 00122 } 00123 00124 if (empty($this->config->showbest) && empty($this->config->showworst)) { 00125 $this->content->text = get_string('configuredtoshownothing', 'block_quiz_results'); 00126 return $this->content; 00127 } 00128 00129 // Get the grades for this quiz 00130 $grades = $DB->get_records('quiz_grades', array('quiz' => $quizid), 'grade, timemodified DESC'); 00131 00132 if (empty($grades)) { 00133 // No grades, sorry 00134 // The block will hide itself in this case 00135 return $this->content; 00136 } 00137 00138 $groupmode = NOGROUPS; 00139 $best = array(); 00140 $worst = array(); 00141 00142 if (!empty($this->config->nameformat)) { 00143 $nameformat = $this->config->nameformat; 00144 } else { 00145 $nameformat = B_QUIZRESULTS_NAME_FORMAT_FULL; 00146 } 00147 00148 if (!empty($this->config->usegroups)) { 00149 if ($inquiz) { 00150 $cm = $this->page->cm; 00151 $context = $this->page->context; 00152 } else { 00153 $cm = get_coursemodule_from_instance('quiz', $quizid, $courseid); 00154 $context = get_context_instance(CONTEXT_MODULE, $cm->id); 00155 } 00156 $groupmode = groups_get_activity_groupmode($cm); 00157 00158 if ($groupmode == SEPARATEGROUPS && has_capability('moodle/site:accessallgroups', $context)) { 00159 // We 'll make an exception in this case 00160 $groupmode = VISIBLEGROUPS; 00161 } 00162 } 00163 00164 switch ($groupmode) { 00165 case VISIBLEGROUPS: 00166 // Display group-mode results 00167 $groups = groups_get_all_groups($courseid); 00168 00169 if(empty($groups)) { 00170 // No groups exist, sorry 00171 $this->content->text = get_string('error_nogroupsexist', 'block_quiz_results'); 00172 return $this->content; 00173 } 00174 00175 // Find out all the userids which have a submitted grade 00176 $userids = array(); 00177 $gradeforuser = array(); 00178 foreach ($grades as $grade) { 00179 $userids[] = $grade->userid; 00180 $gradeforuser[$grade->userid] = (float)$grade->grade; 00181 } 00182 00183 // Now find which groups these users belong in 00184 list($usertest, $params) = $DB->get_in_or_equal($userids); 00185 $params[] = $courseid; 00186 $usergroups = $DB->get_records_sql(' 00187 SELECT gm.id, gm.userid, gm.groupid, g.name 00188 FROM {groups} g 00189 LEFT JOIN {groups_members} gm ON g.id = gm.groupid 00190 WHERE gm.userid ' . $usertest . ' AND g.courseid = ?', $params); 00191 00192 // Now, iterate the grades again and sum them up for each group 00193 $groupgrades = array(); 00194 foreach ($usergroups as $usergroup) { 00195 if (!isset($groupgrades[$usergroup->groupid])) { 00196 $groupgrades[$usergroup->groupid] = array( 00197 'sum' => (float)$gradeforuser[$usergroup->userid], 00198 'number' => 1, 00199 'group' => $usergroup->name); 00200 } else { 00201 $groupgrades[$usergroup->groupid]['sum'] += $gradeforuser[$usergroup->userid]; 00202 $groupgrades[$usergroup->groupid]['number'] += 1; 00203 } 00204 } 00205 00206 foreach($groupgrades as $groupid => $groupgrade) { 00207 $groupgrades[$groupid]['average'] = $groupgrades[$groupid]['sum'] / $groupgrades[$groupid]['number']; 00208 } 00209 00210 // Sort groupgrades according to average grade, ascending 00211 uasort($groupgrades, create_function('$a, $b', 'if($a["average"] == $b["average"]) return 0; return ($a["average"] > $b["average"] ? 1 : -1);')); 00212 00213 // How many groups do we have with graded member submissions to show? 00214 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($groupgrades)); 00215 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($groupgrades) - $numbest); 00216 00217 // Collect all the group results we are going to use in $best and $worst 00218 $remaining = $numbest; 00219 $groupgrade = end($groupgrades); 00220 while ($remaining--) { 00221 $best[key($groupgrades)] = $groupgrade['average']; 00222 $groupgrade = prev($groupgrades); 00223 } 00224 00225 $remaining = $numworst; 00226 $groupgrade = reset($groupgrades); 00227 while ($remaining--) { 00228 $worst[key($groupgrades)] = $groupgrade['average']; 00229 $groupgrade = next($groupgrades); 00230 } 00231 00232 // Ready for output! 00233 $gradeformat = intval(empty($this->config->gradeformat) ? B_QUIZRESULTS_GRADE_FORMAT_PCT : $this->config->gradeformat); 00234 00235 if (!$inquiz) { 00236 // Don't show header and link to the quiz if we ARE at the quiz... 00237 $this->content->text .= '<h1><a href="'.$CFG->wwwroot.'/mod/quiz/view.php?q='.$quizid.'">'.$quiz->name.'</a></h1>'; 00238 } 00239 00240 if ($nameformat = B_QUIZRESULTS_NAME_FORMAT_FULL) { 00241 if (has_capability('moodle/course:managegroups', $context)) { 00242 $grouplink = $CFG->wwwroot.'/group/overview.php?id='.$courseid.'&group='; 00243 } else if (has_capability('moodle/course:viewparticipants', $context)) { 00244 $grouplink = $CFG->wwwroot.'/user/index.php?id='.$courseid.'&group='; 00245 } else { 00246 $grouplink = ''; 00247 } 00248 } 00249 00250 $rank = 0; 00251 if(!empty($best)) { 00252 $this->content->text .= '<table class="grades"><caption>'; 00253 $this->content->text .= ($numbest == 1?get_string('bestgroupgrade', 'block_quiz_results'):get_string('bestgroupgrades', 'block_quiz_results', $numbest)); 00254 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>'; 00255 foreach($best as $groupid => $averagegrade) { 00256 switch($nameformat) { 00257 case B_QUIZRESULTS_NAME_FORMAT_ANON: 00258 case B_QUIZRESULTS_NAME_FORMAT_ID: 00259 $thisname = get_string('group'); 00260 break; 00261 default: 00262 case B_QUIZRESULTS_NAME_FORMAT_FULL: 00263 if ($grouplink) { 00264 $thisname = '<a href="'.$grouplink.$groupid.'">'.$groupgrades[$groupid]['group'].'</a>'; 00265 } else { 00266 $thisname = $groupgrades[$groupid]['group']; 00267 } 00268 break; 00269 } 00270 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 00271 switch($gradeformat) { 00272 case B_QUIZRESULTS_GRADE_FORMAT_FRA: 00273 $this->content->text .= quiz_format_grade($quiz, $averagegrade).'/'.$quiz->grade; 00274 break; 00275 case B_QUIZRESULTS_GRADE_FORMAT_ABS: 00276 $this->content->text .= quiz_format_grade($quiz, $averagegrade); 00277 break; 00278 default: 00279 case B_QUIZRESULTS_GRADE_FORMAT_PCT: 00280 $this->content->text .= round((float)$averagegrade / (float)$quiz->grade * 100).'%'; 00281 break; 00282 } 00283 $this->content->text .= '</td></tr>'; 00284 } 00285 $this->content->text .= '</tbody></table>'; 00286 } 00287 00288 $rank = 0; 00289 if(!empty($worst)) { 00290 $worst = array_reverse($worst, true); 00291 $this->content->text .= '<table class="grades"><caption>'; 00292 $this->content->text .= ($numworst == 1?get_string('worstgroupgrade', 'block_quiz_results'):get_string('worstgroupgrades', 'block_quiz_results', $numworst)); 00293 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>'; 00294 foreach($worst as $groupid => $averagegrade) { 00295 switch($nameformat) { 00296 case B_QUIZRESULTS_NAME_FORMAT_ANON: 00297 case B_QUIZRESULTS_NAME_FORMAT_ID: 00298 $thisname = get_string('group'); 00299 break; 00300 default: 00301 case B_QUIZRESULTS_NAME_FORMAT_FULL: 00302 $thisname = '<a href="'.$CFG->wwwroot.'/course/group.php?group='.$groupid.'&id='.$courseid.'">'.$groupgrades[$groupid]['group'].'</a>'; 00303 break; 00304 } 00305 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 00306 switch($gradeformat) { 00307 case B_QUIZRESULTS_GRADE_FORMAT_FRA: 00308 $this->content->text .= quiz_format_grade($quiz, $averagegrade).'/'.$quiz->grade; 00309 break; 00310 case B_QUIZRESULTS_GRADE_FORMAT_ABS: 00311 $this->content->text .= quiz_format_grade($quiz, $averagegrade); 00312 break; 00313 default: 00314 case B_QUIZRESULTS_GRADE_FORMAT_PCT: 00315 $this->content->text .= round((float)$averagegrade / (float)$quiz->grade * 100).'%'; 00316 break; 00317 } 00318 $this->content->text .= '</td></tr>'; 00319 } 00320 $this->content->text .= '</tbody></table>'; 00321 } 00322 break; 00323 00324 00325 case SEPARATEGROUPS: 00326 // This is going to be just like no-groups mode, only we 'll filter 00327 // out the grades from people not in our group. 00328 if (!isloggedin()) { 00329 // Not logged in, so show nothing 00330 return $this->content; 00331 } 00332 00333 $mygroups = groups_get_all_groups($courseid, $USER->id); 00334 if(empty($mygroups)) { 00335 // Not member of a group, show nothing 00336 return $this->content; 00337 } 00338 00339 // Get users from the same groups as me. 00340 list($grouptest, $params) = $DB->get_in_or_equal(array_keys($mygroups)); 00341 $mygroupsusers = $DB->get_records_sql_menu( 00342 'SELECT DISTINCT userid, 1 FROM {groups_members} WHERE groupid ' . $grouptest, 00343 $params); 00344 00345 // Filter out the grades belonging to other users, and proceed as if there were no groups 00346 foreach ($grades as $key => $grade) { 00347 if (!isset($mygroupsusers[$grade->userid])) { 00348 unset($grades[$key]); 00349 } 00350 } 00351 00352 // No break, fall through to the default case now we have filtered the $grades array. 00353 default: 00354 case NOGROUPS: 00355 // Single user mode 00356 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($grades)); 00357 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($grades) - $numbest); 00358 00359 // Collect all the usernames we are going to need 00360 $remaining = $numbest; 00361 $grade = end($grades); 00362 while($remaining--) { 00363 $best[$grade->userid] = $grade->id; 00364 $grade = prev($grades); 00365 } 00366 00367 $remaining = $numworst; 00368 $grade = reset($grades); 00369 while($remaining--) { 00370 $worst[$grade->userid] = $grade->id; 00371 $grade = next($grades); 00372 } 00373 00374 if(empty($best) && empty($worst)) { 00375 // Nothing to show, for some reason... 00376 return $this->content; 00377 } 00378 00379 // Now grab all the users from the database 00380 $userids = array_merge(array_keys($best), array_keys($worst)); 00381 $users = $DB->get_records_list('user', 'id', $userids, '', 'id, firstname, lastname, idnumber'); 00382 00383 // Ready for output! 00384 00385 $gradeformat = intval(empty($this->config->gradeformat) ? B_QUIZRESULTS_GRADE_FORMAT_PCT : $this->config->gradeformat); 00386 00387 if(!$inquiz) { 00388 // Don't show header and link to the quiz if we ARE at the quiz... 00389 $this->content->text .= '<h1><a href="'.$CFG->wwwroot.'/mod/quiz/view.php?q='.$quizid.'">'.$quiz->name.'</a></h1>'; 00390 } 00391 00392 $rank = 0; 00393 if(!empty($best)) { 00394 $this->content->text .= '<table class="grades"><caption>'; 00395 $this->content->text .= ($numbest == 1?get_string('bestgrade', 'block_quiz_results'):get_string('bestgrades', 'block_quiz_results', $numbest)); 00396 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>'; 00397 foreach($best as $userid => $gradeid) { 00398 switch($nameformat) { 00399 case B_QUIZRESULTS_NAME_FORMAT_ID: 00400 $thisname = get_string('user').' '.$users[$userid]->idnumber; 00401 break; 00402 case B_QUIZRESULTS_NAME_FORMAT_ANON: 00403 $thisname = get_string('user'); 00404 break; 00405 default: 00406 case B_QUIZRESULTS_NAME_FORMAT_FULL: 00407 $thisname = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'&course='.$courseid.'">'.fullname($users[$userid]).'</a>'; 00408 break; 00409 } 00410 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 00411 switch($gradeformat) { 00412 case B_QUIZRESULTS_GRADE_FORMAT_FRA: 00413 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade).'/'.$quiz->grade; 00414 break; 00415 case B_QUIZRESULTS_GRADE_FORMAT_ABS: 00416 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade); 00417 break; 00418 default: 00419 case B_QUIZRESULTS_GRADE_FORMAT_PCT: 00420 if ($quiz->grade) { 00421 $this->content->text .= round((float)$grades[$gradeid]->grade / (float)$quiz->grade * 100).'%'; 00422 } else { 00423 $this->content->text .= '--%'; 00424 } 00425 break; 00426 } 00427 $this->content->text .= '</td></tr>'; 00428 } 00429 $this->content->text .= '</tbody></table>'; 00430 } 00431 00432 $rank = 0; 00433 if(!empty($worst)) { 00434 $worst = array_reverse($worst, true); 00435 $this->content->text .= '<table class="grades"><caption>'; 00436 $this->content->text .= ($numworst == 1?get_string('worstgrade', 'block_quiz_results'):get_string('worstgrades', 'block_quiz_results', $numworst)); 00437 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>'; 00438 foreach($worst as $userid => $gradeid) { 00439 switch($nameformat) { 00440 case B_QUIZRESULTS_NAME_FORMAT_ID: 00441 $thisname = get_string('user').' '.$users[$userid]->idnumber; 00442 break; 00443 case B_QUIZRESULTS_NAME_FORMAT_ANON: 00444 $thisname = get_string('user'); 00445 break; 00446 default: 00447 case B_QUIZRESULTS_NAME_FORMAT_FULL: 00448 $thisname = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'&course='.$courseid.'">'.fullname($users[$userid]).'</a>'; 00449 break; 00450 } 00451 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 00452 switch($gradeformat) { 00453 case B_QUIZRESULTS_GRADE_FORMAT_FRA: 00454 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade).'/'.$quiz->grade; 00455 break; 00456 case B_QUIZRESULTS_GRADE_FORMAT_ABS: 00457 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade); 00458 break; 00459 default: 00460 case B_QUIZRESULTS_GRADE_FORMAT_PCT: 00461 $this->content->text .= round((float)$grades[$gradeid]->grade / (float)$quiz->grade * 100).'%'; 00462 break; 00463 } 00464 $this->content->text .= '</td></tr>'; 00465 } 00466 $this->content->text .= '</tbody></table>'; 00467 } 00468 break; 00469 } 00470 00471 return $this->content; 00472 } 00473 00474 function instance_allow_multiple() { 00475 return true; 00476 } 00477 } 00478 00479