[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/blocks/quiz_results/ -> block_quiz_results.php (source)

   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.'&amp;group=';
 241                  } else if (has_capability('moodle/course:viewparticipants', $context)) {
 242                      $grouplink = $CFG->wwwroot.'/user/index.php?id='.$courseid.'&amp;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.'&amp;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.'&amp;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.'&amp;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  


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1