Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   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   * Grade history report test.
  19   *
  20   * @package    gradereport_history
  21   * @copyright  2014 Frédéric Massart - FMCorz.net
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  /**
  28   * Grade history report test class.
  29   *
  30   * @package    gradereport_history
  31   * @copyright  2014 Frédéric Massart - FMCorz.net
  32   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class gradereport_history_report_testcase extends advanced_testcase {
  35  
  36      /**
  37       * Create some grades.
  38       */
  39      public function test_query_db() {
  40          $this->resetAfterTest();
  41  
  42          // Making the setup.
  43          $c1 = $this->getDataGenerator()->create_course();
  44          $c2 = $this->getDataGenerator()->create_course();
  45          $c1ctx = context_course::instance($c1->id);
  46          $c2ctx = context_course::instance($c2->id);
  47  
  48          // Users.
  49          $u1 = $this->getDataGenerator()->create_user();
  50          $u2 = $this->getDataGenerator()->create_user();
  51          $u3 = $this->getDataGenerator()->create_user();
  52          $u4 = $this->getDataGenerator()->create_user();
  53          $u5 = $this->getDataGenerator()->create_user();
  54          $grader1 = $this->getDataGenerator()->create_user();
  55          $grader2 = $this->getDataGenerator()->create_user();
  56          self::getDataGenerator()->enrol_user($grader1->id, $c1->id, 'teacher');
  57          self::getDataGenerator()->enrol_user($grader2->id, $c1->id, 'teacher');
  58          self::getDataGenerator()->enrol_user($u2->id, $c1->id, 'student');
  59          self::getDataGenerator()->enrol_user($u3->id, $c1->id, 'student');
  60          self::getDataGenerator()->enrol_user($u4->id, $c1->id, 'student');
  61          self::getDataGenerator()->enrol_user($u5->id, $c1->id, 'student');
  62  
  63          // Modules.
  64          $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
  65          $c1m2 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
  66          $c1m3 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
  67          $c2m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c2));
  68          $c2m2 = $this->getDataGenerator()->create_module('assign', array('course' => $c2));
  69  
  70          // Creating fake history data.
  71          $giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign');
  72          $grades = array();
  73  
  74          $this->setUser($grader1);
  75  
  76          $gi = grade_item::fetch($giparams + array('iteminstance' => $c1m1->id));
  77          $grades['c1m1u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
  78                  'timemodified' => time() - 3600));
  79          $grades['c1m1u2'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id,
  80                  'timemodified' => time() + 3600));
  81          $grades['c1m1u3'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id));
  82          $grades['c1m1u4'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id));
  83          $grades['c1m1u5'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id));
  84  
  85          $gi = grade_item::fetch($giparams + array('iteminstance' => $c1m2->id));
  86          $grades['c1m2u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id));
  87          $grades['c1m2u2'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id));
  88  
  89          $gi = grade_item::fetch($giparams + array('iteminstance' => $c1m3->id));
  90          $grades['c1m3u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id));
  91  
  92          $gi = grade_item::fetch($giparams + array('iteminstance' => $c2m1->id));
  93          $grades['c2m1u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
  94              'usermodified' => $grader1->id));
  95          $grades['c2m1u2'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id,
  96              'usermodified' => $grader1->id));
  97          $grades['c2m1u3'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id,
  98              'usermodified' => $grader1->id));
  99          $grades['c2m1u4'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id,
 100              'usermodified' => $grader2->id));
 101  
 102          // Histories where grades have not been revised..
 103          $grades['c2m1u5a'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id,
 104              'timemodified' => time() - 60));
 105          $grades['c2m1u5b'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id,
 106              'timemodified' => time()));
 107          $grades['c2m1u5c'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id,
 108              'timemodified' => time() + 60));
 109  
 110          // Histories where grades have been revised and not revised.
 111          $now = time();
 112          $gi = grade_item::fetch($giparams + array('iteminstance' => $c2m2->id));
 113          $grades['c2m2u1a'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
 114              'timemodified' => $now - 60, 'finalgrade' => 50));
 115          $grades['c2m2u1b'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
 116              'timemodified' => $now - 50, 'finalgrade' => 50));      // Not revised.
 117          $grades['c2m2u1c'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
 118              'timemodified' => $now, 'finalgrade' => 75));
 119          $grades['c2m2u1d'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
 120              'timemodified' => $now + 10, 'finalgrade' => 75));      // Not revised.
 121          $grades['c2m2u1e'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
 122              'timemodified' => $now + 60, 'finalgrade' => 25));
 123          $grades['c2m2u1f'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id,
 124              'timemodified' => $now + 70, 'finalgrade' => 25));      // Not revised.
 125  
 126          // TODO MDL-46736 Handle deleted/non-existing grade items.
 127          // Histories with missing grade items, considered as deleted.
 128          // $grades['c2x1u5'] = $this->create_grade_history($giparams + array('itemid' => -1, 'userid' => $u5->id, 'courseid' => $c1->id));
 129          // $grades['c2x2u5'] = $this->create_grade_history($giparams + array('itemid' => 999999, 'userid' => $u5->id, 'courseid' => $c1->id));
 130  
 131          // Basic filtering based on course id.
 132          $this->assertEquals(8, $this->get_tablelog_results($c1ctx, array(), true));
 133          $this->assertEquals(13, $this->get_tablelog_results($c2ctx, array(), true));
 134  
 135          // Filtering on 1 user.
 136          $this->assertEquals(3, $this->get_tablelog_results($c1ctx, array('userids' => $u1->id), true));
 137  
 138          // Filtering on more users.
 139          $this->assertEquals(4, $this->get_tablelog_results($c1ctx, array('userids' => "$u1->id,$u3->id"), true));
 140  
 141          // Filtering based on one grade item.
 142          $gi = grade_item::fetch($giparams + array('iteminstance' => $c1m1->id));
 143          $this->assertEquals(5, $this->get_tablelog_results($c1ctx, array('itemid' => $gi->id), true));
 144          $gi = grade_item::fetch($giparams + array('iteminstance' => $c1m3->id));
 145          $this->assertEquals(1, $this->get_tablelog_results($c1ctx, array('itemid' => $gi->id), true));
 146  
 147          // Filtering based on the grader.
 148          $this->assertEquals(3, $this->get_tablelog_results($c2ctx, array('grader' => $grader1->id), true));
 149          $this->assertEquals(1, $this->get_tablelog_results($c2ctx, array('grader' => $grader2->id), true));
 150  
 151          // Filtering based on date.
 152          $results = $this->get_tablelog_results($c1ctx, array('datefrom' => time() + 1800));
 153          $this->assertGradeHistoryIds(array($grades['c1m1u2']->id), $results);
 154          $results = $this->get_tablelog_results($c1ctx, array('datetill' => time() - 1800));
 155          $this->assertGradeHistoryIds(array($grades['c1m1u1']->id), $results);
 156          $results = $this->get_tablelog_results($c1ctx, array('datefrom' => time() - 1800, 'datetill' => time() + 1800));
 157          $this->assertGradeHistoryIds(array($grades['c1m1u3']->id, $grades['c1m1u4']->id, $grades['c1m1u5']->id,
 158              $grades['c1m2u1']->id, $grades['c1m2u2']->id, $grades['c1m3u1']->id), $results);
 159  
 160          // Filtering based on revised only.
 161          $this->assertEquals(3, $this->get_tablelog_results($c2ctx, array('userids' => $u5->id), true));
 162          $this->assertEquals(1, $this->get_tablelog_results($c2ctx, array('userids' => $u5->id, 'revisedonly' => true), true));
 163  
 164          // More filtering based on revised only.
 165          $gi = grade_item::fetch($giparams + array('iteminstance' => $c2m2->id));
 166          $this->assertEquals(6, $this->get_tablelog_results($c2ctx, array('userids' => $u1->id, 'itemid' => $gi->id), true));
 167          $results = $this->get_tablelog_results($c2ctx, array('userids' => $u1->id, 'itemid' => $gi->id, 'revisedonly' => true));
 168          $this->assertGradeHistoryIds(array($grades['c2m2u1a']->id, $grades['c2m2u1c']->id, $grades['c2m2u1e']->id), $results);
 169  
 170          // Checking the value of the previous grade.
 171          $this->assertEquals(null, $results[$grades['c2m2u1a']->id]->prevgrade);
 172          $this->assertEquals($grades['c2m2u1a']->finalgrade, $results[$grades['c2m2u1c']->id]->prevgrade);
 173          $this->assertEquals($grades['c2m2u1c']->finalgrade, $results[$grades['c2m2u1e']->id]->prevgrade);
 174  
 175          // Put course in separate groups mode, add grader1 and two students to the same group.
 176          $c1->groupmode = SEPARATEGROUPS;
 177          update_course($c1);
 178          $this->assertFalse(has_capability('moodle/site:accessallgroups', \context_course::instance($c1->id)));
 179          $g1 = self::getDataGenerator()->create_group(['courseid' => $c1->id, 'name' => 'g1']);
 180          self::getDataGenerator()->create_group_member(['groupid' => $g1->id, 'userid' => $grader1->id]);
 181          self::getDataGenerator()->create_group_member(['groupid' => $g1->id, 'userid' => $u1->id]);
 182          self::getDataGenerator()->create_group_member(['groupid' => $g1->id, 'userid' => $u2->id]);
 183          $this->assertEquals(2, $this->get_tablelog_results($c1ctx, array(), true));
 184  
 185          // Grader2 is not in any groups.
 186          $this->setUser($grader2);
 187          $this->assertEquals(0, $this->get_tablelog_results($c1ctx, array(), true));
 188      }
 189  
 190      /**
 191       * Test the get users helper method.
 192       */
 193      public function test_get_users() {
 194          $this->resetAfterTest();
 195  
 196          // Making the setup.
 197          $c1 = $this->getDataGenerator()->create_course();
 198          $c2 = $this->getDataGenerator()->create_course();
 199          $c1ctx = context_course::instance($c1->id);
 200          $c2ctx = context_course::instance($c2->id);
 201  
 202          $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
 203          $c2m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c2));
 204  
 205          // Users.
 206          $u1 = $this->getDataGenerator()->create_user(array('firstname' => 'Eric', 'lastname' => 'Cartman'));
 207          $u2 = $this->getDataGenerator()->create_user(array('firstname' => 'Stan', 'lastname' => 'Marsh'));
 208          $u3 = $this->getDataGenerator()->create_user(array('firstname' => 'Kyle', 'lastname' => 'Broflovski'));
 209          $u4 = $this->getDataGenerator()->create_user(array('firstname' => 'Kenny', 'lastname' => 'McCormick'));
 210  
 211          // Creating grade history for some users.
 212          $gi = grade_item::fetch(array('iteminstance' => $c1m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
 213          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id));
 214          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id));
 215          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id));
 216  
 217          $gi = grade_item::fetch(array('iteminstance' => $c2m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
 218          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id));
 219  
 220          // Checking fetching some users.
 221          $users = \gradereport_history\helper::get_users($c1ctx);
 222          $this->assertCount(3, $users);
 223          $this->assertArrayHasKey($u3->id, $users);
 224          $users = \gradereport_history\helper::get_users($c2ctx);
 225          $this->assertCount(1, $users);
 226          $this->assertArrayHasKey($u4->id, $users);
 227          $users = \gradereport_history\helper::get_users($c1ctx, 'c');
 228          $this->assertCount(1, $users);
 229          $this->assertArrayHasKey($u1->id, $users);
 230          $users = \gradereport_history\helper::get_users($c1ctx, '', 0, 2);
 231          $this->assertCount(2, $users);
 232          $this->assertArrayHasKey($u3->id, $users);
 233          $this->assertArrayHasKey($u1->id, $users);
 234          $users = \gradereport_history\helper::get_users($c1ctx, '', 1, 2);
 235          $this->assertCount(1, $users);
 236          $this->assertArrayHasKey($u2->id, $users);
 237  
 238          // Checking the count of users.
 239          $this->assertEquals(3, \gradereport_history\helper::get_users_count($c1ctx));
 240          $this->assertEquals(1, \gradereport_history\helper::get_users_count($c2ctx));
 241          $this->assertEquals(1, \gradereport_history\helper::get_users_count($c1ctx, 'c'));
 242      }
 243  
 244      /**
 245       * Data provider method for \gradereport_history_report_testcase::test_get_users_with_groups()
 246       */
 247      public function get_users_provider() {
 248          return [
 249              'Visible groups, non-editing teacher, not in any group' => [
 250                  VISIBLEGROUPS, 'teacher', ['g1', 'g2'], ['s1', 's2', 's3', 's4', 's5']
 251              ],
 252              'Visible groups, non-editing teacher' => [
 253                  VISIBLEGROUPS, 'teacher', [], ['s1', 's2', 's3', 's4', 's5']
 254              ],
 255              'Visible groups, editing teacher' => [
 256                  VISIBLEGROUPS, 'editingteacher', ['g1', 'g2'], ['s1', 's2', 's3', 's4', 's5']
 257              ],
 258              'Separate groups, non-editing teacher' => [
 259                  SEPARATEGROUPS, 'teacher', ['g1', 'g2'], ['s1', 's2']
 260              ],
 261              'Separate groups, non-editing teacher, not in any group' => [
 262                  SEPARATEGROUPS, 'teacher', [], []
 263              ],
 264              'Separate groups, non-editing teacher and student share two groups' => [
 265                  SEPARATEGROUPS, 'teacher', ['g4', 'g5'], ['s5']
 266              ],
 267              'Separate groups, editing teacher' => [
 268                  SEPARATEGROUPS, 'editingteacher', ['g1', 'g2'], ['s1', 's2', 's3', 's4', 's5']
 269              ],
 270          ];
 271      }
 272  
 273      /**
 274       * Test for helper::get_users() with course group mode set.
 275       *
 276       * @dataProvider get_users_provider
 277       * @param $groupmode
 278       * @param $teacherrole
 279       * @param $teachergroups
 280       * @param $expectedusers
 281       */
 282      public function test_get_users_with_groups($groupmode, $teacherrole, $teachergroups, $expectedusers) {
 283          global $DB;
 284          $this->resetAfterTest();
 285  
 286          $generator = $this->getDataGenerator();
 287  
 288          // Create a test course.
 289          $course = $generator->create_course(['groupmode' => $groupmode]);
 290  
 291          // Create an assignment module.
 292          $assign = $generator->create_module('assign', ['course' => $course]);
 293  
 294          // Fetch roles.
 295          $role = $DB->get_record('role', ['shortname' => $teacherrole], '*', MUST_EXIST);
 296          $studentrole =  $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST);
 297  
 298          // Create users.
 299          $t1 = $generator->create_user(['username' => 't1', 'email' => 't1@example.com']);
 300          $s1 = $generator->create_user(['username' => 's1', 'email' => 's1@example.com']);
 301          $s2 = $generator->create_user(['username' => 's2', 'email' => 's2@example.com']);
 302          $s3 = $generator->create_user(['username' => 's3', 'email' => 's3@example.com']);
 303          $s4 = $generator->create_user(['username' => 's4', 'email' => 's4@example.com']);
 304          $s5 = $generator->create_user(['username' => 's5', 'email' => 's5@example.com']);
 305  
 306          // Enrol users.
 307          $generator->enrol_user($t1->id, $course->id, $role->id);
 308          $generator->enrol_user($s1->id, $course->id, $studentrole->id);
 309          $generator->enrol_user($s2->id, $course->id, $studentrole->id);
 310          $generator->enrol_user($s3->id, $course->id, $studentrole->id);
 311          $generator->enrol_user($s4->id, $course->id, $studentrole->id);
 312          $generator->enrol_user($s5->id, $course->id, $studentrole->id);
 313  
 314          // Create groups.
 315          $groups = [];
 316          $groups['g1'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g1']);
 317          $groups['g2'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g2']);
 318          $groups['g3'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g3']);
 319          $groups['g4'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g4']);
 320          $groups['g5'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g5']);
 321  
 322          // Add teacher to the assigned groups.
 323          foreach ($teachergroups as $groupname) {
 324              $group = $groups[$groupname];
 325              $generator->create_group_member(['groupid' => $group->id, 'userid' => $t1->id]);
 326          }
 327  
 328          // Add students to groups.
 329          $generator->create_group_member(['groupid' => $groups['g1']->id, 'userid' => $s1->id]);
 330          $generator->create_group_member(['groupid' => $groups['g2']->id, 'userid' => $s2->id]);
 331          $generator->create_group_member(['groupid' => $groups['g3']->id, 'userid' => $s3->id]);
 332          $generator->create_group_member(['groupid' => $groups['g4']->id, 'userid' => $s5->id]);
 333          $generator->create_group_member(['groupid' => $groups['g5']->id, 'userid' => $s5->id]);
 334  
 335          // Creating grade history for the students.
 336          $gi = grade_item::fetch(['iteminstance' => $assign->id, 'itemtype' => 'mod', 'itemmodule' => 'assign']);
 337          $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s1->id]);
 338          $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s2->id]);
 339          $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s3->id]);
 340          $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s4->id]);
 341          $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s5->id]);
 342  
 343          // Log in as the teacher.
 344          $this->setUser($t1);
 345  
 346          // Fetch the users.
 347          $users = \gradereport_history\helper::get_users(context_course::instance($course->id));
 348          // Confirm that the number of users fetched is the same as the count of expected users.
 349          $this->assertCount(count($expectedusers), $users);
 350          foreach ($users as $user) {
 351              // Confirm that each user returned is in the list of expected users.
 352              $this->assertTrue(in_array($user->username, $expectedusers));
 353          }
 354      }
 355  
 356      /**
 357       * Test the get graders helper method.
 358       */
 359      public function test_graders() {
 360          $this->resetAfterTest();
 361  
 362          // Making the setup.
 363          $c1 = $this->getDataGenerator()->create_course();
 364          $c2 = $this->getDataGenerator()->create_course();
 365          $c3 = $this->getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS]);
 366  
 367          $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1));
 368          $c2m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c2));
 369          $c3m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c3));
 370  
 371          // Users.
 372          $u1 = $this->getDataGenerator()->create_user(array('firstname' => 'Eric', 'lastname' => 'Cartman'));
 373          $u2 = $this->getDataGenerator()->create_user(array('firstname' => 'Stan', 'lastname' => 'Marsh'));
 374          $u3 = $this->getDataGenerator()->create_user(array('firstname' => 'Kyle', 'lastname' => 'Broflovski'));
 375          $u4 = $this->getDataGenerator()->create_user(array('firstname' => 'Kenny', 'lastname' => 'McCormick'));
 376  
 377          foreach ([$c1, $c2, $c3] as $course) {
 378              foreach ([$u1, $u2, $u3, $u4] as $user) {
 379                  self::getDataGenerator()->enrol_user($user->id, $course->id, 'student');
 380              }
 381          }
 382  
 383          // Creating grade history for some users.
 384          $gi = grade_item::fetch(array('iteminstance' => $c1m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
 385          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u1->id));
 386          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u2->id));
 387          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u3->id));
 388  
 389          $gi = grade_item::fetch(array('iteminstance' => $c2m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
 390          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u4->id));
 391  
 392          $gi = grade_item::fetch(array('iteminstance' => $c3m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign'));
 393          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u1->id));
 394          $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id, 'usermodified' => $u2->id));
 395  
 396          // Checking fetching some users.
 397          $graders = \gradereport_history\helper::get_graders($c1->id);
 398          $this->assertCount(4, $graders); // Including "all graders" .
 399          $this->assertArrayHasKey($u1->id, $graders);
 400          $this->assertArrayHasKey($u2->id, $graders);
 401          $this->assertArrayHasKey($u3->id, $graders);
 402          $graders = \gradereport_history\helper::get_graders($c2->id);
 403          $this->assertCount(2, $graders); // Including "all graders" .
 404          $this->assertArrayHasKey($u4->id, $graders);
 405  
 406          // Third course is in separate groups mode. Only graders from the same group will be returned.
 407          $g = self::getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'g1']);
 408          self::getDataGenerator()->create_group_member(['groupid' => $g->id, 'userid' => $u1->id]);
 409          self::getDataGenerator()->create_group_member(['groupid' => $g->id, 'userid' => $u2->id]);
 410          $this->setUser($u1);
 411          $graders = \gradereport_history\helper::get_graders($c3->id);
 412          $this->assertCount(3, $graders); // Including "all graders" .
 413          $this->setUser($u3);
 414          $graders = \gradereport_history\helper::get_graders($c3->id);
 415          $this->assertCount(1, $graders); // Including "all graders" .
 416      }
 417  
 418      /**
 419       * Asserts that the array of grade objects contains exactly the right IDs.
 420       *
 421       * @param array $expectedids Array of expected IDs.
 422       * @param array $objects Array of objects returned by the table.
 423       */
 424      protected function assertGradeHistoryIds(array $expectedids, array $objects) {
 425          $this->assertCount(count($expectedids), $objects);
 426          $expectedids = array_flip($expectedids);
 427          foreach ($objects as $object) {
 428              $this->assertArrayHasKey($object->id, $expectedids);
 429              unset($expectedids[$object->id]);
 430          }
 431          $this->assertCount(0, $expectedids);
 432      }
 433  
 434      /**
 435       * Create a new grade history entry.
 436       *
 437       * @param array $params Of values.
 438       * @return object The grade object.
 439       */
 440      protected function create_grade_history($params) {
 441          global $DB;
 442          $params = (array) $params;
 443  
 444          if (!isset($params['itemid'])) {
 445              throw new coding_exception('Missing itemid key.');
 446          }
 447          if (!isset($params['userid'])) {
 448              throw new coding_exception('Missing userid key.');
 449          }
 450  
 451          // Default object.
 452          $grade = new stdClass();
 453          $grade->itemid = 0;
 454          $grade->userid = 0;
 455          $grade->oldid = 123;
 456          $grade->rawgrade = 50;
 457          $grade->finalgrade = 50;
 458          $grade->timecreated = time();
 459          $grade->timemodified = time();
 460          $grade->information = '';
 461          $grade->informationformat = FORMAT_PLAIN;
 462          $grade->feedback = '';
 463          $grade->feedbackformat = FORMAT_PLAIN;
 464          $grade->usermodified = 2;
 465  
 466          // Merge with data passed.
 467          $grade = (object) array_merge((array) $grade, $params);
 468  
 469          // Insert record.
 470          $grade->id = $DB->insert_record('grade_grades_history', $grade);
 471  
 472          return $grade;
 473      }
 474  
 475      /**
 476       * Returns a table log object.
 477       *
 478       * @param context_course $coursecontext The course context.
 479       * @param array $filters An array of filters.
 480       * @param boolean $count When true, returns a count rather than an array of objects.
 481       * @return mixed Count or array of objects.
 482       */
 483      protected function get_tablelog_results($coursecontext, $filters = array(), $count = false) {
 484          $table = new gradereport_history_tests_tablelog('something', $coursecontext, new moodle_url(''), $filters);
 485          return $table->get_test_results($count);
 486      }
 487  
 488  }
 489  
 490  /**
 491   * Extended table log class.
 492   */
 493  class gradereport_history_tests_tablelog extends \gradereport_history\output\tablelog {
 494  
 495      /**
 496       * Get the test results.
 497       *
 498       * @param boolean $count Whether or not we want the count.
 499       * @return mixed Count or array of objects.
 500       */
 501      public function get_test_results($count = false) {
 502          global $DB;
 503          if ($count) {
 504              list($sql, $params) = $this->get_sql_and_params(true);
 505              return $DB->count_records_sql($sql, $params);
 506          } else {
 507              $this->setup();
 508              list($sql, $params) = $this->get_sql_and_params();
 509              return $DB->get_records_sql($sql, $params);
 510          }
 511      }
 512  
 513  }