[ 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 * Handles synchronising members using 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 members using 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_members extends \core\task\scheduled_task { 35 36 /** 37 * The LTI message type. 38 */ 39 const LTI_MESSAGE_TYPE = 'basic-lis-readmembershipsforcontext'; 40 41 /** 42 * The LTI version. 43 */ 44 const LTI_VERSION = 'LTI-1p0'; 45 46 /** 47 * Get a descriptive name for this task. 48 * 49 * @return string 50 */ 51 public function get_name() { 52 return get_string('tasksyncmembers', 'enrol_lti'); 53 } 54 55 /** 56 * Performs the synchronisation of members. 57 * 58 * @return bool|void 59 */ 60 public function execute() { 61 global $CFG, $DB; 62 63 require_once($CFG->dirroot . '/enrol/lti/ims-blti/OAuth.php'); 64 require_once($CFG->dirroot . '/enrol/lti/ims-blti/OAuthBody.php'); 65 66 // Check if the authentication plugin is disabled. 67 if (!is_enabled_auth('lti')) { 68 mtrace('Skipping task - ' . get_string('pluginnotenabled', 'auth', get_string('pluginname', 'auth_lti'))); 69 return true; 70 } 71 72 // Check if the enrolment plugin is disabled - isn't really necessary as the task should not run if 73 // the plugin is disabled, but there is no harm in making sure core hasn't done something wrong. 74 if (!enrol_is_enabled('lti')) { 75 mtrace('Skipping task - ' . get_string('enrolisdisabled', 'enrol_lti')); 76 return true; 77 } 78 79 // Get all the enabled tools. 80 if ($tools = \enrol_lti\helper::get_lti_tools(array('status' => ENROL_INSTANCE_ENABLED, 'membersync' => 1))) { 81 $ltiplugin = enrol_get_plugin('lti'); 82 $consumers = array(); 83 $currentusers = array(); 84 $userphotos = array(); 85 foreach ($tools as $tool) { 86 mtrace("Starting - Member sync for shared tool '$tool->id' for the course '$tool->courseid'."); 87 88 // Variables to keep track of information to display later. 89 $usercount = 0; 90 $enrolcount = 0; 91 $unenrolcount = 0; 92 93 // We check for all the users - users can access the same tool from different consumers. 94 if ($ltiusers = $DB->get_records('enrol_lti_users', array('toolid' => $tool->id), 'lastaccess DESC')) { 95 foreach ($ltiusers as $ltiuser) { 96 $mtracecontent = "for the user '$ltiuser->userid' in the tool '$tool->id' for the course " . 97 "'$tool->courseid'"; 98 $usercount++; 99 100 // Check if we do not have a membershipsurl - this can happen if the sync process has an unexpected error. 101 if (!$ltiuser->membershipsurl) { 102 mtrace("Skipping - Empty membershipsurl $mtracecontent."); 103 continue; 104 } 105 106 // Check if we do not have a membershipsid - this can happen if the sync process has an unexpected error. 107 if (!$ltiuser->membershipsid) { 108 mtrace("Skipping - Empty membershipsid $mtracecontent."); 109 continue; 110 } 111 112 $consumer = sha1($ltiuser->membershipsurl . ':' . $ltiuser->membershipsid . ':' . 113 $ltiuser->consumerkey . ':' . $ltiuser->consumersecret); 114 if (in_array($consumer, $consumers)) { 115 // We have already synchronised with this consumer. 116 continue; 117 } 118 119 $consumers[] = $consumer; 120 121 $params = array( 122 'lti_message_type' => self::LTI_MESSAGE_TYPE, 123 'id' => $ltiuser->membershipsid, 124 'lti_version' => self::LTI_VERSION 125 ); 126 127 mtrace("Calling memberships url '$ltiuser->membershipsurl' with body '" . 128 json_encode($params) . "'"); 129 130 try { 131 $response = sendOAuthParamsPOST('POST', $ltiuser->membershipsurl, $ltiuser->consumerkey, 132 $ltiuser->consumersecret, 'application/x-www-form-urlencoded', $params); 133 } catch (\Exception $e) { 134 mtrace("Skipping - No response received $mtracecontent from '$ltiuser->membershipsurl'"); 135 mtrace($e->getMessage()); 136 continue; 137 } 138 139 // Check the response from the consumer. 140 $data = new \SimpleXMLElement($response); 141 142 // Check if we did not receive a valid response. 143 if (empty($data->statusinfo)) { 144 mtrace("Skipping - Bad response received $mtracecontent from '$ltiuser->membershipsurl'"); 145 mtrace('Skipping - Error parsing the XML received \'' . substr($response, 0, 125) . 146 '\' ... (Displaying only 125 chars)'); 147 continue; 148 } 149 150 // Check if we did not receive a valid response. 151 if (strpos(strtolower($data->statusinfo->codemajor), 'success') === false) { 152 mtrace('Skipping - Error received from the remote system: ' . $data->statusinfo->codemajor 153 . ' ' . $data->statusinfo->severity . ' ' . $data->statusinfo->codeminor); 154 continue; 155 } 156 157 $members = $data->memberships->member; 158 mtrace(count($members) . ' members received.'); 159 foreach ($members as $member) { 160 // Set the user data. 161 $user = new \stdClass(); 162 $user->username = \enrol_lti\helper::create_username($ltiuser->consumerkey, $member->user_id); 163 $user->firstname = \core_user::clean_field($member->person_name_given, 'firstname'); 164 $user->lastname = \core_user::clean_field($member->person_name_family, 'lastname'); 165 $user->email = \core_user::clean_field($member->person_contact_email_primary, 'email'); 166 167 // Get the user data from the LTI consumer. 168 $user = \enrol_lti\helper::assign_user_tool_data($tool, $user); 169 170 if (!$dbuser = $DB->get_record('user', array('username' => $user->username, 'deleted' => 0))) { 171 if ($tool->membersyncmode == \enrol_lti\helper::MEMBER_SYNC_ENROL_AND_UNENROL || 172 $tool->membersyncmode == \enrol_lti\helper::MEMBER_SYNC_ENROL_NEW) { 173 // If the email was stripped/not set then fill it with a default one. This 174 // stops the user from being redirected to edit their profile page. 175 if (empty($user->email)) { 176 $user->email = $user->username . "@example.com"; 177 } 178 179 $user->auth = 'lti'; 180 $user->id = user_create_user($user); 181 182 // Add the information to the necessary arrays. 183 $currentusers[] = $user->id; 184 $userphotos[$user->id] = $member->user_image; 185 } 186 } else { 187 // If email is empty remove it, so we don't update the user with an empty email. 188 if (empty($user->email)) { 189 unset($user->email); 190 } 191 192 $user->id = $dbuser->id; 193 user_update_user($user); 194 195 // Add the information to the necessary arrays. 196 $currentusers[] = $user->id; 197 $userphotos[$user->id] = $member->user_image; 198 } 199 if ($tool->membersyncmode == \enrol_lti\helper::MEMBER_SYNC_ENROL_AND_UNENROL || 200 $tool->membersyncmode == \enrol_lti\helper::MEMBER_SYNC_ENROL_NEW) { 201 // Enrol the user in the course. 202 \enrol_lti\helper::enrol_user($tool, $user->id); 203 } 204 } 205 } 206 // Now we check if we have to unenrol users who were not listed. 207 if ($tool->membersyncmode == \enrol_lti\helper::MEMBER_SYNC_ENROL_AND_UNENROL || 208 $tool->membersyncmode == \enrol_lti\helper::MEMBER_SYNC_UNENROL_MISSING) { 209 // Go through the users and check if any were never listed, if so, remove them. 210 foreach ($ltiusers as $ltiuser) { 211 if (!in_array($ltiuser->userid, $currentusers)) { 212 $instance = new \stdClass(); 213 $instance->id = $tool->enrolid; 214 $instance->courseid = $tool->courseid; 215 $instance->enrol = 'lti'; 216 $ltiplugin->unenrol_user($instance, $ltiuser->id); 217 } 218 } 219 } 220 } 221 mtrace("Completed - Synced members for tool '$tool->id' in the course '$tool->courseid'. " . 222 "Processed $usercount users; enrolled $enrolcount members; unenrolled $unenrolcount members."); 223 mtrace(""); 224 } 225 226 // Sync the user profile photos. 227 mtrace("Started - Syncing user profile images."); 228 $counter = 0; 229 if (!empty($userphotos)) { 230 foreach ($userphotos as $userid => $url) { 231 if ($url) { 232 $result = \enrol_lti\helper::update_user_profile_image($userid, $url); 233 if ($result === \enrol_lti\helper::PROFILE_IMAGE_UPDATE_SUCCESSFUL) { 234 $counter++; 235 mtrace("Profile image succesfully downloaded and created for user '$userid' from $url."); 236 } else { 237 mtrace($result); 238 } 239 } 240 } 241 } 242 mtrace("Completed - Synced $counter profile images."); 243 } 244 } 245 }
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 |