Differences Between: [Versions 310 and 403] [Versions 39 and 403]
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 activity. 19 * 20 * @package block_activity_results 21 * @copyright 2009 Tim Hunt 22 * @copyright 2015 Stephen Bourget 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 require_once($CFG->dirroot . '/lib/grade/constants.php'); 29 require_once($CFG->dirroot . '/course/lib.php'); 30 31 define('B_ACTIVITYRESULTS_NAME_FORMAT_FULL', 1); 32 define('B_ACTIVITYRESULTS_NAME_FORMAT_ID', 2); 33 define('B_ACTIVITYRESULTS_NAME_FORMAT_ANON', 3); 34 define('B_ACTIVITYRESULTS_GRADE_FORMAT_PCT', 1); 35 define('B_ACTIVITYRESULTS_GRADE_FORMAT_FRA', 2); 36 define('B_ACTIVITYRESULTS_GRADE_FORMAT_ABS', 3); 37 define('B_ACTIVITYRESULTS_GRADE_FORMAT_SCALE', 4); 38 39 /** 40 * Block activity_results class definition. 41 * 42 * This block can be added to a course page or a activity page to display of list of 43 * the best/worst students/groups in a particular activity. 44 * 45 * @package block_activity_results 46 * @copyright 2009 Tim Hunt 47 * @copyright 2015 Stephen Bourget 48 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 49 */ 50 class block_activity_results extends block_base { 51 52 /** 53 * Core function used to initialize the block. 54 */ 55 public function init() { 56 $this->title = get_string('pluginname', 'block_activity_results'); 57 } 58 59 /** 60 * Allow the block to have a configuration page 61 * 62 * @return boolean 63 */ 64 public function has_config() { 65 return true; 66 } 67 68 /** 69 * Core function, specifies where the block can be used. 70 * @return array 71 */ 72 public function applicable_formats() { 73 return array('course-view' => true, 'mod' => true); 74 } 75 76 /** 77 * If this block belongs to a activity context, then return that activity's id. 78 * Otherwise, return 0. 79 * @return stdclass the activity record. 80 */ 81 public function get_owning_activity() { 82 global $DB; 83 84 // Set some defaults. 85 $result = new stdClass(); 86 $result->id = 0; 87 88 if (empty($this->instance->parentcontextid)) { 89 return $result; 90 } 91 $parentcontext = context::instance_by_id($this->instance->parentcontextid); 92 if ($parentcontext->contextlevel != CONTEXT_MODULE) { 93 return $result; 94 } 95 $cm = get_coursemodule_from_id($this->page->cm->modname, $parentcontext->instanceid); 96 if (!$cm) { 97 return $result; 98 } 99 // Get the grade_items id. 100 $rec = $DB->get_record('grade_items', array('iteminstance' => $cm->instance, 'itemmodule' => $this->page->cm->modname)); 101 if (!$rec) { 102 return $result; 103 } 104 // See if it is a gradable activity. 105 if (($rec->gradetype != GRADE_TYPE_VALUE) && ($rec->gradetype != GRADE_TYPE_SCALE)) { 106 return $result; 107 } 108 return $rec; 109 } 110 111 /** 112 * Used to save the form config data 113 * @param stdclass $data 114 * @param bool $nolongerused 115 */ 116 public function instance_config_save($data, $nolongerused = false) { 117 global $DB; 118 if (empty($data->activitygradeitemid)) { 119 // Figure out info about parent module. 120 $info = $this->get_owning_activity(); 121 $data->activitygradeitemid = $info->id; 122 if ($info->id < 1) { 123 // No activity was selected. 124 $info->itemmodule = ''; 125 $info->iteminstance = ''; 126 } else { 127 $data->activityparent = $info->itemmodule; 128 $data->activityparentid = $info->iteminstance; 129 } 130 } else { 131 // Lookup info about the parent module (we have the id from mdl_grade_items. 132 $info = $DB->get_record('grade_items', array('id' => $data->activitygradeitemid)); 133 $data->activityparent = $info->itemmodule; 134 $data->activityparentid = $info->iteminstance; 135 } 136 parent::instance_config_save($data); 137 } 138 139 /** 140 * Used to generate the content for the block. 141 * @return string 142 */ 143 public function get_content() { 144 global $USER, $CFG, $DB; 145 146 if ($this->content !== null) { 147 return $this->content; 148 } 149 150 $this->content = new stdClass; 151 $this->content->text = ''; 152 $this->content->footer = ''; 153 154 if (empty($this->instance)) { 155 return $this->content; 156 } 157 158 // We are configured so use the configuration. 159 if (!empty($this->config->activitygradeitemid)) { 160 // We are configured. 161 $activitygradeitemid = $this->config->activitygradeitemid; 162 163 // Lookup the module in the grade_items table. 164 $activity = $DB->get_record('grade_items', array('id' => $activitygradeitemid)); 165 if (empty($activity)) { 166 // Activity does not exist. 167 $this->content->text = get_string('error_emptyactivityrecord', 'block_activity_results'); 168 return $this->content; 169 } 170 $courseid = $activity->courseid; 171 $inactivity = false; 172 } else { 173 // Not configured. 174 $activitygradeitemid = 0; 175 } 176 177 // Check to see if we are in the moule we are displaying results for. 178 if (!empty($this->config->activitygradeitemid)) { 179 if ($this->get_owning_activity()->id == $this->config->activitygradeitemid) { 180 $inactivity = true; 181 } else { 182 $inactivity = false; 183 } 184 } 185 186 // Activity ID is missing. 187 if (empty($activitygradeitemid)) { 188 $this->content->text = get_string('error_emptyactivityid', 'block_activity_results'); 189 return $this->content; 190 } 191 192 // Check to see if we are configured. 193 if (empty($this->config->showbest) && empty($this->config->showworst)) { 194 $this->content->text = get_string('configuredtoshownothing', 'block_activity_results'); 195 return $this->content; 196 } 197 198 // Check to see if it is a supported grade type. 199 if (empty($activity->gradetype) || ($activity->gradetype != GRADE_TYPE_VALUE && $activity->gradetype != GRADE_TYPE_SCALE)) { 200 $this->content->text = get_string('error_unsupportedgradetype', 'block_activity_results'); 201 return $this->content; 202 } 203 204 // Get the grades for this activity. 205 $sql = 'SELECT * FROM {grade_grades} 206 WHERE itemid = ? AND finalgrade is not NULL 207 ORDER BY finalgrade, timemodified DESC'; 208 209 $grades = $DB->get_records_sql($sql, array( $activitygradeitemid)); 210 211 if (empty($grades) || $activity->hidden) { 212 // No grades available, The block will hide itself in this case. 213 return $this->content; 214 } 215 216 // Set up results. 217 $groupmode = NOGROUPS; 218 $best = array(); 219 $worst = array(); 220 221 if (!empty($this->config->nameformat)) { 222 $nameformat = $this->config->nameformat; 223 } else { 224 $nameformat = B_ACTIVITYRESULTS_NAME_FORMAT_FULL; 225 } 226 227 // Get $cm and context. 228 if ($inactivity) { 229 $cm = $this->page->cm; 230 $context = $this->page->context; 231 } else { 232 $cm = get_coursemodule_from_instance($activity->itemmodule, $activity->iteminstance, $courseid); 233 $context = context_module::instance($cm->id); 234 } 235 236 if (!empty($this->config->usegroups)) { 237 $groupmode = groups_get_activity_groupmode($cm); 238 239 if ($groupmode == SEPARATEGROUPS && has_capability('moodle/site:accessallgroups', $context)) { 240 // If you have the ability to see all groups then lets show them. 241 $groupmode = VISIBLEGROUPS; 242 } 243 } 244 245 switch ($groupmode) { 246 case VISIBLEGROUPS: 247 // Display group-mode results. 248 $groups = groups_get_all_groups($courseid); 249 250 if (empty($groups)) { 251 // No groups exist, sorry. 252 $this->content->text = get_string('error_nogroupsexist', 'block_activity_results'); 253 return $this->content; 254 } 255 256 // Find out all the userids which have a submitted grade. 257 $userids = array(); 258 $gradeforuser = array(); 259 foreach ($grades as $grade) { 260 $userids[] = $grade->userid; 261 $gradeforuser[$grade->userid] = (float)$grade->finalgrade; 262 } 263 264 // Now find which groups these users belong in. 265 list($usertest, $params) = $DB->get_in_or_equal($userids); 266 $params[] = $courseid; 267 $usergroups = $DB->get_records_sql(' 268 SELECT gm.id, gm.userid, gm.groupid, g.name 269 FROM {groups} g 270 LEFT JOIN {groups_members} gm ON g.id = gm.groupid 271 WHERE gm.userid ' . $usertest . ' AND g.courseid = ?', $params); 272 273 // Now, iterate the grades again and sum them up for each group. 274 $groupgrades = array(); 275 foreach ($usergroups as $usergroup) { 276 if (!isset($groupgrades[$usergroup->groupid])) { 277 $groupgrades[$usergroup->groupid] = array( 278 'sum' => (float)$gradeforuser[$usergroup->userid], 279 'number' => 1, 280 'group' => $usergroup->name); 281 } else { 282 $groupgrades[$usergroup->groupid]['sum'] += $gradeforuser[$usergroup->userid]; 283 $groupgrades[$usergroup->groupid]['number'] += 1; 284 } 285 } 286 287 foreach ($groupgrades as $groupid => $groupgrade) { 288 $groupgrades[$groupid]['average'] = $groupgrades[$groupid]['sum'] / $groupgrades[$groupid]['number']; 289 } 290 291 // Sort groupgrades according to average grade, ascending. 292 uasort($groupgrades, function($a, $b) { 293 if ($a["average"] == $b["average"]) { 294 return 0; 295 } 296 return ($a["average"] > $b["average"] ? 1 : -1); 297 }); 298 299 // How many groups do we have with graded member submissions to show? 300 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($groupgrades)); 301 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($groupgrades) - $numbest); 302 303 // Collect all the group results we are going to use in $best and $worst. 304 $remaining = $numbest; 305 $groupgrade = end($groupgrades); 306 while ($remaining--) { 307 $best[key($groupgrades)] = $groupgrade['average']; 308 $groupgrade = prev($groupgrades); 309 } 310 311 $remaining = $numworst; 312 $groupgrade = reset($groupgrades); 313 while ($remaining--) { 314 $worst[key($groupgrades)] = $groupgrade['average']; 315 $groupgrade = next($groupgrades); 316 } 317 318 // Ready for output! 319 if ($activity->gradetype == GRADE_TYPE_SCALE) { 320 // We must display the results using scales. 321 $gradeformat = B_ACTIVITYRESULTS_GRADE_FORMAT_SCALE; 322 // Preload the scale. 323 $scale = $this->get_scale($activity->scaleid); 324 } else if (intval(empty($this->config->gradeformat))) { 325 $gradeformat = B_ACTIVITYRESULTS_GRADE_FORMAT_PCT; 326 } else { 327 $gradeformat = $this->config->gradeformat; 328 } 329 330 // Generate the header. 331 $this->content->text .= $this->activity_link($activity, $cm); 332 333 if ($nameformat == B_ACTIVITYRESULTS_NAME_FORMAT_FULL) { 334 if (has_capability('moodle/course:managegroups', $context)) { 335 $grouplink = $CFG->wwwroot.'/group/overview.php?id='.$courseid.'&group='; 336 } else if (course_can_view_participants($context)) { 337 $grouplink = $CFG->wwwroot.'/user/index.php?id='.$courseid.'&group='; 338 } else { 339 $grouplink = ''; 340 } 341 } 342 343 $rank = 0; 344 if (!empty($best)) { 345 $this->content->text .= '<table class="grades"><caption class="pb-0"><h6>'; 346 if ($numbest == 1) { 347 $this->content->text .= get_string('bestgroupgrade', 'block_activity_results'); 348 } else { 349 $this->content->text .= get_string('bestgroupgrades', 'block_activity_results', $numbest); 350 } 351 $this->content->text .= '</h6></caption><colgroup class="number" />'; 352 $this->content->text .= '<colgroup class="name" /><colgroup class="grade" /><tbody>'; 353 foreach ($best as $groupid => $averagegrade) { 354 switch ($nameformat) { 355 case B_ACTIVITYRESULTS_NAME_FORMAT_ANON: 356 case B_ACTIVITYRESULTS_NAME_FORMAT_ID: 357 $thisname = get_string('group'); 358 break; 359 default: 360 case B_ACTIVITYRESULTS_NAME_FORMAT_FULL: 361 if ($grouplink) { 362 $thisname = '<a href="'.$grouplink.$groupid.'">'.$groupgrades[$groupid]['group'].'</a>'; 363 } else { 364 $thisname = $groupgrades[$groupid]['group']; 365 } 366 break; 367 } 368 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 369 switch ($gradeformat) { 370 case B_ACTIVITYRESULTS_GRADE_FORMAT_SCALE: 371 // Round answer up and locate appropriate scale. 372 $answer = (round($averagegrade, 0, PHP_ROUND_HALF_UP) - 1); 373 if (isset($scale[$answer])) { 374 $this->content->text .= $scale[$answer]; 375 } else { 376 // Value is not in the scale. 377 $this->content->text .= get_string('unknown', 'block_activity_results'); 378 } 379 break; 380 case B_ACTIVITYRESULTS_GRADE_FORMAT_FRA: 381 $this->content->text .= $this->activity_format_grade($averagegrade) 382 . '/' . $this->activity_format_grade($activity->grademax); 383 break; 384 case B_ACTIVITYRESULTS_GRADE_FORMAT_ABS: 385 $this->content->text .= $this->activity_format_grade($averagegrade); 386 break; 387 default: 388 case B_ACTIVITYRESULTS_GRADE_FORMAT_PCT: 389 $this->content->text .= $this->activity_format_grade((float)$averagegrade / 390 (float)$activity->grademax * 100).'%'; 391 break; 392 } 393 $this->content->text .= '</td></tr>'; 394 } 395 $this->content->text .= '</tbody></table>'; 396 } 397 398 $rank = 0; 399 if (!empty($worst)) { 400 $worst = array_reverse($worst, true); 401 $this->content->text .= '<table class="grades"><caption class="pb-0"><h6>'; 402 if ($numworst == 1) { 403 $this->content->text .= get_string('worstgroupgrade', 'block_activity_results'); 404 } else { 405 $this->content->text .= get_string('worstgroupgrades', 'block_activity_results', $numworst); 406 } 407 $this->content->text .= '</h6></caption><colgroup class="number" />'; 408 $this->content->text .= '<colgroup class="name" /><colgroup class="grade" /><tbody>'; 409 foreach ($worst as $groupid => $averagegrade) { 410 switch ($nameformat) { 411 case B_ACTIVITYRESULTS_NAME_FORMAT_ANON: 412 case B_ACTIVITYRESULTS_NAME_FORMAT_ID: 413 $thisname = get_string('group'); 414 break; 415 default: 416 case B_ACTIVITYRESULTS_NAME_FORMAT_FULL: 417 if ($grouplink) { 418 $thisname = '<a href="'.$grouplink.$groupid.'">'.$groupgrades[$groupid]['group'].'</a>'; 419 } else { 420 $thisname = $groupgrades[$groupid]['group']; 421 } 422 break; 423 } 424 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 425 switch ($gradeformat) { 426 case B_ACTIVITYRESULTS_GRADE_FORMAT_SCALE: 427 // Round answer up and locate appropriate scale. 428 $answer = (round($averagegrade, 0, PHP_ROUND_HALF_UP) - 1); 429 if (isset($scale[$answer])) { 430 $this->content->text .= $scale[$answer]; 431 } else { 432 // Value is not in the scale. 433 $this->content->text .= get_string('unknown', 'block_activity_results'); 434 } 435 break; 436 case B_ACTIVITYRESULTS_GRADE_FORMAT_FRA: 437 $this->content->text .= $this->activity_format_grade($averagegrade) 438 . '/' . $this->activity_format_grade($activity->grademax); 439 break; 440 case B_ACTIVITYRESULTS_GRADE_FORMAT_ABS: 441 $this->content->text .= $this->activity_format_grade($averagegrade); 442 break; 443 default: 444 case B_ACTIVITYRESULTS_GRADE_FORMAT_PCT: 445 $this->content->text .= $this->activity_format_grade((float)$averagegrade / 446 (float)$activity->grademax * 100).'%'; 447 break; 448 } 449 $this->content->text .= '</td></tr>'; 450 } 451 $this->content->text .= '</tbody></table>'; 452 } 453 break; 454 455 case SEPARATEGROUPS: 456 // This is going to be just like no-groups mode, only we 'll filter 457 // out the grades from people not in our group. 458 if (!isloggedin()) { 459 // Not logged in, so show nothing. 460 return $this->content; 461 } 462 463 $mygroups = groups_get_all_groups($courseid, $USER->id); 464 if (empty($mygroups)) { 465 // Not member of a group, show nothing. 466 return $this->content; 467 } 468 469 // Get users from the same groups as me. 470 list($grouptest, $params) = $DB->get_in_or_equal(array_keys($mygroups)); 471 $mygroupsusers = $DB->get_records_sql_menu( 472 'SELECT DISTINCT userid, 1 FROM {groups_members} WHERE groupid ' . $grouptest, 473 $params); 474 475 // Filter out the grades belonging to other users, and proceed as if there were no groups. 476 foreach ($grades as $key => $grade) { 477 if (!isset($mygroupsusers[$grade->userid])) { 478 unset($grades[$key]); 479 } 480 } 481 482 // No break, fall through to the default case now we have filtered the $grades array. 483 default: 484 case NOGROUPS: 485 // Single user mode. 486 $numbest = empty($this->config->showbest) ? 0 : min($this->config->showbest, count($grades)); 487 $numworst = empty($this->config->showworst) ? 0 : min($this->config->showworst, count($grades) - $numbest); 488 489 // Collect all the usernames we are going to need. 490 $remaining = $numbest; 491 $grade = end($grades); 492 while ($remaining--) { 493 $best[$grade->userid] = $grade->id; 494 $grade = prev($grades); 495 } 496 497 $remaining = $numworst; 498 $grade = reset($grades); 499 while ($remaining--) { 500 $worst[$grade->userid] = $grade->id; 501 $grade = next($grades); 502 } 503 504 if (empty($best) && empty($worst)) { 505 // Nothing to show, for some reason... 506 return $this->content; 507 } 508 509 // Now grab all the users from the database. 510 $userids = array_merge(array_keys($best), array_keys($worst)); 511 $fields = array_merge(array('id', 'idnumber'), \core_user\fields::get_name_fields()); 512 $fields = implode(',', $fields); 513 $users = $DB->get_records_list('user', 'id', $userids, '', $fields); 514 515 // If configured to view user idnumber, ensure current user can see it. 516 $extrafields = \core_user\fields::for_identity($this->context)->get_required_fields(); 517 $canviewidnumber = (array_search('idnumber', $extrafields) !== false); 518 519 // Ready for output! 520 if ($activity->gradetype == GRADE_TYPE_SCALE) { 521 // We must display the results using scales. 522 $gradeformat = B_ACTIVITYRESULTS_GRADE_FORMAT_SCALE; 523 // Preload the scale. 524 $scale = $this->get_scale($activity->scaleid); 525 } else if (intval(empty($this->config->gradeformat))) { 526 $gradeformat = B_ACTIVITYRESULTS_GRADE_FORMAT_PCT; 527 } else { 528 $gradeformat = $this->config->gradeformat; 529 } 530 531 // Generate the header. 532 $this->content->text .= $this->activity_link($activity, $cm); 533 534 $rank = 0; 535 if (!empty($best)) { 536 $this->content->text .= '<table class="grades"><caption class="pb-0"><h6>'; 537 if ($numbest == 1) { 538 $this->content->text .= get_string('bestgrade', 'block_activity_results'); 539 } else { 540 $this->content->text .= get_string('bestgrades', 'block_activity_results', $numbest); 541 } 542 $this->content->text .= '</h6></caption><colgroup class="number" />'; 543 $this->content->text .= '<colgroup class="name" /><colgroup class="grade" /><tbody>'; 544 545 foreach ($best as $userid => $gradeid) { 546 switch ($nameformat) { 547 case B_ACTIVITYRESULTS_NAME_FORMAT_ID: 548 $thisname = get_string('user'); 549 if ($canviewidnumber) { 550 $thisname .= ' ' . s($users[$userid]->idnumber); 551 } 552 break; 553 case B_ACTIVITYRESULTS_NAME_FORMAT_ANON: 554 $thisname = get_string('user'); 555 break; 556 default: 557 case B_ACTIVITYRESULTS_NAME_FORMAT_FULL: 558 if (has_capability('moodle/user:viewdetails', $context)) { 559 $thisname = html_writer::link(new moodle_url('/user/view.php', 560 array('id' => $userid, 'course' => $courseid)), fullname($users[$userid])); 561 } else { 562 $thisname = fullname($users[$userid]); 563 } 564 break; 565 } 566 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 567 switch ($gradeformat) { 568 case B_ACTIVITYRESULTS_GRADE_FORMAT_SCALE: 569 // Round answer up and locate appropriate scale. 570 $answer = (round($grades[$gradeid]->finalgrade, 0, PHP_ROUND_HALF_UP) - 1); 571 if (isset($scale[$answer])) { 572 $this->content->text .= $scale[$answer]; 573 } else { 574 // Value is not in the scale. 575 $this->content->text .= get_string('unknown', 'block_activity_results'); 576 } 577 break; 578 case B_ACTIVITYRESULTS_GRADE_FORMAT_FRA: 579 $this->content->text .= $this->activity_format_grade($grades[$gradeid]->finalgrade); 580 $this->content->text .= '/'.$this->activity_format_grade($activity->grademax); 581 break; 582 case B_ACTIVITYRESULTS_GRADE_FORMAT_ABS: 583 $this->content->text .= $this->activity_format_grade($grades[$gradeid]->finalgrade); 584 break; 585 default: 586 case B_ACTIVITYRESULTS_GRADE_FORMAT_PCT: 587 if ($activity->grademax) { 588 $this->content->text .= $this->activity_format_grade((float)$grades[$gradeid]->finalgrade / 589 (float)$activity->grademax * 100).'%'; 590 } else { 591 $this->content->text .= '--%'; 592 } 593 break; 594 } 595 $this->content->text .= '</td></tr>'; 596 } 597 $this->content->text .= '</tbody></table>'; 598 } 599 600 $rank = 0; 601 if (!empty($worst)) { 602 $worst = array_reverse($worst, true); 603 $this->content->text .= '<table class="grades"><caption class="pb-0"><h6>'; 604 if ($numbest == 1) { 605 $this->content->text .= get_string('worstgrade', 'block_activity_results'); 606 } else { 607 $this->content->text .= get_string('worstgrades', 'block_activity_results', $numworst); 608 } 609 $this->content->text .= '</h6></caption><colgroup class="number" />'; 610 $this->content->text .= '<colgroup class="name" /><colgroup class="grade" /><tbody>'; 611 foreach ($worst as $userid => $gradeid) { 612 switch ($nameformat) { 613 case B_ACTIVITYRESULTS_NAME_FORMAT_ID: 614 $thisname = get_string('user'); 615 if ($canviewidnumber) { 616 $thisname .= ' ' . s($users[$userid]->idnumber); 617 }; 618 break; 619 case B_ACTIVITYRESULTS_NAME_FORMAT_ANON: 620 $thisname = get_string('user'); 621 break; 622 default: 623 case B_ACTIVITYRESULTS_NAME_FORMAT_FULL: 624 if (has_capability('moodle/user:viewdetails', $context)) { 625 $thisname = html_writer::link(new moodle_url('/user/view.php', 626 array('id' => $userid, 'course' => $courseid)), fullname($users[$userid])); 627 } else { 628 $thisname = fullname($users[$userid]); 629 } 630 break; 631 } 632 $this->content->text .= '<tr><td>'.(++$rank).'.</td><td>'.$thisname.'</td><td>'; 633 switch ($gradeformat) { 634 case B_ACTIVITYRESULTS_GRADE_FORMAT_SCALE: 635 // Round answer up and locate appropriate scale. 636 $answer = (round($grades[$gradeid]->finalgrade, 0, PHP_ROUND_HALF_UP) - 1); 637 if (isset($scale[$answer])) { 638 $this->content->text .= $scale[$answer]; 639 } else { 640 // Value is not in the scale. 641 $this->content->text .= get_string('unknown', 'block_activity_results'); 642 } 643 break; 644 case B_ACTIVITYRESULTS_GRADE_FORMAT_FRA: 645 $this->content->text .= $this->activity_format_grade($grades[$gradeid]->finalgrade); 646 $this->content->text .= '/'.$this->activity_format_grade($activity->grademax); 647 break; 648 case B_ACTIVITYRESULTS_GRADE_FORMAT_ABS: 649 $this->content->text .= $this->activity_format_grade($grades[$gradeid]->finalgrade); 650 break; 651 default: 652 case B_ACTIVITYRESULTS_GRADE_FORMAT_PCT: 653 if ($activity->grademax) { 654 $this->content->text .= $this->activity_format_grade((float)$grades[$gradeid]->finalgrade / 655 (float)$activity->grademax * 100).'%'; 656 } else { 657 $this->content->text .= '--%'; 658 } 659 break; 660 } 661 $this->content->text .= '</td></tr>'; 662 } 663 $this->content->text .= '</tbody></table>'; 664 } 665 break; 666 } 667 668 return $this->content; 669 } 670 671 /** 672 * Allows the block to be added multiple times to a single page 673 * @return boolean 674 */ 675 public function instance_allow_multiple() { 676 return true; 677 } 678 679 /** 680 * Formats the grade to the specified decimal points 681 * @param float $grade 682 * @return string 683 */ 684 private function activity_format_grade($grade) { 685 if (is_null($grade)) { 686 return get_string('notyetgraded', 'block_activity_results'); 687 } 688 return format_float($grade, $this->config->decimalpoints); 689 } 690 691 /** 692 * Generates the Link to the activity module when displayed outside of the module. 693 * @param stdclass $activity 694 * @param stdclass $cm 695 * @return string 696 */ 697 private function activity_link($activity, $cm) { 698 699 $o = html_writer::start_tag('h5'); 700 $o .= html_writer::link(new moodle_url('/mod/'.$activity->itemmodule.'/view.php', 701 array('id' => $cm->id)), format_string(($activity->itemname), true, ['context' => context_module::instance($cm->id)])); 702 $o .= html_writer::end_tag('h5'); 703 return $o; 704 } 705 706 /** 707 * Generates a numeric array of scale entries 708 * @param int $scaleid 709 * @return array 710 */ 711 private function get_scale($scaleid) { 712 global $DB; 713 $scaletext = $DB->get_field('scale', 'scale', array('id' => $scaleid), IGNORE_MISSING); 714 $scale = explode ( ',', $scaletext); 715 return $scale; 716 717 } 718 719 /** 720 * Return the plugin config settings for external functions. 721 * 722 * @return stdClass the configs for both the block instance and plugin 723 * @since Moodle 3.8 724 */ 725 public function get_config_for_external() { 726 // Return all settings for all users since it is safe (no private keys, etc..). 727 $instanceconfigs = !empty($this->config) ? $this->config : new stdClass(); 728 $pluginconfigs = get_config('block_activity_results'); 729 730 return (object) [ 731 'instance' => $instanceconfigs, 732 'plugin' => $pluginconfigs, 733 ]; 734 } 735 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body