/** * Test upgrade_letter_boundary_needs_freeze function. */ public function test_upgrade_letter_boundary_needs_freeze() { global $CFG; $this->resetAfterTest(); require_once $CFG->libdir . '/db/upgradelib.php'; $courses = array(); $contexts = array(); for ($i = 0; $i < 3; $i++) { $courses[] = $this->getDataGenerator()->create_course(); $contexts[] = context_course::instance($courses[$i]->id); } // Course one is not using a letter boundary. $this->assertFalse(upgrade_letter_boundary_needs_freeze($contexts[0])); // Let's make course 2 use the bad boundary. $this->assign_bad_letter_boundary($contexts[1]->id); $this->assertTrue(upgrade_letter_boundary_needs_freeze($contexts[1])); // Course 3 has letter boundaries that are fine. $this->assign_good_letter_boundary($contexts[2]->id); $this->assertFalse(upgrade_letter_boundary_needs_freeze($contexts[2])); // Try the system context not using a letter boundary. $systemcontext = context_system::instance(); $this->assertFalse(upgrade_letter_boundary_needs_freeze($systemcontext)); }
/** * Marks all courses that require rounded grade items be updated. * * Used during upgrade and in course restore process. * * This upgrade script is needed because it has been decided that if a grade is rounded up, and it will changed a letter * grade or satisfy a course completion grade criteria, then it should be set as so, and the letter will be awarded and or * the course completion grade will be awarded. * * @param int $courseid Specify a course ID to run this script on just one course. */ function upgrade_course_letter_boundary($courseid = null) { global $DB, $CFG; $coursesql = ''; $params = array('contextlevel' => CONTEXT_COURSE); if (!empty($courseid)) { $coursesql = 'AND c.id = :courseid'; $params['courseid'] = $courseid; } // Check to see if the system letter boundaries are borked. $systemcontext = context_system::instance(); $systemneedsfreeze = upgrade_letter_boundary_needs_freeze($systemcontext); // 3, 13, 23, 31, and 32 are the grade display types that incorporate showing letters. See lib/grade/constants/php. $systemletters = isset($CFG->grade_displaytype) && in_array($CFG->grade_displaytype, array(3, 13, 23, 31, 32)); $contextselect = context_helper::get_preload_record_columns_sql('ctx'); if ($systemletters && $systemneedsfreeze) { // Select courses with no grade setting for display and a grade item that is using the default display, // but have not altered the course letter boundary configuration. These courses are definitely affected. $sql = "SELECT DISTINCT c.id AS courseid\n FROM {course} c\n JOIN {grade_items} gi ON c.id = gi.courseid\n JOIN {context} ctx ON ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel\n LEFT JOIN {grade_settings} gs ON gs.courseid = c.id AND gs.name = 'displaytype'\n LEFT JOIN {grade_letters} gl ON gl.contextid = ctx.id\n WHERE gi.display = 0 AND (gs.value is NULL)\n AND gl.id is NULL {$coursesql}"; $affectedcourseids = $DB->get_recordset_sql($sql, $params); foreach ($affectedcourseids as $courseid) { set_config('gradebook_calculations_freeze_' . $courseid->courseid, 20160518); } $affectedcourseids->close(); } if ($systemletters || $systemneedsfreeze) { // If the system letter boundary is okay proceed to check grade item and course grade display settings. $sql = "SELECT DISTINCT c.id AS courseid, {$contextselect}\n FROM {course} c\n JOIN {context} ctx ON ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel\n JOIN {grade_items} gi ON c.id = gi.courseid\n LEFT JOIN {grade_settings} gs ON c.id = gs.courseid AND gs.name = 'displaytype'\n LEFT JOIN {grade_letters} gl ON gl.contextid = ctx.id\n WHERE gi.display IN (3, 13, 23, 31, 32)\n OR (" . $DB->sql_compare_text('gs.value') . " IN ('3', '13', '23', '31', '32'))\n OR gl.id is NOT NULL\n {$coursesql}"; } else { // There is no site setting for letter grades. Just check the modified letter boundaries. $sql = "SELECT DISTINCT c.id AS courseid, {$contextselect}\n FROM {grade_letters} l, {course} c\n JOIN {context} ctx ON ctx.instanceid = c.id AND ctx.contextlevel = :contextlevel\n WHERE l.contextid = ctx.id\n AND ctx.instanceid = c.id\n {$coursesql}"; } $potentialcourses = $DB->get_recordset_sql($sql, $params); foreach ($potentialcourses as $value) { $gradebookfreeze = 'gradebook_calculations_freeze_' . $value->courseid; // Check also if this course id has already been frozen. // If we already have this course ID then move on to the next record. if (!property_exists($CFG, $gradebookfreeze)) { // Check for 57 letter grade issue. context_helper::preload_from_record($value); $coursecontext = context_course::instance($value->courseid); if (upgrade_letter_boundary_needs_freeze($coursecontext)) { // We have a course with a possible score standardisation problem. Flag for freeze. // Flag this course as being frozen. set_config('gradebook_calculations_freeze_' . $value->courseid, 20160518); } } } $potentialcourses->close(); }