See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401]
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 * Handles synchronising grades for the enrolment LTI. 19 * 20 * @package enrol_lti 21 * @copyright 2016 Mark Nelson <markn@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace enrol_lti\task; 26 27 /** 28 * Task for synchronising grades for the enrolment LTI. 29 * 30 * @package enrol_lti 31 * @copyright 2016 Mark Nelson <markn@moodle.com> 32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 */ 34 class sync_grades extends \core\task\scheduled_task { 35 36 /** 37 * Get a descriptive name for this task. 38 * 39 * @return string 40 */ 41 public function get_name() { 42 return get_string('tasksyncgrades', 'enrol_lti'); 43 } 44 45 /** 46 * Performs the synchronisation of grades. 47 * 48 * @return bool|void 49 */ 50 public function execute() { 51 global $DB, $CFG; 52 53 require_once($CFG->dirroot . '/enrol/lti/ims-blti/OAuth.php'); 54 require_once($CFG->dirroot . '/enrol/lti/ims-blti/OAuthBody.php'); 55 require_once($CFG->dirroot . '/lib/completionlib.php'); 56 require_once($CFG->libdir . '/gradelib.php'); 57 require_once($CFG->dirroot . '/grade/querylib.php'); 58 59 // Check if the authentication plugin is disabled. 60 if (!is_enabled_auth('lti')) { 61 mtrace('Skipping task - ' . get_string('pluginnotenabled', 'auth', get_string('pluginname', 'auth_lti'))); 62 return true; 63 } 64 65 // Check if the enrolment plugin is disabled - isn't really necessary as the task should not run if 66 // the plugin is disabled, but there is no harm in making sure core hasn't done something wrong. 67 if (!enrol_is_enabled('lti')) { 68 mtrace('Skipping task - ' . get_string('enrolisdisabled', 'enrol_lti')); 69 return true; 70 } 71 72 // Get all the enabled tools. 73 if ($tools = \enrol_lti\helper::get_lti_tools(array('status' => ENROL_INSTANCE_ENABLED, 'gradesync' => 1, 74 'ltiversion' => 'LTI-1p0/LTI-2p0'))) { 75 foreach ($tools as $tool) { 76 mtrace("Starting - Grade sync for shared tool '$tool->id' for the course '$tool->courseid'."); 77 78 // Variables to keep track of information to display later. 79 $usercount = 0; 80 $sendcount = 0; 81 82 // We check for all the users - users can access the same tool from different consumers. 83 if ($ltiusers = $DB->get_records('enrol_lti_users', array('toolid' => $tool->id), 'lastaccess DESC')) { 84 $completion = new \completion_info(get_course($tool->courseid)); 85 foreach ($ltiusers as $ltiuser) { 86 $mtracecontent = "for the user '$ltiuser->userid' in the tool '$tool->id' for the course " . 87 "'$tool->courseid'"; 88 89 $usercount = $usercount + 1; 90 91 // Check if we do not have a serviceurl - this can happen if the sync process has an unexpected error. 92 if (empty($ltiuser->serviceurl)) { 93 mtrace("Skipping - Empty serviceurl $mtracecontent."); 94 continue; 95 } 96 97 // Check if we do not have a sourceid - this can happen if the sync process has an unexpected error. 98 if (empty($ltiuser->sourceid)) { 99 mtrace("Skipping - Empty sourceid $mtracecontent."); 100 continue; 101 } 102 103 // Need a valid context to continue. 104 if (!$context = \context::instance_by_id($tool->contextid, IGNORE_MISSING)) { 105 mtrace("Failed - Invalid contextid '$tool->contextid' for the tool '$tool->id'."); 106 continue; 107 } 108 109 // Ok, let's get the grade. 110 $grade = false; 111 if ($context->contextlevel == CONTEXT_COURSE) { 112 // Check if the user did not completed the course when it was required. 113 if ($tool->gradesynccompletion && !$completion->is_course_complete($ltiuser->userid)) { 114 mtrace("Skipping - Course not completed $mtracecontent."); 115 continue; 116 } 117 118 // Get the grade. 119 if ($grade = grade_get_course_grade($ltiuser->userid, $tool->courseid)) { 120 $grademax = floatval($grade->item->grademax); 121 $grade = $grade->grade; 122 } 123 } else if ($context->contextlevel == CONTEXT_MODULE) { 124 $cm = get_coursemodule_from_id(false, $context->instanceid, 0, false, MUST_EXIST); 125 126 if ($tool->gradesynccompletion) { 127 $data = $completion->get_data($cm, false, $ltiuser->userid); 128 if ($data->completionstate != COMPLETION_COMPLETE_PASS && 129 $data->completionstate != COMPLETION_COMPLETE) { 130 mtrace("Skipping - Activity not completed $mtracecontent."); 131 continue; 132 } 133 } 134 135 $grades = grade_get_grades($cm->course, 'mod', $cm->modname, $cm->instance, $ltiuser->userid); 136 if (!empty($grades->items[0]->grades)) { 137 $grade = reset($grades->items[0]->grades); 138 if (!empty($grade->item)) { 139 $grademax = floatval($grade->item->grademax); 140 } else { 141 $grademax = floatval($grades->items[0]->grademax); 142 } 143 $grade = $grade->grade; 144 } 145 } 146 147 if ($grade === false || $grade === null || strlen($grade) < 1) { 148 mtrace("Skipping - Invalid grade $mtracecontent."); 149 continue; 150 } 151 152 // No need to be dividing by zero. 153 if (empty($grademax)) { 154 mtrace("Skipping - Invalid grade $mtracecontent."); 155 continue; 156 } 157 158 // Check to see if the grade has changed. 159 if (!grade_floats_different($grade, $ltiuser->lastgrade)) { 160 mtrace("Not sent - The grade $mtracecontent was not sent as the grades are the same."); 161 continue; 162 } 163 164 // Sync with the external system. 165 $floatgrade = $grade / $grademax; 166 $body = \enrol_lti\helper::create_service_body($ltiuser->sourceid, $floatgrade); 167 168 try { 169 $response = sendOAuthBodyPOST('POST', $ltiuser->serviceurl, 170 $ltiuser->consumerkey, $ltiuser->consumersecret, 'application/xml', $body); 171 } catch (\Exception $e) { 172 mtrace("Failed - The grade '$floatgrade' $mtracecontent failed to send."); 173 mtrace($e->getMessage()); 174 continue; 175 } 176 177 if (strpos(strtolower($response), 'success') !== false) { 178 $DB->set_field('enrol_lti_users', 'lastgrade', grade_floatval($grade), array('id' => $ltiuser->id)); 179 mtrace("Success - The grade '$floatgrade' $mtracecontent was sent."); 180 $sendcount = $sendcount + 1; 181 } else { 182 mtrace("Failed - The grade '$floatgrade' $mtracecontent failed to send."); 183 } 184 185 } 186 } 187 mtrace("Completed - Synced grades for tool '$tool->id' in the course '$tool->courseid'. " . 188 "Processed $usercount users; sent $sendcount grades."); 189 mtrace(""); 190 } 191 } 192 } 193 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body