[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/tests/ -> upgradelib_test.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * 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  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1