Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402]
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 namespace gradereport_history; 18 19 defined('MOODLE_INTERNAL') || die(); 20 21 /** 22 * Grade history report test class. 23 * 24 * @package gradereport_history 25 * @copyright 2014 Frédéric Massart - FMCorz.net 26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 */ 28 class report_test extends \advanced_testcase { 29 30 /** 31 * Create some grades. 32 */ 33 public function test_query_db() { 34 $this->resetAfterTest(); 35 36 // Making the setup. 37 $c1 = $this->getDataGenerator()->create_course(); 38 $c2 = $this->getDataGenerator()->create_course(); 39 $c1ctx = \context_course::instance($c1->id); 40 $c2ctx = \context_course::instance($c2->id); 41 42 // Users. 43 $u1 = $this->getDataGenerator()->create_user(); 44 $u2 = $this->getDataGenerator()->create_user(); 45 $u3 = $this->getDataGenerator()->create_user(); 46 $u4 = $this->getDataGenerator()->create_user(); 47 $u5 = $this->getDataGenerator()->create_user(); 48 $grader1 = $this->getDataGenerator()->create_user(); 49 $grader2 = $this->getDataGenerator()->create_user(); 50 self::getDataGenerator()->enrol_user($grader1->id, $c1->id, 'teacher'); 51 self::getDataGenerator()->enrol_user($grader2->id, $c1->id, 'teacher'); 52 self::getDataGenerator()->enrol_user($u2->id, $c1->id, 'student'); 53 self::getDataGenerator()->enrol_user($u3->id, $c1->id, 'student'); 54 self::getDataGenerator()->enrol_user($u4->id, $c1->id, 'student'); 55 self::getDataGenerator()->enrol_user($u5->id, $c1->id, 'student'); 56 57 self::getDataGenerator()->enrol_user($grader1->id, $c2->id, 'teacher'); 58 self::getDataGenerator()->enrol_user($u5->id, $c2->id, 'student'); 59 60 // Modules. 61 $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1)); 62 $c1m2 = $this->getDataGenerator()->create_module('assign', array('course' => $c1)); 63 $c1m3 = $this->getDataGenerator()->create_module('assign', array('course' => $c1)); 64 $c2m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c2)); 65 $c2m2 = $this->getDataGenerator()->create_module('assign', array('course' => $c2)); 66 67 // Creating fake history data. 68 $giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign'); 69 $grades = array(); 70 71 $this->setUser($grader1); 72 73 $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m1->id)); 74 $grades['c1m1u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 75 'timemodified' => time() - 3600)); 76 $grades['c1m1u2'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id, 77 'timemodified' => time() + 3600)); 78 $grades['c1m1u3'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id)); 79 $grades['c1m1u4'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id)); 80 $grades['c1m1u5'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id)); 81 82 $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m2->id)); 83 $grades['c1m2u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id)); 84 $grades['c1m2u2'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id)); 85 86 $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m3->id)); 87 $grades['c1m3u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id)); 88 89 $gi = \grade_item::fetch($giparams + array('iteminstance' => $c2m1->id)); 90 $grades['c2m1u1'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 91 'usermodified' => $grader1->id)); 92 $grades['c2m1u2'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id, 93 'usermodified' => $grader1->id)); 94 $grades['c2m1u3'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id, 95 'usermodified' => $grader1->id)); 96 $grades['c2m1u4'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id, 97 'usermodified' => $grader2->id)); 98 99 // Histories where grades have not been revised.. 100 $grades['c2m1u5a'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id, 101 'timemodified' => time() - 60)); 102 $grades['c2m1u5b'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id, 103 'timemodified' => time())); 104 $grades['c2m1u5c'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u5->id, 105 'timemodified' => time() + 60)); 106 107 // Histories where grades have been revised and not revised. 108 $now = time(); 109 $gi = \grade_item::fetch($giparams + array('iteminstance' => $c2m2->id)); 110 $grades['c2m2u1a'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 111 'timemodified' => $now - 60, 'finalgrade' => 50)); 112 $grades['c2m2u1b'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 113 'timemodified' => $now - 50, 'finalgrade' => 50)); // Not revised. 114 $grades['c2m2u1c'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 115 'timemodified' => $now, 'finalgrade' => 75)); 116 $grades['c2m2u1d'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 117 'timemodified' => $now + 10, 'finalgrade' => 75)); // Not revised. 118 $grades['c2m2u1e'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 119 'timemodified' => $now + 60, 'finalgrade' => 25)); 120 $grades['c2m2u1f'] = $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 121 'timemodified' => $now + 70, 'finalgrade' => 25)); // Not revised. 122 123 // TODO MDL-46736 Handle deleted/non-existing grade items. 124 // Histories with missing grade items, considered as deleted. 125 // $grades['c2x1u5'] = $this->create_grade_history($giparams + array('itemid' => -1, 'userid' => $u5->id, 'courseid' => $c1->id)); 126 // $grades['c2x2u5'] = $this->create_grade_history($giparams + array('itemid' => 999999, 'userid' => $u5->id, 'courseid' => $c1->id)); 127 128 // Basic filtering based on course id. 129 $this->assertEquals(8, $this->get_tablelog_results($c1ctx, array(), true)); 130 $this->assertEquals(13, $this->get_tablelog_results($c2ctx, array(), true)); 131 132 // Filtering on 1 user the current user cannot access should return all records. 133 $this->assertEquals(8, $this->get_tablelog_results($c1ctx, array('userids' => $u1->id), true)); 134 135 // Filtering on 2 users, only one of whom the current user can access. 136 $this->assertEquals(1, $this->get_tablelog_results($c1ctx, ['userids' => "$u1->id,$u3->id"], true)); 137 $results = $this->get_tablelog_results($c1ctx, ['userids' => "$u1->id,$u3->id"]); 138 $this->assertGradeHistoryIds([$grades['c1m1u3']->id], $results); 139 140 // Filtering on 2 users, both of whom the current user can access. 141 $this->assertEquals(3, $this->get_tablelog_results($c1ctx, ['userids' => "$u2->id,$u3->id"], true)); 142 $results = $this->get_tablelog_results($c1ctx, ['userids' => "$u2->id,$u3->id"]); 143 $this->assertGradeHistoryIds([$grades['c1m1u2']->id, $grades['c1m1u3']->id, $grades['c1m2u2']->id], $results); 144 145 // Filtering based on one grade item. 146 $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m1->id)); 147 $this->assertEquals(5, $this->get_tablelog_results($c1ctx, array('itemid' => $gi->id), true)); 148 $gi = \grade_item::fetch($giparams + array('iteminstance' => $c1m3->id)); 149 $this->assertEquals(1, $this->get_tablelog_results($c1ctx, array('itemid' => $gi->id), true)); 150 151 // Filtering based on the grader. 152 $this->assertEquals(3, $this->get_tablelog_results($c2ctx, array('grader' => $grader1->id), true)); 153 $this->assertEquals(1, $this->get_tablelog_results($c2ctx, array('grader' => $grader2->id), true)); 154 155 // Filtering based on date. 156 $results = $this->get_tablelog_results($c1ctx, array('datefrom' => time() + 1800)); 157 $this->assertGradeHistoryIds(array($grades['c1m1u2']->id), $results); 158 $results = $this->get_tablelog_results($c1ctx, array('datetill' => time() - 1800)); 159 $this->assertGradeHistoryIds(array($grades['c1m1u1']->id), $results); 160 $results = $this->get_tablelog_results($c1ctx, array('datefrom' => time() - 1800, 'datetill' => time() + 1800)); 161 $this->assertGradeHistoryIds(array($grades['c1m1u3']->id, $grades['c1m1u4']->id, $grades['c1m1u5']->id, 162 $grades['c1m2u1']->id, $grades['c1m2u2']->id, $grades['c1m3u1']->id), $results); 163 164 // Filtering based on revised only. 165 $this->assertEquals(3, $this->get_tablelog_results($c2ctx, array('userids' => $u5->id), true)); 166 $this->assertEquals(1, $this->get_tablelog_results($c2ctx, array('userids' => $u5->id, 'revisedonly' => true), true)); 167 168 // More filtering based on revised only. 169 $gi = \grade_item::fetch($giparams + array('iteminstance' => $c2m2->id)); 170 $this->assertEquals(6, $this->get_tablelog_results($c2ctx, array('userids' => $u1->id, 'itemid' => $gi->id), true)); 171 $results = $this->get_tablelog_results($c2ctx, array('userids' => $u1->id, 'itemid' => $gi->id, 'revisedonly' => true)); 172 $this->assertGradeHistoryIds(array($grades['c2m2u1a']->id, $grades['c2m2u1c']->id, $grades['c2m2u1e']->id), $results); 173 174 // Checking the value of the previous grade. 175 $this->assertEquals(null, $results[$grades['c2m2u1a']->id]->prevgrade); 176 $this->assertEquals($grades['c2m2u1a']->finalgrade, $results[$grades['c2m2u1c']->id]->prevgrade); 177 $this->assertEquals($grades['c2m2u1c']->finalgrade, $results[$grades['c2m2u1e']->id]->prevgrade); 178 179 // Put course in separate groups mode, add grader1 and two students to the same group. 180 $c1->groupmode = SEPARATEGROUPS; 181 update_course($c1); 182 $this->assertFalse(has_capability('moodle/site:accessallgroups', \context_course::instance($c1->id))); 183 $g1 = self::getDataGenerator()->create_group(['courseid' => $c1->id, 'name' => 'g1']); 184 self::getDataGenerator()->create_group_member(['groupid' => $g1->id, 'userid' => $grader1->id]); 185 self::getDataGenerator()->create_group_member(['groupid' => $g1->id, 'userid' => $u1->id]); 186 self::getDataGenerator()->create_group_member(['groupid' => $g1->id, 'userid' => $u2->id]); 187 $this->assertEquals(2, $this->get_tablelog_results($c1ctx, array(), true)); 188 189 // Grader2 is not in any groups. 190 $this->setUser($grader2); 191 $this->assertEquals(0, $this->get_tablelog_results($c1ctx, array(), true)); 192 } 193 194 /** 195 * Test the get users helper method. 196 */ 197 public function test_get_users() { 198 $this->resetAfterTest(); 199 200 // Making the setup. 201 $c1 = $this->getDataGenerator()->create_course(); 202 $c2 = $this->getDataGenerator()->create_course(); 203 $c1ctx = \context_course::instance($c1->id); 204 $c2ctx = \context_course::instance($c2->id); 205 206 $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1)); 207 $c2m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c2)); 208 209 // Users. 210 $u1 = $this->getDataGenerator()->create_user(array('firstname' => 'Eric', 'lastname' => 'Cartman')); 211 $u2 = $this->getDataGenerator()->create_user(array('firstname' => 'Stan', 'lastname' => 'Marsh')); 212 $u3 = $this->getDataGenerator()->create_user(array('firstname' => 'Kyle', 'lastname' => 'Broflovski')); 213 $u4 = $this->getDataGenerator()->create_user(array('firstname' => 'Kenny', 'lastname' => 'McCormick')); 214 215 // Creating grade history for some users. 216 $gi = \grade_item::fetch(array('iteminstance' => $c1m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign')); 217 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id)); 218 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id)); 219 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id)); 220 221 $gi = \grade_item::fetch(array('iteminstance' => $c2m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign')); 222 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id)); 223 224 // Checking fetching some users. 225 $users = \gradereport_history\helper::get_users($c1ctx); 226 $this->assertCount(3, $users); 227 $this->assertArrayHasKey($u3->id, $users); 228 $users = \gradereport_history\helper::get_users($c2ctx); 229 $this->assertCount(1, $users); 230 $this->assertArrayHasKey($u4->id, $users); 231 $users = \gradereport_history\helper::get_users($c1ctx, 'c'); 232 $this->assertCount(1, $users); 233 $this->assertArrayHasKey($u1->id, $users); 234 $users = \gradereport_history\helper::get_users($c1ctx, '', 0, 2); 235 $this->assertCount(2, $users); 236 $this->assertArrayHasKey($u3->id, $users); 237 $this->assertArrayHasKey($u1->id, $users); 238 $users = \gradereport_history\helper::get_users($c1ctx, '', 1, 2); 239 $this->assertCount(1, $users); 240 $this->assertArrayHasKey($u2->id, $users); 241 242 // Checking the count of users. 243 $this->assertEquals(3, \gradereport_history\helper::get_users_count($c1ctx)); 244 $this->assertEquals(1, \gradereport_history\helper::get_users_count($c2ctx)); 245 $this->assertEquals(1, \gradereport_history\helper::get_users_count($c1ctx, 'c')); 246 } 247 248 /** 249 * Data provider for \gradereport_history_report_testcase::test_get_users_with_profile_fields() 250 * Testing get_users() and get_users_count() test cases. 251 * 252 * @return array List of data sets (test cases) 253 */ 254 public function get_users_with_profile_fields_provider(): array { 255 return [ 256 // User identity check boxes, 'email', 'profile_field_lang' and 'profile_field_height' are checked. 257 'show email,lang and height;search for all users' => 258 ['email,profile_field_lang,profile_field_height', '', ['u1', 'u2', 'u3', 'u4']], 259 'show email,lang and height;search for users on .org ' => 260 ['email,profile_field_lang,profile_field_height', '.org', ['u1', 'u2', 'u4']], 261 'show email,lang and height;search for users on .com ' => 262 ['email,profile_field_lang,profile_field_height', '.com', []], 263 'show email,lang and height;search for users on .uk ' => 264 ['email,profile_field_lang,profile_field_height', '.uk', ['u3']], 265 'show email,lang and height,search for Spanish speakers' => 266 ['email,profile_field_lang,profile_field_height', 'spanish', ['u1', 'u4']], 267 'show email,lang and height,search for Spanish speakers' => 268 ['email,profile_field_lang,profile_field_height', 'spa', ['u1', 'u4']], 269 'show email,lang and height,search for German speakers' => 270 ['email,profile_field_lang,profile_field_height', 'german', ['u2']], 271 'show email,lang and height,search for German speakers' => 272 ['email,profile_field_lang,profile_field_height', 'ger', ['u2']], 273 'show email,lang and height,search for English speakers' => 274 ['email,profile_field_lang,profile_field_height', 'english', ['u3']], 275 'show email,lang and height,search for English speakers' => 276 ['email,profile_field_lang,profile_field_height', 'eng', ['u3']], 277 'show email,lang and height,search for English speakers' => 278 ['email,profile_field_lang,profile_field_height', 'ish', ['u3']], 279 'show email,lang and height,search for users with height 180cm' => 280 ['email,profile_field_lang,profile_field_height', '180cm', ['u2', 'u3', 'u4']], 281 'show email,lang and height,search for users with height 180cm' => 282 ['email,profile_field_lang,profile_field_height', '180', ['u2', 'u3', 'u4']], 283 'show email,lang and height,search for users with height 170cm' => 284 ['email,profile_field_lang,profile_field_height', '170cm', ['u1']], 285 'show email,lang and height,search for users with height 170cm' => 286 ['email,profile_field_lang,profile_field_height', '170', ['u1']], 287 288 // User identity check boxes, 'email' and 'profile_field_height' are checked. 289 'show email and height;search for users on .org' => 290 ['email,profile_field_height', '.org', ['u1', 'u2', 'u4']], 291 'show email and height;search for users on .com' => 292 ['email,profile_field_height', '.com', []], 293 'show email and height;search for users on .co' => 294 ['email,profile_field_height', '.co', ['u3']], 295 'show email and height,search for Spanish/German/English speakers' => 296 ['email,profile_field_height', 'spanish', []], 297 'show email and height,search for Spanish/German/English speakers' => 298 ['email,profile_field_height', 'german', []], 299 'show email and height,search for Spanish/German/English speakers' => 300 ['email,profile_field_height', 'english', []], 301 'show email,lang and height,search for English speakers' => 302 ['email,profile_field_height', 'english', []], 303 'show email and height,search for English speakers' => 304 ['email,profile_field_height', 'eng', []], 305 'show email and height,search for English speakers' => 306 ['email,profile_field_height', 'ish', []], 307 'show email and height,search for users with height 180cm' => 308 ['email,profile_field_height', '180cm', ['u2', 'u3', 'u4']], 309 'show email,lang and height,search for users with height 180cm' => 310 ['email,profile_field_height', '180', ['u2', 'u3', 'u4']], 311 'show email,lang and height,search for users with height 170cm' => 312 ['email,profile_field_height', '170cm', ['u1']], 313 'show email,lang and height,search for users with height 170cm' => 314 ['email,profile_field_height', '170', ['u1']], 315 316 // User identity check boxes, only 'email' is checked. 317 'show email only;search for users on .org' => ['email', '.org', ['u1', 'u2', 'u4']], 318 'show email only;search for users on .com' => ['email', '.com', []], 319 'show email only;search for users on .co.uk' => ['email', 'co.uk', ['u3']], 320 'show email only;search for users on .uk' => ['email', '.uk', ['u3']], 321 'show email only;search for users on .co' => ['email', '.co', ['u3']], 322 'show email only;search for Spanish speakers' => ['email', 'spanish', []], 323 'show email only;search for German speakers' => ['email', 'german', []], 324 'show email only;search for English speakers' => ['email', 'english', []], 325 'show email only;search for users with height 180cm' => ['email', '180cm', []], 326 'show email only;search for users with height 180cm' => ['email', '180', []], 327 'show email only;search for users with height 170cm' => ['email', '170cm', []], 328 'show email only;search for users with height 170cm' => ['email', '170', []], 329 ]; 330 } 331 332 /** 333 * Testing the search functionality on get_users() and get_users_count() and their inner methods. 334 * 335 * @dataProvider get_users_with_profile_fields_provider 336 * 337 * @param string $showuseridentity, list of user identities to be shown. 338 * @param string $searchstring, the string to be searched. 339 * @param array $expectedusernames, a list of expected usernames. 340 * @return void 341 */ 342 public function test_get_users_with_profile_fields(string $showuseridentity, string $searchstring, 343 array $expectedusernames): void { 344 global $CFG, $DB; 345 require_once($CFG->dirroot . '/user/profile/lib.php'); 346 $this->resetAfterTest(); 347 348 // Create a couple of custom profile fields, which are in user identity. 349 $generator = $this->getDataGenerator(); 350 $generator->create_custom_profile_field(['datatype' => 'text', 351 'shortname' => 'lang', 'name' => 'Language']); 352 $generator->create_custom_profile_field(['datatype' => 'text', 353 'shortname' => 'height', 'name' => 'Height']); 354 355 // Create a couple of test users. 356 $u1 = $generator->create_user(['firstname' => 'Eduardo', 'lastname' => 'Gomes', 357 'username' => 'u1', 'email' => 'u1@x.org', 'profile_field_lang' => 'Spanish', 358 'profile_field_height' => '170cm']); 359 $u2 = $generator->create_user(['firstname' => 'Dieter', 'lastname' => 'Schmitt', 360 'username' => 'u2', 'email' => 'u2@x.org', 'profile_field_lang' => 'German', 361 'profile_field_height' => '180cm']); 362 363 $u3 = $generator->create_user(['firstname' => 'Peter', 'lastname' => 'Jones', 364 'username' => 'u3', 'email' => 'u3@x.co.uk', 'profile_field_lang' => 'English', 365 'profile_field_height' => '180cm']); 366 $u4 = $generator->create_user(['firstname' => 'Pedro', 'lastname' => 'Gomes', 367 'username' => 'u4', 'email' => 'u3@x.org', 'profile_field_lang' => 'Spanish', 368 'profile_field_height' => '180cm']); 369 370 // Do this as admin user. 371 $this->setAdminUser(); 372 373 // Making the setup. 374 $c1 = $this->getDataGenerator()->create_course(); 375 $c1ctx = \context_course::instance($c1->id); 376 $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1)); 377 378 // Creating grade history for some users. 379 $gi = \grade_item::fetch(array('iteminstance' => $c1m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign')); 380 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id)); 381 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id)); 382 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u3->id)); 383 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u4->id)); 384 385 // Checking fetching some users with this config settings. 386 set_config('showuseridentity', $showuseridentity); 387 $numberofexpectedusers = count($expectedusernames); 388 $users = \gradereport_history\helper::get_users($c1ctx, $searchstring); 389 $userscount = \gradereport_history\helper::get_users_count($c1ctx, $searchstring); 390 $this->assertEquals($numberofexpectedusers, $userscount); 391 $this->assertCount($numberofexpectedusers, $users); 392 foreach ($users as $user) { 393 if (in_array($user->username, $expectedusernames)) { 394 $this->assertArrayHasKey($user->id, $users); 395 } else { 396 $this->assertArrayNotHasKey($user->id, $users); 397 } 398 } 399 } 400 401 /** 402 * Data provider method for \gradereport_history_report_testcase::test_get_users_with_groups() 403 */ 404 public function get_users_provider() { 405 return [ 406 'Visible groups, non-editing teacher, not in any group' => [ 407 VISIBLEGROUPS, 'teacher', ['g1', 'g2'], ['s1', 's2', 's3', 's4', 's5'] 408 ], 409 'Visible groups, non-editing teacher' => [ 410 VISIBLEGROUPS, 'teacher', [], ['s1', 's2', 's3', 's4', 's5'] 411 ], 412 'Visible groups, editing teacher' => [ 413 VISIBLEGROUPS, 'editingteacher', ['g1', 'g2'], ['s1', 's2', 's3', 's4', 's5'] 414 ], 415 'Separate groups, non-editing teacher' => [ 416 SEPARATEGROUPS, 'teacher', ['g1', 'g2'], ['s1', 's2'] 417 ], 418 'Separate groups, non-editing teacher, not in any group' => [ 419 SEPARATEGROUPS, 'teacher', [], [] 420 ], 421 'Separate groups, non-editing teacher and student share two groups' => [ 422 SEPARATEGROUPS, 'teacher', ['g4', 'g5'], ['s5'] 423 ], 424 'Separate groups, editing teacher' => [ 425 SEPARATEGROUPS, 'editingteacher', ['g1', 'g2'], ['s1', 's2', 's3', 's4', 's5'] 426 ], 427 ]; 428 } 429 430 /** 431 * Test for helper::get_users() with course group mode set. 432 * 433 * @dataProvider get_users_provider 434 * @param $groupmode 435 * @param $teacherrole 436 * @param $teachergroups 437 * @param $expectedusers 438 */ 439 public function test_get_users_with_groups($groupmode, $teacherrole, $teachergroups, $expectedusers) { 440 global $DB; 441 $this->resetAfterTest(); 442 443 $generator = $this->getDataGenerator(); 444 445 // Create a test course. 446 $course = $generator->create_course(['groupmode' => $groupmode]); 447 448 // Create an assignment module. 449 $assign = $generator->create_module('assign', ['course' => $course]); 450 451 // Fetch roles. 452 $role = $DB->get_record('role', ['shortname' => $teacherrole], '*', MUST_EXIST); 453 $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST); 454 455 // Create users. 456 $t1 = $generator->create_user(['username' => 't1', 'email' => 't1@example.com']); 457 $s1 = $generator->create_user(['username' => 's1', 'email' => 's1@example.com']); 458 $s2 = $generator->create_user(['username' => 's2', 'email' => 's2@example.com']); 459 $s3 = $generator->create_user(['username' => 's3', 'email' => 's3@example.com']); 460 $s4 = $generator->create_user(['username' => 's4', 'email' => 's4@example.com']); 461 $s5 = $generator->create_user(['username' => 's5', 'email' => 's5@example.com']); 462 463 // Enrol users. 464 $generator->enrol_user($t1->id, $course->id, $role->id); 465 $generator->enrol_user($s1->id, $course->id, $studentrole->id); 466 $generator->enrol_user($s2->id, $course->id, $studentrole->id); 467 $generator->enrol_user($s3->id, $course->id, $studentrole->id); 468 $generator->enrol_user($s4->id, $course->id, $studentrole->id); 469 $generator->enrol_user($s5->id, $course->id, $studentrole->id); 470 471 // Create groups. 472 $groups = []; 473 $groups['g1'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g1']); 474 $groups['g2'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g2']); 475 $groups['g3'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g3']); 476 $groups['g4'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g4']); 477 $groups['g5'] = $generator->create_group(['courseid' => $course->id, 'name' => 'g5']); 478 479 // Add teacher to the assigned groups. 480 foreach ($teachergroups as $groupname) { 481 $group = $groups[$groupname]; 482 $generator->create_group_member(['groupid' => $group->id, 'userid' => $t1->id]); 483 } 484 485 // Add students to groups. 486 $generator->create_group_member(['groupid' => $groups['g1']->id, 'userid' => $s1->id]); 487 $generator->create_group_member(['groupid' => $groups['g2']->id, 'userid' => $s2->id]); 488 $generator->create_group_member(['groupid' => $groups['g3']->id, 'userid' => $s3->id]); 489 $generator->create_group_member(['groupid' => $groups['g4']->id, 'userid' => $s5->id]); 490 $generator->create_group_member(['groupid' => $groups['g5']->id, 'userid' => $s5->id]); 491 492 // Creating grade history for the students. 493 $gi = \grade_item::fetch(['iteminstance' => $assign->id, 'itemtype' => 'mod', 'itemmodule' => 'assign']); 494 $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s1->id]); 495 $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s2->id]); 496 $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s3->id]); 497 $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s4->id]); 498 $this->create_grade_history(['itemid' => $gi->id, 'userid' => $s5->id]); 499 500 // Log in as the teacher. 501 $this->setUser($t1); 502 503 // Fetch the users. 504 $users = \gradereport_history\helper::get_users(\context_course::instance($course->id)); 505 // Confirm that the number of users fetched is the same as the count of expected users. 506 $this->assertCount(count($expectedusers), $users); 507 foreach ($users as $user) { 508 // Confirm that each user returned is in the list of expected users. 509 $this->assertTrue(in_array($user->username, $expectedusers)); 510 } 511 } 512 513 /** 514 * Test the get graders helper method. 515 */ 516 public function test_graders() { 517 $this->resetAfterTest(); 518 519 // Making the setup. 520 $c1 = $this->getDataGenerator()->create_course(); 521 $c2 = $this->getDataGenerator()->create_course(); 522 $c3 = $this->getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS]); 523 524 $c1m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1)); 525 $c2m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c2)); 526 $c3m1 = $this->getDataGenerator()->create_module('assign', array('course' => $c3)); 527 528 // Users. 529 $u1 = $this->getDataGenerator()->create_user(array('firstname' => 'Eric', 'lastname' => 'Cartman')); 530 $u2 = $this->getDataGenerator()->create_user(array('firstname' => 'Stan', 'lastname' => 'Marsh')); 531 $u3 = $this->getDataGenerator()->create_user(array('firstname' => 'Kyle', 'lastname' => 'Broflovski')); 532 $u4 = $this->getDataGenerator()->create_user(array('firstname' => 'Kenny', 'lastname' => 'McCormick')); 533 534 foreach ([$c1, $c2, $c3] as $course) { 535 foreach ([$u1, $u2, $u3, $u4] as $user) { 536 self::getDataGenerator()->enrol_user($user->id, $course->id, 'student'); 537 } 538 } 539 540 // Creating grade history for some users. 541 $gi = \grade_item::fetch(array('iteminstance' => $c1m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign')); 542 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u1->id)); 543 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u2->id)); 544 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u3->id)); 545 546 $gi = \grade_item::fetch(array('iteminstance' => $c2m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign')); 547 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u4->id)); 548 549 $gi = \grade_item::fetch(array('iteminstance' => $c3m1->id, 'itemtype' => 'mod', 'itemmodule' => 'assign')); 550 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u1->id, 'usermodified' => $u1->id)); 551 $this->create_grade_history(array('itemid' => $gi->id, 'userid' => $u2->id, 'usermodified' => $u2->id)); 552 553 // Checking fetching some users. 554 $graders = \gradereport_history\helper::get_graders($c1->id); 555 $this->assertCount(4, $graders); // Including "all graders" . 556 $this->assertArrayHasKey($u1->id, $graders); 557 $this->assertArrayHasKey($u2->id, $graders); 558 $this->assertArrayHasKey($u3->id, $graders); 559 $graders = \gradereport_history\helper::get_graders($c2->id); 560 $this->assertCount(2, $graders); // Including "all graders" . 561 $this->assertArrayHasKey($u4->id, $graders); 562 563 // Third course is in separate groups mode. Only graders from the same group will be returned. 564 $g = self::getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'g1']); 565 self::getDataGenerator()->create_group_member(['groupid' => $g->id, 'userid' => $u1->id]); 566 self::getDataGenerator()->create_group_member(['groupid' => $g->id, 'userid' => $u2->id]); 567 $this->setUser($u1); 568 $graders = \gradereport_history\helper::get_graders($c3->id); 569 $this->assertCount(3, $graders); // Including "all graders" . 570 $this->setUser($u3); 571 $graders = \gradereport_history\helper::get_graders($c3->id); 572 $this->assertCount(1, $graders); // Including "all graders" . 573 } 574 575 /** 576 * Asserts that the array of grade objects contains exactly the right IDs. 577 * 578 * @param array $expectedids Array of expected IDs. 579 * @param array $objects Array of objects returned by the table. 580 */ 581 protected function assertGradeHistoryIds(array $expectedids, array $objects) { 582 $this->assertCount(count($expectedids), $objects); 583 $expectedids = array_flip($expectedids); 584 foreach ($objects as $object) { 585 $this->assertArrayHasKey($object->id, $expectedids); 586 unset($expectedids[$object->id]); 587 } 588 $this->assertCount(0, $expectedids); 589 } 590 591 /** 592 * Create a new grade history entry. 593 * 594 * @param array $params Of values. 595 * @return object The grade object. 596 */ 597 protected function create_grade_history($params) { 598 global $DB; 599 $params = (array) $params; 600 601 if (!isset($params['itemid'])) { 602 throw new \coding_exception('Missing itemid key.'); 603 } 604 if (!isset($params['userid'])) { 605 throw new \coding_exception('Missing userid key.'); 606 } 607 608 // Default object. 609 $grade = new \stdClass(); 610 $grade->itemid = 0; 611 $grade->userid = 0; 612 $grade->oldid = 123; 613 $grade->rawgrade = 50; 614 $grade->finalgrade = 50; 615 $grade->timecreated = time(); 616 $grade->timemodified = time(); 617 $grade->information = ''; 618 $grade->informationformat = FORMAT_PLAIN; 619 $grade->feedback = ''; 620 $grade->feedbackformat = FORMAT_PLAIN; 621 $grade->usermodified = 2; 622 623 // Merge with data passed. 624 $grade = (object) array_merge((array) $grade, $params); 625 626 // Insert record. 627 $grade->id = $DB->insert_record('grade_grades_history', $grade); 628 629 return $grade; 630 } 631 632 /** 633 * Returns a table log object. 634 * 635 * @param context_course $coursecontext The course context. 636 * @param array $filters An array of filters. 637 * @param boolean $count When true, returns a count rather than an array of objects. 638 * @return mixed Count or array of objects. 639 */ 640 protected function get_tablelog_results($coursecontext, $filters = array(), $count = false) { 641 $table = new gradereport_history_tests_tablelog('something', $coursecontext, new \moodle_url(''), $filters); 642 return $table->get_test_results($count); 643 } 644 645 } 646 647 /** 648 * Extended table log class. 649 */ 650 class gradereport_history_tests_tablelog extends \gradereport_history\output\tablelog { 651 652 /** 653 * Get the test results. 654 * 655 * @param boolean $count Whether or not we want the count. 656 * @return mixed Count or array of objects. 657 */ 658 public function get_test_results($count = false) { 659 global $DB; 660 if ($count) { 661 list($sql, $params) = $this->get_sql_and_params(true); 662 return $DB->count_records_sql($sql, $params); 663 } else { 664 $this->setup(); 665 list($sql, $params) = $this->get_sql_and_params(); 666 return $DB->get_records_sql($sql, $params); 667 } 668 } 669 670 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body