[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Classes to enforce the various access rules that can apply to a quiz. 19 * 20 * @package block_quiz_results 21 * @copyright 2009 Tim Hunt 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 require_once($CFG->dirroot . '/mod/quiz/lib.php'); 29 30 31 /** 32 * Block quiz_results class definition. 33 * 34 * This block can be added to a course page or a quiz page to display of list of 35 * the best/worst students/groups in a particular quiz. 36 * 37 * @package block_quiz_results 38 * @copyright 2009 Tim Hunt 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 define('B_QUIZRESULTS_NAME_FORMAT_FULL', 1); 42 define('B_QUIZRESULTS_NAME_FORMAT_ID', 2); 43 define('B_QUIZRESULTS_NAME_FORMAT_ANON', 3); 44 define('B_QUIZRESULTS_GRADE_FORMAT_PCT', 1); 45 define('B_QUIZRESULTS_GRADE_FORMAT_FRA', 2); 46 define('B_QUIZRESULTS_GRADE_FORMAT_ABS', 3); 47 48 class block_quiz_results extends block_base { 49 function init() { 50 $this->title = get_string('pluginname', 'block_quiz_results'); 51 } 52 53 function applicable_formats() { 54 return array('course' => true, 'mod-quiz' => true); 55 } 56 57 /** 58 * If this block belongs to a quiz context, then return that quiz's id. 59 * Otherwise, return 0. 60 * @return integer the quiz id. 61 */ 62 public function get_owning_quiz() { 63 if (empty($this->instance->parentcontextid)) { 64 return 0; 65 } 66 $parentcontext = context::instance_by_id($this->instance->parentcontextid); 67 if ($parentcontext->contextlevel != CONTEXT_MODULE) { 68 return 0; 69 } 70 $cm = get_coursemodule_from_id('quiz', $parentcontext->instanceid); 71 if (!$cm) { 72 return 0; 73 } 74 return $cm->instance; 75 } 76 77 function instance_config_save($data, $nolongerused = false) { 78 if (empty($data->quizid)) { 79 $data->quizid = $this->get_owning_quiz(); 80 } 81 parent::instance_config_save($data); 82 } 83 84 function get_content() { 85 global $USER, $CFG, $DB; 86 87 if ($this->content !== NULL) { 88 return $this->content; 89 } 90 91 $this->content = new stdClass; 92 $this->content->text = ''; 93 $this->content->footer = ''; 94 95 if (empty($this->instance)) { 96 return $this->content; 97 } 98 99 if ($this->page->activityname == 'quiz' && $this->page->context->id == $this->instance->parentcontextid) { 100 $quiz = $this->page->activityrecord; 101 $quizid = $quiz->id; 102 $courseid = $this->page->course->id; 103 $inquiz = true; 104 } else if (!empty($this->config->quizid)) { 105 $quizid = $this->config->quizid; 106 $quiz = $DB->get_record('quiz', array('id' => $quizid)); 107 if (empty($quiz)) { 108 $this->content->text = get_string('error_emptyquizrecord', 'block_quiz_results'); 109 return $this->content; 110 } 111 $courseid = $quiz->course; 112 $inquiz = false; 113 } else { 114 $quizid = 0; 115 } 116 117 if (empty($quizid)) { 118 $this->content->text = get_string('error_emptyquizid', 'block_quiz_results'); 119 return $this->content; 120 } 121 122 if (empty($this->config->showbest) && empty($this->config->showworst)) { 123 $this->content->text = get_string('configuredtoshownothing', 'block_quiz_results'); 124 return $this->content; 125 } 126 127 // Get the grades for this quiz 128 $grades = $DB->get_records('quiz_grades', array('quiz' => $quizid), 'grade, timemodified DESC'); 129 130 if (empty($grades)) { 131 // No grades, sorry 132 // The block will hide itself in this case 133 return $this->content; 134 } 135 136 $groupmode = NOGROUPS; 137 $best = array(); 138 $worst = array(); 139 140 if (!empty($this->config->nameformat)) { 141 $nameformat = $this->config->nameformat; 142 } else { 143 $nameformat = B_QUIZRESULTS_NAME_FORMAT_FULL; 144 } 145 146 if (!empty($this->config->usegroups)) { 147 if ($inquiz) { 148 $cm = $this->page->cm; 149 $context = $this->page->context; 150 } else { 151 $cm = get_coursemodule_from_instance('quiz', $quizid, $courseid); 152 $context = context_module::instance($cm->id); 153 } 154 $groupmode = groups_get_activity_groupmode($cm); 155 156 if ($groupmode == SEPARATEGROUPS && has_capability('moodle/site:accessallgroups', $context)) { 157 // We 'll make an exception in this case 158 $groupmode = VISIBLEGROUPS; 159 } 160 } 161 162 switch ($groupmode) { 163 case VISIBLEGROUPS: 164 // Display group-mode results 165 $groups = groups_get_all_groups($courseid); 166 167 if(empty($groups)) { 168 // No groups exist, sorry 169 $this->content->text = get_string('error_nogroupsexist', 'block_quiz_results'); 170 return $this->content; 171 } 172 173 // Find out all the userids which have a submitted grade 174 $userids = array(); 175 $gradeforuser = array(); 176 foreach ($grades as $grade) { 177 $userids[] = $grade->userid; 178 $gradeforuser[$grade->userid] = (float)$grade->grade; 179 } 180 181 // Now find which groups these users belong in 182 list($usertest, $params) = $DB->get_in_or_equal($userids); 183 $params[] = $courseid; 184 $usergroups = $DB->get_records_sql(' 185 SELECT gm.id, gm.userid, gm.groupid, g.name 186 FROM {groups} g 187 LEFT JOIN {groups_members} gm ON g.id = gm.groupid 188 WHERE gm.userid ' . $usertest . ' AND g.courseid = ?', $params); 189 190 // Now, iterate the grades again and sum them up for each group 191 $groupgrades = array(); 192 foreach ($usergroups as $usergroup) { 193 if (!isset($groupgrades[$usergroup->groupid])) { 194 $groupgrades[$usergroup->groupid] = array( 195 'sum' => (float)$gradeforuser[$usergroup->userid], 196 'number' => 1, 197 'group' => $usergroup->name); 198 } else { 199 $groupgrades[$usergroup->groupid]['sum'] += $gradeforuser[$usergroup->userid]; 200 $groupgrades[$usergroup->groupid]['number'] += 1; 201 } 202 } 203 204 foreach($groupgrades as $groupid => $groupgrade) { 205 $groupgrades[$groupid]['average'] = $groupgrades[$groupid]['sum'] / $groupgrades[$groupid]['number']; 206 } 207 208 // Sort groupgrades according to average grade, ascending 209 uasort($groupgrades, create_function('$a, $b', 'if($a["average"] == $b["average"]) return 0; return ($a["average"] > $b["average"] ? 1 : -1);')); 210 211 // How many groups do we have with graded member submissions to show? 212 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($groupgrades)); 213 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($groupgrades) - $numbest); 214 215 // Collect all the group results we are going to use in $best and $worst 216 $remaining = $numbest; 217 $groupgrade = end($groupgrades); 218 while ($remaining--) { 219 $best[key($groupgrades)] = $groupgrade['average']; 220 $groupgrade = prev($groupgrades); 221 } 222 223 $remaining = $numworst; 224 $groupgrade = reset($groupgrades); 225 while ($remaining--) { 226 $worst[key($groupgrades)] = $groupgrade['average']; 227 $groupgrade = next($groupgrades); 228 } 229 230 // Ready for output! 231 $gradeformat = intval(empty($this->config->gradeformat) ? B_QUIZRESULTS_GRADE_FORMAT_PCT : $this->config->gradeformat); 232 233 if (!$inquiz) { 234 // Don't show header and link to the quiz if we ARE at the quiz... 235 $this->content->text .= '<h1><a href="'.$CFG->wwwroot.'/mod/quiz/view.php?q='.$quizid.'">'.$quiz->name.'</a></h1>'; 236 } 237 238 if ($nameformat = B_QUIZRESULTS_NAME_FORMAT_FULL) { 239 if (has_capability('moodle/course:managegroups', $context)) { 240 $grouplink = $CFG->wwwroot.'/group/overview.php?id='.$courseid.'&group='; 241 } else if (has_capability('moodle/course:viewparticipants', $context)) { 242 $grouplink = $CFG->wwwroot.'/user/index.php?id='.$courseid.'&group='; 243 } else { 244 $grouplink = ''; 245 } 246 } 247 248 $rank = 0; 249 if(!empty($best)) { 250 $this->content->text .= '<table class="grades"><caption>'; 251 $this->content->text .= ($numbest == 1?get_string('bestgroupgrade', 'block_quiz_results'):get_string('bestgroupgrades', 'block_quiz_results', $numbest)); 252 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>'; 253 foreach($best as $groupid => $averagegrade) { 254 switch($nameformat) { 255 case B_QUIZRESULTS_NAME_FORMAT_ANON: 256 case B_QUIZRESULTS_NAME_FORMAT_ID: 257 $thisname = get_string('group'); 258 break; 259 default: 260 case B_QUIZRESULTS_NAME_FORMAT_FULL: 261 if ($grouplink) { 262 $thisname = '<a href="'.$grouplink.$groupid.'">'.$groupgrades[$groupid]['group'].'</a>'; 263 } else { 264 $thisname = $groupgrades[$groupid]['group']; 265 } 266 break; 267 } 268 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 269 switch($gradeformat) { 270 case B_QUIZRESULTS_GRADE_FORMAT_FRA: 271 $this->content->text .= quiz_format_grade($quiz, $averagegrade).'/'.$quiz->grade; 272 break; 273 case B_QUIZRESULTS_GRADE_FORMAT_ABS: 274 $this->content->text .= quiz_format_grade($quiz, $averagegrade); 275 break; 276 default: 277 case B_QUIZRESULTS_GRADE_FORMAT_PCT: 278 $this->content->text .= round((float)$averagegrade / (float)$quiz->grade * 100).'%'; 279 break; 280 } 281 $this->content->text .= '</td></tr>'; 282 } 283 $this->content->text .= '</tbody></table>'; 284 } 285 286 $rank = 0; 287 if(!empty($worst)) { 288 $worst = array_reverse($worst, true); 289 $this->content->text .= '<table class="grades"><caption>'; 290 $this->content->text .= ($numworst == 1?get_string('worstgroupgrade', 'block_quiz_results'):get_string('worstgroupgrades', 'block_quiz_results', $numworst)); 291 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>'; 292 foreach($worst as $groupid => $averagegrade) { 293 switch($nameformat) { 294 case B_QUIZRESULTS_NAME_FORMAT_ANON: 295 case B_QUIZRESULTS_NAME_FORMAT_ID: 296 $thisname = get_string('group'); 297 break; 298 default: 299 case B_QUIZRESULTS_NAME_FORMAT_FULL: 300 $thisname = '<a href="'.$CFG->wwwroot.'/course/group.php?group='.$groupid.'&id='.$courseid.'">'.$groupgrades[$groupid]['group'].'</a>'; 301 break; 302 } 303 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 304 switch($gradeformat) { 305 case B_QUIZRESULTS_GRADE_FORMAT_FRA: 306 $this->content->text .= quiz_format_grade($quiz, $averagegrade).'/'.$quiz->grade; 307 break; 308 case B_QUIZRESULTS_GRADE_FORMAT_ABS: 309 $this->content->text .= quiz_format_grade($quiz, $averagegrade); 310 break; 311 default: 312 case B_QUIZRESULTS_GRADE_FORMAT_PCT: 313 $this->content->text .= round((float)$averagegrade / (float)$quiz->grade * 100).'%'; 314 break; 315 } 316 $this->content->text .= '</td></tr>'; 317 } 318 $this->content->text .= '</tbody></table>'; 319 } 320 break; 321 322 323 case SEPARATEGROUPS: 324 // This is going to be just like no-groups mode, only we 'll filter 325 // out the grades from people not in our group. 326 if (!isloggedin()) { 327 // Not logged in, so show nothing 328 return $this->content; 329 } 330 331 $mygroups = groups_get_all_groups($courseid, $USER->id); 332 if(empty($mygroups)) { 333 // Not member of a group, show nothing 334 return $this->content; 335 } 336 337 // Get users from the same groups as me. 338 list($grouptest, $params) = $DB->get_in_or_equal(array_keys($mygroups)); 339 $mygroupsusers = $DB->get_records_sql_menu( 340 'SELECT DISTINCT userid, 1 FROM {groups_members} WHERE groupid ' . $grouptest, 341 $params); 342 343 // Filter out the grades belonging to other users, and proceed as if there were no groups 344 foreach ($grades as $key => $grade) { 345 if (!isset($mygroupsusers[$grade->userid])) { 346 unset($grades[$key]); 347 } 348 } 349 350 // No break, fall through to the default case now we have filtered the $grades array. 351 default: 352 case NOGROUPS: 353 // Single user mode 354 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($grades)); 355 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($grades) - $numbest); 356 357 // Collect all the usernames we are going to need 358 $remaining = $numbest; 359 $grade = end($grades); 360 while($remaining--) { 361 $best[$grade->userid] = $grade->id; 362 $grade = prev($grades); 363 } 364 365 $remaining = $numworst; 366 $grade = reset($grades); 367 while($remaining--) { 368 $worst[$grade->userid] = $grade->id; 369 $grade = next($grades); 370 } 371 372 if(empty($best) && empty($worst)) { 373 // Nothing to show, for some reason... 374 return $this->content; 375 } 376 377 // Now grab all the users from the database 378 $userids = array_merge(array_keys($best), array_keys($worst)); 379 $fields = array_merge(array('id', 'idnumber'), get_all_user_name_fields()); 380 $fields = implode(',', $fields); 381 $users = $DB->get_records_list('user', 'id', $userids, '', $fields); 382 383 // Ready for output! 384 385 $gradeformat = intval(empty($this->config->gradeformat) ? B_QUIZRESULTS_GRADE_FORMAT_PCT : $this->config->gradeformat); 386 387 if(!$inquiz) { 388 // Don't show header and link to the quiz if we ARE at the quiz... 389 $this->content->text .= '<h1><a href="'.$CFG->wwwroot.'/mod/quiz/view.php?q='.$quizid.'">'.$quiz->name.'</a></h1>'; 390 } 391 392 $rank = 0; 393 if(!empty($best)) { 394 $this->content->text .= '<table class="grades"><caption>'; 395 $this->content->text .= ($numbest == 1?get_string('bestgrade', 'block_quiz_results'):get_string('bestgrades', 'block_quiz_results', $numbest)); 396 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>'; 397 foreach($best as $userid => $gradeid) { 398 switch($nameformat) { 399 case B_QUIZRESULTS_NAME_FORMAT_ID: 400 $thisname = get_string('user').' '.$users[$userid]->idnumber; 401 break; 402 case B_QUIZRESULTS_NAME_FORMAT_ANON: 403 $thisname = get_string('user'); 404 break; 405 default: 406 case B_QUIZRESULTS_NAME_FORMAT_FULL: 407 $thisname = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'&course='.$courseid.'">'.fullname($users[$userid]).'</a>'; 408 break; 409 } 410 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 411 switch($gradeformat) { 412 case B_QUIZRESULTS_GRADE_FORMAT_FRA: 413 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade).'/'.$quiz->grade; 414 break; 415 case B_QUIZRESULTS_GRADE_FORMAT_ABS: 416 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade); 417 break; 418 default: 419 case B_QUIZRESULTS_GRADE_FORMAT_PCT: 420 if ($quiz->grade) { 421 $this->content->text .= round((float)$grades[$gradeid]->grade / (float)$quiz->grade * 100).'%'; 422 } else { 423 $this->content->text .= '--%'; 424 } 425 break; 426 } 427 $this->content->text .= '</td></tr>'; 428 } 429 $this->content->text .= '</tbody></table>'; 430 } 431 432 $rank = 0; 433 if(!empty($worst)) { 434 $worst = array_reverse($worst, true); 435 $this->content->text .= '<table class="grades"><caption>'; 436 $this->content->text .= ($numworst == 1?get_string('worstgrade', 'block_quiz_results'):get_string('worstgrades', 'block_quiz_results', $numworst)); 437 $this->content->text .= '</caption><colgroup class="number" /><colgroup class="name" /><colgroup class="grade" /><tbody>'; 438 foreach($worst as $userid => $gradeid) { 439 switch($nameformat) { 440 case B_QUIZRESULTS_NAME_FORMAT_ID: 441 $thisname = get_string('user').' '.$users[$userid]->idnumber; 442 break; 443 case B_QUIZRESULTS_NAME_FORMAT_ANON: 444 $thisname = get_string('user'); 445 break; 446 default: 447 case B_QUIZRESULTS_NAME_FORMAT_FULL: 448 $thisname = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'&course='.$courseid.'">'.fullname($users[$userid]).'</a>'; 449 break; 450 } 451 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 452 switch($gradeformat) { 453 case B_QUIZRESULTS_GRADE_FORMAT_FRA: 454 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade).'/'.$quiz->grade; 455 break; 456 case B_QUIZRESULTS_GRADE_FORMAT_ABS: 457 $this->content->text .= quiz_format_grade($quiz, $grades[$gradeid]->grade); 458 break; 459 default: 460 case B_QUIZRESULTS_GRADE_FORMAT_PCT: 461 $this->content->text .= round((float)$grades[$gradeid]->grade / (float)$quiz->grade * 100).'%'; 462 break; 463 } 464 $this->content->text .= '</td></tr>'; 465 } 466 $this->content->text .= '</tbody></table>'; 467 } 468 break; 469 } 470 471 return $this->content; 472 } 473 474 function instance_allow_multiple() { 475 return true; 476 } 477 } 478 479
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |