[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Unit tests for the lib/upgradelib.php library. 19 * 20 * @package core 21 * @category phpunit 22 * @copyright 2013 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 require_once($CFG->libdir.'/upgradelib.php'); 30 31 /** 32 * Tests various classes and functions in upgradelib.php library. 33 */ 34 class core_upgradelib_testcase extends advanced_testcase { 35 36 /** 37 * Test the {@link upgrade_stale_php_files_present() function 38 */ 39 public function test_upgrade_stale_php_files_present() { 40 // Just call the function, must return bool false always 41 // if there aren't any old files in the codebase. 42 $this->assertFalse(upgrade_stale_php_files_present()); 43 } 44 45 /** 46 * Populate some fake grade items into the database with specified 47 * sortorder and course id. 48 * 49 * NOTE: This function doesn't make much attempt to respect the 50 * gradebook internals, its simply used to fake some data for 51 * testing the upgradelib function. Please don't use it for other 52 * purposes. 53 * 54 * @param int $courseid id of course 55 * @param int $sortorder numeric sorting order of item 56 * @return stdClass grade item object from the database. 57 */ 58 private function insert_fake_grade_item_sortorder($courseid, $sortorder) { 59 global $DB, $CFG; 60 require_once($CFG->libdir.'/gradelib.php'); 61 62 $item = new stdClass(); 63 $item->courseid = $courseid; 64 $item->sortorder = $sortorder; 65 $item->gradetype = GRADE_TYPE_VALUE; 66 $item->grademin = 30; 67 $item->grademax = 110; 68 $item->itemnumber = 1; 69 $item->iteminfo = ''; 70 $item->timecreated = time(); 71 $item->timemodified = time(); 72 73 $item->id = $DB->insert_record('grade_items', $item); 74 75 return $DB->get_record('grade_items', array('id' => $item->id)); 76 } 77 78 public function test_upgrade_fix_missing_root_folders_draft() { 79 global $DB, $SITE; 80 81 $this->resetAfterTest(true); 82 83 $user = $this->getDataGenerator()->create_user(); 84 $usercontext = context_user::instance($user->id); 85 $this->setUser($user); 86 $resource1 = $this->getDataGenerator()->get_plugin_generator('mod_resource') 87 ->create_instance(array('course' => $SITE->id)); 88 $context = context_module::instance($resource1->cmid); 89 $draftitemid = 0; 90 file_prepare_draft_area($draftitemid, $context->id, 'mod_resource', 'content', 0); 91 92 $queryparams = array( 93 'component' => 'user', 94 'contextid' => $usercontext->id, 95 'filearea' => 'draft', 96 'itemid' => $draftitemid, 97 ); 98 99 // Make sure there are two records in files for the draft file area and one of them has filename '.'. 100 $records = $DB->get_records_menu('files', $queryparams, '', 'id, filename'); 101 $this->assertEquals(2, count($records)); 102 $this->assertTrue(in_array('.', $records)); 103 $originalhash = $DB->get_field('files', 'pathnamehash', $queryparams + array('filename' => '.')); 104 105 // Delete record with filename '.' and make sure it does not exist any more. 106 $DB->delete_records('files', $queryparams + array('filename' => '.')); 107 108 $records = $DB->get_records_menu('files', $queryparams, '', 'id, filename'); 109 $this->assertEquals(1, count($records)); 110 $this->assertFalse(in_array('.', $records)); 111 112 // Run upgrade script and make sure the record is restored. 113 upgrade_fix_missing_root_folders_draft(); 114 115 $records = $DB->get_records_menu('files', $queryparams, '', 'id, filename'); 116 $this->assertEquals(2, count($records)); 117 $this->assertTrue(in_array('.', $records)); 118 $newhash = $DB->get_field('files', 'pathnamehash', $queryparams + array('filename' => '.')); 119 $this->assertEquals($originalhash, $newhash); 120 } 121 122 /** 123 * Test upgrade minmaxgrade step. 124 */ 125 public function test_upgrade_minmaxgrade() { 126 global $CFG, $DB; 127 require_once($CFG->libdir . '/gradelib.php'); 128 $initialminmax = $CFG->grade_minmaxtouse; 129 $this->resetAfterTest(); 130 131 $c1 = $this->getDataGenerator()->create_course(); 132 $c2 = $this->getDataGenerator()->create_course(); 133 $c3 = $this->getDataGenerator()->create_course(); 134 $u1 = $this->getDataGenerator()->create_user(); 135 $a1 = $this->getDataGenerator()->create_module('assign', array('course' => $c1, 'grade' => 100)); 136 $a2 = $this->getDataGenerator()->create_module('assign', array('course' => $c2, 'grade' => 100)); 137 $a3 = $this->getDataGenerator()->create_module('assign', array('course' => $c3, 'grade' => 100)); 138 139 $cm1 = get_coursemodule_from_instance('assign', $a1->id); 140 $ctx1 = context_module::instance($cm1->id); 141 $assign1 = new assign($ctx1, $cm1, $c1); 142 143 $cm2 = get_coursemodule_from_instance('assign', $a2->id); 144 $ctx2 = context_module::instance($cm2->id); 145 $assign2 = new assign($ctx2, $cm2, $c2); 146 147 $cm3 = get_coursemodule_from_instance('assign', $a3->id); 148 $ctx3 = context_module::instance($cm3->id); 149 $assign3 = new assign($ctx3, $cm3, $c3); 150 151 // Give a grade to the student. 152 $ug = $assign1->get_user_grade($u1->id, true); 153 $ug->grade = 10; 154 $assign1->update_grade($ug); 155 156 $ug = $assign2->get_user_grade($u1->id, true); 157 $ug->grade = 20; 158 $assign2->update_grade($ug); 159 160 $ug = $assign3->get_user_grade($u1->id, true); 161 $ug->grade = 30; 162 $assign3->update_grade($ug); 163 164 165 // Run the upgrade. 166 upgrade_minmaxgrade(); 167 168 // Nothing has happened. 169 $this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c1->id))); 170 $this->assertSame(false, grade_get_setting($c1->id, 'minmaxtouse', false, true)); 171 $this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c1->id))); 172 $this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c2->id))); 173 $this->assertSame(false, grade_get_setting($c2->id, 'minmaxtouse', false, true)); 174 $this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c2->id))); 175 $this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c3->id))); 176 $this->assertSame(false, grade_get_setting($c3->id, 'minmaxtouse', false, true)); 177 $this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c3->id))); 178 179 // Create inconsistency in c1 and c2. 180 $giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $a1->id, 181 'courseid' => $c1->id, 'itemnumber' => 0); 182 $gi = grade_item::fetch($giparams); 183 $gi->grademin = 5; 184 $gi->update(); 185 186 $giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $a2->id, 187 'courseid' => $c2->id, 'itemnumber' => 0); 188 $gi = grade_item::fetch($giparams); 189 $gi->grademax = 50; 190 $gi->update(); 191 192 193 // C1 and C2 should be updated, but the course setting should not be set. 194 $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_GRADE; 195 196 // Run the upgrade. 197 upgrade_minmaxgrade(); 198 199 // C1 and C2 were partially updated. 200 $this->assertTrue($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c1->id))); 201 $this->assertSame(false, grade_get_setting($c1->id, 'minmaxtouse', false, true)); 202 $this->assertTrue($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c1->id))); 203 $this->assertTrue($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c2->id))); 204 $this->assertSame(false, grade_get_setting($c2->id, 'minmaxtouse', false, true)); 205 $this->assertTrue($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c2->id))); 206 207 // Nothing has happened for C3. 208 $this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c3->id))); 209 $this->assertSame(false, grade_get_setting($c3->id, 'minmaxtouse', false, true)); 210 $this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c3->id))); 211 212 213 // Course setting should not be set on a course that has the setting already. 214 $CFG->grade_minmaxtouse = GRADE_MIN_MAX_FROM_GRADE_ITEM; 215 grade_set_setting($c1->id, 'minmaxtouse', -1); // Sets different value than constant to check that it remained the same. 216 217 // Run the upgrade. 218 upgrade_minmaxgrade(); 219 220 // C2 was updated. 221 $this->assertSame((string) GRADE_MIN_MAX_FROM_GRADE_GRADE, grade_get_setting($c2->id, 'minmaxtouse', false, true)); 222 223 // Nothing has happened for C1. 224 $this->assertSame('-1', grade_get_setting($c1->id, 'minmaxtouse', false, true)); 225 226 // Nothing has happened for C3. 227 $this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c3->id))); 228 $this->assertSame(false, grade_get_setting($c3->id, 'minmaxtouse', false, true)); 229 $this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c3->id))); 230 231 232 // Final check, this time we'll unset the default config. 233 unset($CFG->grade_minmaxtouse); 234 grade_set_setting($c1->id, 'minmaxtouse', null); 235 236 // Run the upgrade. 237 upgrade_minmaxgrade(); 238 239 // C1 was updated. 240 $this->assertSame((string) GRADE_MIN_MAX_FROM_GRADE_GRADE, grade_get_setting($c1->id, 'minmaxtouse', false, true)); 241 242 // Nothing has happened for C3. 243 $this->assertFalse($DB->record_exists('config', array('name' => 'show_min_max_grades_changed_' . $c3->id))); 244 $this->assertSame(false, grade_get_setting($c3->id, 'minmaxtouse', false, true)); 245 $this->assertFalse($DB->record_exists('grade_items', array('needsupdate' => 1, 'courseid' => $c3->id))); 246 247 // Restore value. 248 $CFG->grade_minmaxtouse = $initialminmax; 249 } 250 251 public function test_upgrade_extra_credit_weightoverride() { 252 global $DB, $CFG; 253 254 $this->resetAfterTest(true); 255 256 require_once($CFG->libdir . '/db/upgradelib.php'); 257 258 $c = array(); 259 $a = array(); 260 $gi = array(); 261 for ($i=0; $i<5; $i++) { 262 $c[$i] = $this->getDataGenerator()->create_course(); 263 $a[$i] = array(); 264 $gi[$i] = array(); 265 for ($j=0;$j<3;$j++) { 266 $a[$i][$j] = $this->getDataGenerator()->create_module('assign', array('course' => $c[$i], 'grade' => 100)); 267 $giparams = array('itemtype' => 'mod', 'itemmodule' => 'assign', 'iteminstance' => $a[$i][$j]->id, 268 'courseid' => $c[$i]->id, 'itemnumber' => 0); 269 $gi[$i][$j] = grade_item::fetch($giparams); 270 } 271 } 272 273 // Case 1: Course $c[0] has aggregation method different from natural. 274 $coursecategory = grade_category::fetch_course_category($c[0]->id); 275 $coursecategory->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN; 276 $coursecategory->update(); 277 $gi[0][1]->aggregationcoef = 1; 278 $gi[0][1]->update(); 279 $gi[0][2]->weightoverride = 1; 280 $gi[0][2]->update(); 281 282 // Case 2: Course $c[1] has neither extra credits nor overrides 283 284 // Case 3: Course $c[2] has extra credits but no overrides 285 $gi[2][1]->aggregationcoef = 1; 286 $gi[2][1]->update(); 287 288 // Case 4: Course $c[3] has no extra credits and has overrides 289 $gi[3][2]->weightoverride = 1; 290 $gi[3][2]->update(); 291 292 // Case 5: Course $c[4] has both extra credits and overrides 293 $gi[4][1]->aggregationcoef = 1; 294 $gi[4][1]->update(); 295 $gi[4][2]->weightoverride = 1; 296 $gi[4][2]->update(); 297 298 // Run the upgrade script and make sure only course $c[4] was marked as needed to be fixed. 299 upgrade_extra_credit_weightoverride(); 300 301 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[0]->id})); 302 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[1]->id})); 303 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[2]->id})); 304 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[3]->id})); 305 $this->assertEquals(20150619, $CFG->{'gradebook_calculations_freeze_' . $c[4]->id}); 306 307 set_config('gradebook_calculations_freeze_' . $c[4]->id, null); 308 309 // Run the upgrade script for a single course only. 310 upgrade_extra_credit_weightoverride($c[0]->id); 311 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $c[0]->id})); 312 upgrade_extra_credit_weightoverride($c[4]->id); 313 $this->assertEquals(20150619, $CFG->{'gradebook_calculations_freeze_' . $c[4]->id}); 314 } 315 316 /** 317 * Test the upgrade function for flagging courses with calculated grade item problems. 318 */ 319 public function test_upgrade_calculated_grade_items_freeze() { 320 global $DB, $CFG; 321 322 $this->resetAfterTest(); 323 324 require_once($CFG->libdir . '/db/upgradelib.php'); 325 326 // Create a user. 327 $user = $this->getDataGenerator()->create_user(); 328 329 // Create a couple of courses. 330 $course1 = $this->getDataGenerator()->create_course(); 331 $course2 = $this->getDataGenerator()->create_course(); 332 $course3 = $this->getDataGenerator()->create_course(); 333 334 // Enrol the user in the courses. 335 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 336 $maninstance1 = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual'), '*', MUST_EXIST); 337 $maninstance2 = $DB->get_record('enrol', array('courseid' => $course2->id, 'enrol' => 'manual'), '*', MUST_EXIST); 338 $maninstance3 = $DB->get_record('enrol', array('courseid' => $course3->id, 'enrol' => 'manual'), '*', MUST_EXIST); 339 $manual = enrol_get_plugin('manual'); 340 $manual->enrol_user($maninstance1, $user->id, $studentrole->id); 341 $manual->enrol_user($maninstance2, $user->id, $studentrole->id); 342 $manual->enrol_user($maninstance3, $user->id, $studentrole->id); 343 344 // To create the data we need we freeze the grade book to use the old behaviour. 345 set_config('gradebook_calculations_freeze_' . $course1->id, 20150627); 346 set_config('gradebook_calculations_freeze_' . $course2->id, 20150627); 347 set_config('gradebook_calculations_freeze_' . $course3->id, 20150627); 348 $CFG->grade_minmaxtouse = 2; 349 350 // Creating a category for a grade item. 351 $gradecategory = new grade_category(); 352 $gradecategory->fullname = 'calculated grade category'; 353 $gradecategory->courseid = $course1->id; 354 $gradecategory->insert(); 355 $gradecategoryid = $gradecategory->id; 356 357 // This is a manual grade item. 358 $gradeitem = new grade_item(); 359 $gradeitem->itemname = 'grade item one'; 360 $gradeitem->itemtype = 'manual'; 361 $gradeitem->categoryid = $gradecategoryid; 362 $gradeitem->courseid = $course1->id; 363 $gradeitem->idnumber = 'gi1'; 364 $gradeitem->insert(); 365 366 // Changing the category into a calculated grade category. 367 $gradecategoryitem = grade_item::fetch(array('iteminstance' => $gradecategory->id)); 368 $gradecategoryitem->calculation = '=##gi' . $gradeitem->id . '##/2'; 369 $gradecategoryitem->update(); 370 371 // Setting a grade for the student. 372 $grade = $gradeitem->get_grade($user->id, true); 373 $grade->finalgrade = 50; 374 $grade->update(); 375 // Creating all the grade_grade items. 376 grade_regrade_final_grades($course1->id); 377 // Updating the grade category to a new grade max and min. 378 $gradecategoryitem->grademax = 50; 379 $gradecategoryitem->grademin = 5; 380 $gradecategoryitem->update(); 381 382 // Different manual grade item for course 2. We are creating a course with a calculated grade item that has a grade max of 383 // 50. The grade_grade will have a rawgrademax of 100 regardless. 384 $gradeitem = new grade_item(); 385 $gradeitem->itemname = 'grade item one'; 386 $gradeitem->itemtype = 'manual'; 387 $gradeitem->courseid = $course2->id; 388 $gradeitem->idnumber = 'gi1'; 389 $gradeitem->grademax = 25; 390 $gradeitem->insert(); 391 392 // Calculated grade item for course 2. 393 $calculatedgradeitem = new grade_item(); 394 $calculatedgradeitem->itemname = 'calculated grade'; 395 $calculatedgradeitem->itemtype = 'manual'; 396 $calculatedgradeitem->courseid = $course2->id; 397 $calculatedgradeitem->calculation = '=##gi' . $gradeitem->id . '##*2'; 398 $calculatedgradeitem->grademax = 50; 399 $calculatedgradeitem->insert(); 400 401 // Assigning a grade for the user. 402 $grade = $gradeitem->get_grade($user->id, true); 403 $grade->finalgrade = 10; 404 $grade->update(); 405 406 // Setting all of the grade_grade items. 407 grade_regrade_final_grades($course2->id); 408 409 // Different manual grade item for course 3. We are creating a course with a calculated grade item that has a grade max of 410 // 50. The grade_grade will have a rawgrademax of 100 regardless. 411 $gradeitem = new grade_item(); 412 $gradeitem->itemname = 'grade item one'; 413 $gradeitem->itemtype = 'manual'; 414 $gradeitem->courseid = $course3->id; 415 $gradeitem->idnumber = 'gi1'; 416 $gradeitem->grademax = 25; 417 $gradeitem->insert(); 418 419 // Calculated grade item for course 2. 420 $calculatedgradeitem = new grade_item(); 421 $calculatedgradeitem->itemname = 'calculated grade'; 422 $calculatedgradeitem->itemtype = 'manual'; 423 $calculatedgradeitem->courseid = $course3->id; 424 $calculatedgradeitem->calculation = '=##gi' . $gradeitem->id . '##*2'; 425 $calculatedgradeitem->grademax = 50; 426 $calculatedgradeitem->insert(); 427 428 // Assigning a grade for the user. 429 $grade = $gradeitem->get_grade($user->id, true); 430 $grade->finalgrade = 10; 431 $grade->update(); 432 433 // Setting all of the grade_grade items. 434 grade_regrade_final_grades($course3->id); 435 // Need to do this first before changing the other courses, otherwise they will be flagged too early. 436 set_config('gradebook_calculations_freeze_' . $course3->id, null); 437 upgrade_calculated_grade_items($course3->id); 438 $this->assertEquals(20150627, $CFG->{'gradebook_calculations_freeze_' . $course3->id}); 439 440 // Change the setting back to null. 441 set_config('gradebook_calculations_freeze_' . $course1->id, null); 442 set_config('gradebook_calculations_freeze_' . $course2->id, null); 443 // Run the upgrade. 444 upgrade_calculated_grade_items(); 445 // The setting should be set again after the upgrade. 446 $this->assertEquals(20150627, $CFG->{'gradebook_calculations_freeze_' . $course1->id}); 447 $this->assertEquals(20150627, $CFG->{'gradebook_calculations_freeze_' . $course2->id}); 448 } 449 450 function test_upgrade_calculated_grade_items_regrade() { 451 global $DB, $CFG; 452 453 $this->resetAfterTest(); 454 455 require_once($CFG->libdir . '/db/upgradelib.php'); 456 457 // Create a user. 458 $user = $this->getDataGenerator()->create_user(); 459 460 // Create a course. 461 $course = $this->getDataGenerator()->create_course(); 462 463 // Enrol the user in the course. 464 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 465 $maninstance1 = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST); 466 $manual = enrol_get_plugin('manual'); 467 $manual->enrol_user($maninstance1, $user->id, $studentrole->id); 468 469 set_config('upgrade_calculatedgradeitemsonlyregrade', 1); 470 471 // Creating a category for a grade item. 472 $gradecategory = new grade_category(); 473 $gradecategory->fullname = 'calculated grade category'; 474 $gradecategory->courseid = $course->id; 475 $gradecategory->insert(); 476 $gradecategoryid = $gradecategory->id; 477 478 // This is a manual grade item. 479 $gradeitem = new grade_item(); 480 $gradeitem->itemname = 'grade item one'; 481 $gradeitem->itemtype = 'manual'; 482 $gradeitem->categoryid = $gradecategoryid; 483 $gradeitem->courseid = $course->id; 484 $gradeitem->idnumber = 'gi1'; 485 $gradeitem->insert(); 486 487 // Changing the category into a calculated grade category. 488 $gradecategoryitem = grade_item::fetch(array('iteminstance' => $gradecategory->id)); 489 $gradecategoryitem->calculation = '=##gi' . $gradeitem->id . '##/2'; 490 $gradecategoryitem->grademax = 50; 491 $gradecategoryitem->grademin = 15; 492 $gradecategoryitem->update(); 493 494 // Setting a grade for the student. 495 $grade = $gradeitem->get_grade($user->id, true); 496 $grade->finalgrade = 50; 497 $grade->update(); 498 499 grade_regrade_final_grades($course->id); 500 $grade = grade_grade::fetch(array('itemid' => $gradecategoryitem->id, 'userid' => $user->id)); 501 $grade->rawgrademax = 100; 502 $grade->rawgrademin = 0; 503 $grade->update(); 504 $this->assertNotEquals($gradecategoryitem->grademax, $grade->rawgrademax); 505 $this->assertNotEquals($gradecategoryitem->grademin, $grade->rawgrademin); 506 507 // This is the function that we are testing. If we comment out this line, then the test fails because the grade items 508 // are not flagged for regrading. 509 upgrade_calculated_grade_items(); 510 grade_regrade_final_grades($course->id); 511 512 $grade = grade_grade::fetch(array('itemid' => $gradecategoryitem->id, 'userid' => $user->id)); 513 514 $this->assertEquals($gradecategoryitem->grademax, $grade->rawgrademax); 515 $this->assertEquals($gradecategoryitem->grademin, $grade->rawgrademin); 516 } 517 518 public function test_upgrade_course_tags() { 519 global $DB, $CFG; 520 521 $this->resetAfterTest(); 522 523 require_once($CFG->libdir . '/db/upgradelib.php'); 524 525 // Running upgrade script when there are no tags. 526 upgrade_course_tags(); 527 $this->assertFalse($DB->record_exists('tag_instance', array())); 528 529 // No course entries. 530 $DB->insert_record('tag_instance', array('itemid' => 123, 'tagid' => 101, 'tiuserid' => 0, 531 'itemtype' => 'post', 'component' => 'core', 'contextid' => 1)); 532 $DB->insert_record('tag_instance', array('itemid' => 333, 'tagid' => 103, 'tiuserid' => 1002, 533 'itemtype' => 'post', 'component' => 'core', 'contextid' => 1)); 534 535 upgrade_course_tags(); 536 $records = array_values($DB->get_records('tag_instance', array(), 'id', '*')); 537 $this->assertEquals(2, count($records)); 538 $this->assertEquals(123, $records[0]->itemid); 539 $this->assertEquals(333, $records[1]->itemid); 540 541 // Imagine we have tags 101, 102, 103, ... and courses 1, 2, 3, ... and users 1001, 1002, ... . 542 $keys = array('itemid', 'tagid', 'tiuserid'); 543 $valuesets = array( 544 array(1, 101, 0), 545 array(1, 102, 0), 546 547 array(2, 102, 0), 548 array(2, 103, 1001), 549 550 array(3, 103, 0), 551 array(3, 103, 1001), 552 553 array(3, 104, 1006), 554 array(3, 104, 1001), 555 array(3, 104, 1002), 556 ); 557 558 foreach ($valuesets as $values) { 559 $DB->insert_record('tag_instance', array_combine($keys, $values) + 560 array('itemtype' => 'course', 'component' => 'core', 'contextid' => 1)); 561 } 562 563 upgrade_course_tags(); 564 // There are 8 records in 'tag_instance' table and 7 of them do not have tiuserid (except for one 'post'). 565 $records = array_values($DB->get_records('tag_instance', array(), 'id', '*')); 566 $this->assertEquals(8, count($records)); 567 $this->assertEquals(7, $DB->count_records('tag_instance', array('tiuserid' => 0))); 568 // Course 1 is mapped to tags 101 and 102. 569 $this->assertEquals(array(101, 102), array_values($DB->get_fieldset_select('tag_instance', 'tagid', 570 'itemtype = ? AND itemid = ? ORDER BY tagid', array('course', 1)))); 571 // Course 2 is mapped to tags 102 and 103. 572 $this->assertEquals(array(102, 103), array_values($DB->get_fieldset_select('tag_instance', 'tagid', 573 'itemtype = ? AND itemid = ? ORDER BY tagid', array('course', 2)))); 574 // Course 1 is mapped to tags 101 and 102. 575 $this->assertEquals(array(103, 104), array_values($DB->get_fieldset_select('tag_instance', 'tagid', 576 'itemtype = ? AND itemid = ? ORDER BY tagid', array('course', 3)))); 577 } 578 579 /** 580 * Test that the upgrade script correctly flags courses to be frozen due to letter boundary problems. 581 */ 582 public function test_upgrade_course_letter_boundary() { 583 global $CFG, $DB; 584 $this->resetAfterTest(true); 585 586 require_once($CFG->libdir . '/db/upgradelib.php'); 587 588 // Create a user. 589 $user = $this->getDataGenerator()->create_user(); 590 591 // Create some courses. 592 $courses = array(); 593 $contexts = array(); 594 for ($i = 0; $i < 45; $i++) { 595 $course = $this->getDataGenerator()->create_course(); 596 $context = context_course::instance($course->id); 597 if (in_array($i, array(2, 5, 10, 13, 14, 19, 23, 25, 30, 34, 36))) { 598 // Assign good letter boundaries. 599 $this->assign_good_letter_boundary($context->id); 600 } 601 if (in_array($i, array(3, 6, 11, 15, 20, 24, 26, 31, 35))) { 602 // Assign bad letter boundaries. 603 $this->assign_bad_letter_boundary($context->id); 604 } 605 606 if (in_array($i, array(3, 9, 10, 11, 18, 19, 20, 29, 30, 31, 40))) { 607 grade_set_setting($course->id, 'displaytype', '3'); 608 } else if (in_array($i, array(8, 17, 28))) { 609 grade_set_setting($course->id, 'displaytype', '2'); 610 } 611 612 if (in_array($i, array(37, 43))) { 613 // Show. 614 grade_set_setting($course->id, 'report_user_showlettergrade', '1'); 615 } else if (in_array($i, array(38, 42))) { 616 // Hide. 617 grade_set_setting($course->id, 'report_user_showlettergrade', '0'); 618 } 619 620 $assignrow = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'name' => 'Test!')); 621 $gi = grade_item::fetch( 622 array('itemtype' => 'mod', 623 'itemmodule' => 'assign', 624 'iteminstance' => $assignrow->id, 625 'courseid' => $course->id)); 626 if (in_array($i, array(6, 13, 14, 15, 23, 24, 34, 35, 36, 41))) { 627 grade_item::set_properties($gi, array('display' => 3)); 628 $gi->update(); 629 } else if (in_array($i, array(12, 21, 32))) { 630 grade_item::set_properties($gi, array('display' => 2)); 631 $gi->update(); 632 } 633 $gradegrade = new grade_grade(); 634 $gradegrade->itemid = $gi->id; 635 $gradegrade->userid = $user->id; 636 $gradegrade->rawgrade = 55.5563; 637 $gradegrade->finalgrade = 55.5563; 638 $gradegrade->rawgrademax = 100; 639 $gradegrade->rawgrademin = 0; 640 $gradegrade->timecreated = time(); 641 $gradegrade->timemodified = time(); 642 $gradegrade->insert(); 643 644 $contexts[] = $context; 645 $courses[] = $course; 646 } 647 648 upgrade_course_letter_boundary(); 649 650 // No system setting for grade letter boundaries. 651 // [0] A course with no letter boundaries. 652 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[0]->id})); 653 // [1] A course with letter boundaries which are default. 654 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[1]->id})); 655 // [2] A course with letter boundaries which are custom but not affected. 656 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[2]->id})); 657 // [3] A course with letter boundaries which are custom and will be affected. 658 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[3]->id}); 659 // [4] A course with no letter boundaries, but with a grade item with letter boundaries which are default. 660 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[4]->id})); 661 // [5] A course with no letter boundaries, but with a grade item with letter boundaries which are not default, but not affected. 662 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[5]->id})); 663 // [6] A course with no letter boundaries, but with a grade item with letter boundaries which are not default which will be affected. 664 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[6]->id}); 665 666 // System setting for grade letter boundaries (default). 667 set_config('grade_displaytype', '3'); 668 for ($i = 0; $i < 45; $i++) { 669 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); 670 } 671 upgrade_course_letter_boundary(); 672 673 // [7] A course with no grade display settings for the course or grade items. 674 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[7]->id})); 675 // [8] A course with grade display settings, but for something that isn't letters. 676 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[8]->id})); 677 // [9] A course with grade display settings of letters which are default. 678 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[9]->id})); 679 // [10] A course with grade display settings of letters which are not default, but not affected. 680 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[10]->id})); 681 // [11] A course with grade display settings of letters which are not default, which will be affected. 682 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[11]->id}); 683 // [12] A grade item with display settings that are not letters. 684 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[12]->id})); 685 // [13] A grade item with display settings of letters which are default. 686 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[13]->id})); 687 // [14] A grade item with display settings of letters which are not default, but not affected. 688 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[14]->id})); 689 // [15] A grade item with display settings of letters which are not default, which will be affected. 690 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[15]->id}); 691 692 // System setting for grade letter boundaries (custom with problem). 693 $systemcontext = context_system::instance(); 694 $this->assign_bad_letter_boundary($systemcontext->id); 695 for ($i = 0; $i < 45; $i++) { 696 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); 697 } 698 upgrade_course_letter_boundary(); 699 700 // [16] A course with no grade display settings for the course or grade items. 701 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[16]->id}); 702 // [17] A course with grade display settings, but for something that isn't letters. 703 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[17]->id})); 704 // [18] A course with grade display settings of letters which are default. 705 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[18]->id}); 706 // [19] A course with grade display settings of letters which are not default, but not affected. 707 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[19]->id})); 708 // [20] A course with grade display settings of letters which are not default, which will be affected. 709 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[20]->id}); 710 // [21] A grade item with display settings which are not letters. Grade total will be affected so should be frozen. 711 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[21]->id}); 712 // [22] A grade item with display settings of letters which are default. 713 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[22]->id}); 714 // [23] A grade item with display settings of letters which are not default, but not affected. Course uses new letter boundary setting. 715 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[23]->id})); 716 // [24] A grade item with display settings of letters which are not default, which will be affected. 717 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[24]->id}); 718 // [25] A course which is using the default grade display setting, but has updated the grade letter boundary (not 57) Should not be frozen. 719 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[25]->id})); 720 // [26] A course that is using the default display setting (letters) and altered the letter boundary with 57. Should be frozen. 721 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[26]->id}); 722 723 // System setting not showing letters. 724 set_config('grade_displaytype', '2'); 725 for ($i = 0; $i < 45; $i++) { 726 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); 727 } 728 upgrade_course_letter_boundary(); 729 730 // [27] A course with no grade display settings for the course or grade items. 731 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[27]->id})); 732 // [28] A course with grade display settings, but for something that isn't letters. 733 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[28]->id})); 734 // [29] A course with grade display settings of letters which are default. 735 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[29]->id}); 736 // [30] A course with grade display settings of letters which are not default, but not affected. 737 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[30]->id})); 738 // [31] A course with grade display settings of letters which are not default, which will be affected. 739 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[31]->id}); 740 // [32] A grade item with display settings which are not letters. 741 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[32]->id})); 742 // [33] All system defaults. 743 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[33]->id})); 744 // [34] A grade item with display settings of letters which are not default, but not affected. Course uses new letter boundary setting. 745 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[34]->id})); 746 // [35] A grade item with display settings of letters which are not default, which will be affected. 747 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[35]->id}); 748 // [36] A course with grade display settings of letters with modified and good boundary (not 57) Should not be frozen. 749 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[36]->id})); 750 751 // Previous site conditions still exist. 752 for ($i = 0; $i < 45; $i++) { 753 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); 754 } 755 upgrade_course_letter_boundary(); 756 757 // [37] Site setting for not showing the letter column and course setting set to show (frozen). 758 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[37]->id}); 759 // [38] Site setting for not showing the letter column and course setting set to hide. 760 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[38]->id})); 761 // [39] Site setting for not showing the letter column and course setting set to default. 762 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[39]->id})); 763 // [40] Site setting for not showing the letter column and course setting set to default. Course display set to letters (frozen). 764 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[40]->id}); 765 // [41] Site setting for not showing the letter column and course setting set to default. Grade item display set to letters (frozen). 766 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[41]->id}); 767 768 // Previous site conditions still exist. 769 for ($i = 0; $i < 45; $i++) { 770 unset_config('gradebook_calculations_freeze_' . $courses[$i]->id); 771 } 772 set_config('grade_report_user_showlettergrade', '1'); 773 upgrade_course_letter_boundary(); 774 775 // [42] Site setting for showing the letter column, but course setting set to hide. 776 $this->assertTrue(empty($CFG->{'gradebook_calculations_freeze_' . $courses[42]->id})); 777 // [43] Site setting for showing the letter column and course setting set to show (frozen). 778 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[43]->id}); 779 // [44] Site setting for showing the letter column and course setting set to default (frozen). 780 $this->assertEquals(20160518, $CFG->{'gradebook_calculations_freeze_' . $courses[44]->id}); 781 } 782 783 /** 784 * Test upgrade_letter_boundary_needs_freeze function. 785 */ 786 public function test_upgrade_letter_boundary_needs_freeze() { 787 global $CFG; 788 789 $this->resetAfterTest(); 790 791 require_once($CFG->libdir . '/db/upgradelib.php'); 792 793 $courses = array(); 794 $contexts = array(); 795 for ($i = 0; $i < 3; $i++) { 796 $courses[] = $this->getDataGenerator()->create_course(); 797 $contexts[] = context_course::instance($courses[$i]->id); 798 } 799 800 // Course one is not using a letter boundary. 801 $this->assertFalse(upgrade_letter_boundary_needs_freeze($contexts[0])); 802 803 // Let's make course 2 use the bad boundary. 804 $this->assign_bad_letter_boundary($contexts[1]->id); 805 $this->assertTrue(upgrade_letter_boundary_needs_freeze($contexts[1])); 806 // Course 3 has letter boundaries that are fine. 807 $this->assign_good_letter_boundary($contexts[2]->id); 808 $this->assertFalse(upgrade_letter_boundary_needs_freeze($contexts[2])); 809 // Try the system context not using a letter boundary. 810 $systemcontext = context_system::instance(); 811 $this->assertFalse(upgrade_letter_boundary_needs_freeze($systemcontext)); 812 } 813 814 /** 815 * Assigns letter boundaries with comparison problems. 816 * 817 * @param int $contextid Context ID. 818 */ 819 private function assign_bad_letter_boundary($contextid) { 820 global $DB; 821 $newlettersscale = array( 822 array('contextid' => $contextid, 'lowerboundary' => 90.00000, 'letter' => 'A'), 823 array('contextid' => $contextid, 'lowerboundary' => 85.00000, 'letter' => 'A-'), 824 array('contextid' => $contextid, 'lowerboundary' => 80.00000, 'letter' => 'B+'), 825 array('contextid' => $contextid, 'lowerboundary' => 75.00000, 'letter' => 'B'), 826 array('contextid' => $contextid, 'lowerboundary' => 70.00000, 'letter' => 'B-'), 827 array('contextid' => $contextid, 'lowerboundary' => 65.00000, 'letter' => 'C+'), 828 array('contextid' => $contextid, 'lowerboundary' => 57.00000, 'letter' => 'C'), 829 array('contextid' => $contextid, 'lowerboundary' => 50.00000, 'letter' => 'C-'), 830 array('contextid' => $contextid, 'lowerboundary' => 40.00000, 'letter' => 'D+'), 831 array('contextid' => $contextid, 'lowerboundary' => 25.00000, 'letter' => 'D'), 832 array('contextid' => $contextid, 'lowerboundary' => 0.00000, 'letter' => 'F'), 833 ); 834 835 $DB->delete_records('grade_letters', array('contextid' => $contextid)); 836 foreach ($newlettersscale as $record) { 837 // There is no API to do this, so we have to manually insert into the database. 838 $DB->insert_record('grade_letters', $record); 839 } 840 } 841 842 /** 843 * Assigns letter boundaries with no comparison problems. 844 * 845 * @param int $contextid Context ID. 846 */ 847 private function assign_good_letter_boundary($contextid) { 848 global $DB; 849 $newlettersscale = array( 850 array('contextid' => $contextid, 'lowerboundary' => 90.00000, 'letter' => 'A'), 851 array('contextid' => $contextid, 'lowerboundary' => 85.00000, 'letter' => 'A-'), 852 array('contextid' => $contextid, 'lowerboundary' => 80.00000, 'letter' => 'B+'), 853 array('contextid' => $contextid, 'lowerboundary' => 75.00000, 'letter' => 'B'), 854 array('contextid' => $contextid, 'lowerboundary' => 70.00000, 'letter' => 'B-'), 855 array('contextid' => $contextid, 'lowerboundary' => 65.00000, 'letter' => 'C+'), 856 array('contextid' => $contextid, 'lowerboundary' => 54.00000, 'letter' => 'C'), 857 array('contextid' => $contextid, 'lowerboundary' => 50.00000, 'letter' => 'C-'), 858 array('contextid' => $contextid, 'lowerboundary' => 40.00000, 'letter' => 'D+'), 859 array('contextid' => $contextid, 'lowerboundary' => 25.00000, 'letter' => 'D'), 860 array('contextid' => $contextid, 'lowerboundary' => 0.00000, 'letter' => 'F'), 861 ); 862 863 $DB->delete_records('grade_letters', array('contextid' => $contextid)); 864 foreach ($newlettersscale as $record) { 865 // There is no API to do this, so we have to manually insert into the database. 866 $DB->insert_record('grade_letters', $record); 867 } 868 } 869 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |