| 1 | efrain | 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 |  * LTI enrolment plugin helper.
 | 
        
           |  |  | 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;
 | 
        
           |  |  | 26 |   | 
        
           |  |  | 27 | defined('MOODLE_INTERNAL') || die();
 | 
        
           |  |  | 28 |   | 
        
           |  |  | 29 | /**
 | 
        
           |  |  | 30 |  * LTI enrolment plugin helper class.
 | 
        
           |  |  | 31 |  *
 | 
        
           |  |  | 32 |  * @package enrol_lti
 | 
        
           |  |  | 33 |  * @copyright 2016 Mark Nelson <markn@moodle.com>
 | 
        
           |  |  | 34 |  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 35 |  */
 | 
        
           |  |  | 36 | class helper {
 | 
        
           |  |  | 37 |     /*
 | 
        
           |  |  | 38 |      * The value used when we want to enrol new members and unenrol old ones.
 | 
        
           |  |  | 39 |      */
 | 
        
           |  |  | 40 |     const MEMBER_SYNC_ENROL_AND_UNENROL = 1;
 | 
        
           |  |  | 41 |   | 
        
           |  |  | 42 |     /*
 | 
        
           |  |  | 43 |      * The value used when we want to enrol new members only.
 | 
        
           |  |  | 44 |      */
 | 
        
           |  |  | 45 |     const MEMBER_SYNC_ENROL_NEW = 2;
 | 
        
           |  |  | 46 |   | 
        
           |  |  | 47 |     /*
 | 
        
           |  |  | 48 |      * The value used when we want to unenrol missing users.
 | 
        
           |  |  | 49 |      */
 | 
        
           |  |  | 50 |     const MEMBER_SYNC_UNENROL_MISSING = 3;
 | 
        
           |  |  | 51 |   | 
        
           |  |  | 52 |     /**
 | 
        
           |  |  | 53 |      * Code for when an enrolment was successful.
 | 
        
           |  |  | 54 |      */
 | 
        
           |  |  | 55 |     const ENROLMENT_SUCCESSFUL = true;
 | 
        
           |  |  | 56 |   | 
        
           |  |  | 57 |     /**
 | 
        
           |  |  | 58 |      * Error code for enrolment when max enrolled reached.
 | 
        
           |  |  | 59 |      */
 | 
        
           |  |  | 60 |     const ENROLMENT_MAX_ENROLLED = 'maxenrolledreached';
 | 
        
           |  |  | 61 |   | 
        
           |  |  | 62 |     /**
 | 
        
           |  |  | 63 |      * Error code for enrolment has not started.
 | 
        
           |  |  | 64 |      */
 | 
        
           |  |  | 65 |     const ENROLMENT_NOT_STARTED = 'enrolmentnotstarted';
 | 
        
           |  |  | 66 |   | 
        
           |  |  | 67 |     /**
 | 
        
           |  |  | 68 |      * Error code for enrolment when enrolment has finished.
 | 
        
           |  |  | 69 |      */
 | 
        
           |  |  | 70 |     const ENROLMENT_FINISHED = 'enrolmentfinished';
 | 
        
           |  |  | 71 |   | 
        
           |  |  | 72 |     /**
 | 
        
           |  |  | 73 |      * Error code for when an image file fails to upload.
 | 
        
           |  |  | 74 |      */
 | 
        
           |  |  | 75 |     const PROFILE_IMAGE_UPDATE_SUCCESSFUL = true;
 | 
        
           |  |  | 76 |   | 
        
           |  |  | 77 |     /**
 | 
        
           |  |  | 78 |      * Error code for when an image file fails to upload.
 | 
        
           |  |  | 79 |      */
 | 
        
           |  |  | 80 |     const PROFILE_IMAGE_UPDATE_FAILED = 'profileimagefailed';
 | 
        
           |  |  | 81 |   | 
        
           |  |  | 82 |     /**
 | 
        
           |  |  | 83 |      * Creates a unique username.
 | 
        
           |  |  | 84 |      *
 | 
        
           |  |  | 85 |      * @param string $consumerkey Consumer key
 | 
        
           |  |  | 86 |      * @param string $ltiuserid External tool user id
 | 
        
           |  |  | 87 |      * @return string The new username
 | 
        
           |  |  | 88 |      */
 | 
        
           |  |  | 89 |     public static function create_username($consumerkey, $ltiuserid) {
 | 
        
           |  |  | 90 |         if (!empty($ltiuserid) && !empty($consumerkey)) {
 | 
        
           |  |  | 91 |             $userkey = $consumerkey . ':' . $ltiuserid;
 | 
        
           |  |  | 92 |         } else {
 | 
        
           |  |  | 93 |             $userkey = false;
 | 
        
           |  |  | 94 |         }
 | 
        
           |  |  | 95 |   | 
        
           |  |  | 96 |         return 'enrol_lti' . sha1($consumerkey . '::' . $userkey);
 | 
        
           |  |  | 97 |     }
 | 
        
           |  |  | 98 |   | 
        
           |  |  | 99 |     /**
 | 
        
           |  |  | 100 |      * Adds default values for the user object based on the tool provided.
 | 
        
           |  |  | 101 |      *
 | 
        
           |  |  | 102 |      * @param \stdClass $tool
 | 
        
           |  |  | 103 |      * @param \stdClass $user
 | 
        
           |  |  | 104 |      * @return \stdClass The $user class with added default values
 | 
        
           |  |  | 105 |      */
 | 
        
           |  |  | 106 |     public static function assign_user_tool_data($tool, $user) {
 | 
        
           |  |  | 107 |         global $CFG;
 | 
        
           |  |  | 108 |   | 
        
           |  |  | 109 |         $user->city = (!empty($tool->city)) ? $tool->city : "";
 | 
        
           |  |  | 110 |         $user->country = (!empty($tool->country)) ? $tool->country : "";
 | 
        
           |  |  | 111 |         $user->institution = (!empty($tool->institution)) ? $tool->institution : "";
 | 
        
           |  |  | 112 |         $user->timezone = (!empty($tool->timezone)) ? $tool->timezone : "";
 | 
        
           |  |  | 113 |         if (isset($tool->maildisplay)) {
 | 
        
           |  |  | 114 |             $user->maildisplay = $tool->maildisplay;
 | 
        
           |  |  | 115 |         } else if (isset($CFG->defaultpreference_maildisplay)) {
 | 
        
           |  |  | 116 |             $user->maildisplay = $CFG->defaultpreference_maildisplay;
 | 
        
           |  |  | 117 |         } else {
 | 
        
           |  |  | 118 |             $user->maildisplay = 2;
 | 
        
           |  |  | 119 |         }
 | 
        
           |  |  | 120 |         $user->mnethostid = $CFG->mnet_localhost_id;
 | 
        
           |  |  | 121 |         $user->confirmed = 1;
 | 
        
           |  |  | 122 |         $user->lang = $tool->lang;
 | 
        
           |  |  | 123 |   | 
        
           |  |  | 124 |         return $user;
 | 
        
           |  |  | 125 |     }
 | 
        
           |  |  | 126 |   | 
        
           |  |  | 127 |     /**
 | 
        
           |  |  | 128 |      * Compares two users.
 | 
        
           |  |  | 129 |      *
 | 
        
           |  |  | 130 |      * @param \stdClass $newuser The new user
 | 
        
           |  |  | 131 |      * @param \stdClass $olduser The old user
 | 
        
           |  |  | 132 |      * @return bool True if both users are the same
 | 
        
           |  |  | 133 |      */
 | 
        
           |  |  | 134 |     public static function user_match($newuser, $olduser) {
 | 
        
           |  |  | 135 |         if ($newuser->firstname != $olduser->firstname) {
 | 
        
           |  |  | 136 |             return false;
 | 
        
           |  |  | 137 |         }
 | 
        
           |  |  | 138 |         if ($newuser->lastname != $olduser->lastname) {
 | 
        
           |  |  | 139 |             return false;
 | 
        
           |  |  | 140 |         }
 | 
        
           |  |  | 141 |         if ($newuser->email != $olduser->email) {
 | 
        
           |  |  | 142 |             return false;
 | 
        
           |  |  | 143 |         }
 | 
        
           |  |  | 144 |         if ($newuser->city != $olduser->city) {
 | 
        
           |  |  | 145 |             return false;
 | 
        
           |  |  | 146 |         }
 | 
        
           |  |  | 147 |         if ($newuser->country != $olduser->country) {
 | 
        
           |  |  | 148 |             return false;
 | 
        
           |  |  | 149 |         }
 | 
        
           |  |  | 150 |         if ($newuser->institution != $olduser->institution) {
 | 
        
           |  |  | 151 |             return false;
 | 
        
           |  |  | 152 |         }
 | 
        
           |  |  | 153 |         if ($newuser->timezone != $olduser->timezone) {
 | 
        
           |  |  | 154 |             return false;
 | 
        
           |  |  | 155 |         }
 | 
        
           |  |  | 156 |         if ($newuser->maildisplay != $olduser->maildisplay) {
 | 
        
           |  |  | 157 |             return false;
 | 
        
           |  |  | 158 |         }
 | 
        
           |  |  | 159 |         if ($newuser->mnethostid != $olduser->mnethostid) {
 | 
        
           |  |  | 160 |             return false;
 | 
        
           |  |  | 161 |         }
 | 
        
           |  |  | 162 |         if ($newuser->confirmed != $olduser->confirmed) {
 | 
        
           |  |  | 163 |             return false;
 | 
        
           |  |  | 164 |         }
 | 
        
           |  |  | 165 |         if ($newuser->lang != $olduser->lang) {
 | 
        
           |  |  | 166 |             return false;
 | 
        
           |  |  | 167 |         }
 | 
        
           |  |  | 168 |   | 
        
           |  |  | 169 |         return true;
 | 
        
           |  |  | 170 |     }
 | 
        
           |  |  | 171 |   | 
        
           |  |  | 172 |     /**
 | 
        
           |  |  | 173 |      * Updates the users profile image.
 | 
        
           |  |  | 174 |      *
 | 
        
           |  |  | 175 |      * @param int $userid the id of the user
 | 
        
           |  |  | 176 |      * @param string $url the url of the image
 | 
        
           |  |  | 177 |      * @return bool|string true if successful, else a string explaining why it failed
 | 
        
           |  |  | 178 |      */
 | 
        
           |  |  | 179 |     public static function update_user_profile_image($userid, $url) {
 | 
        
           |  |  | 180 |         global $CFG, $DB;
 | 
        
           |  |  | 181 |   | 
        
           |  |  | 182 |         require_once($CFG->libdir . '/filelib.php');
 | 
        
           |  |  | 183 |         require_once($CFG->libdir . '/gdlib.php');
 | 
        
           |  |  | 184 |   | 
        
           |  |  | 185 |         $fs = get_file_storage();
 | 
        
           |  |  | 186 |   | 
        
           |  |  | 187 |         $context = \context_user::instance($userid, MUST_EXIST);
 | 
        
           |  |  | 188 |         $fs->delete_area_files($context->id, 'user', 'newicon');
 | 
        
           |  |  | 189 |   | 
        
           |  |  | 190 |         $filerecord = array(
 | 
        
           |  |  | 191 |             'contextid' => $context->id,
 | 
        
           |  |  | 192 |             'component' => 'user',
 | 
        
           |  |  | 193 |             'filearea' => 'newicon',
 | 
        
           |  |  | 194 |             'itemid' => 0,
 | 
        
           |  |  | 195 |             'filepath' => '/'
 | 
        
           |  |  | 196 |         );
 | 
        
           |  |  | 197 |   | 
        
           |  |  | 198 |         $urlparams = array(
 | 
        
           |  |  | 199 |             'calctimeout' => false,
 | 
        
           |  |  | 200 |             'timeout' => 5,
 | 
        
           |  |  | 201 |             'skipcertverify' => true,
 | 
        
           |  |  | 202 |             'connecttimeout' => 5
 | 
        
           |  |  | 203 |         );
 | 
        
           |  |  | 204 |   | 
        
           |  |  | 205 |         try {
 | 
        
           |  |  | 206 |             $fs->create_file_from_url($filerecord, $url, $urlparams);
 | 
        
           |  |  | 207 |         } catch (\file_exception $e) {
 | 
        
           |  |  | 208 |             return get_string($e->errorcode, $e->module, $e->a);
 | 
        
           |  |  | 209 |         }
 | 
        
           |  |  | 210 |   | 
        
           |  |  | 211 |         $iconfile = $fs->get_area_files($context->id, 'user', 'newicon', false, 'itemid', false);
 | 
        
           |  |  | 212 |   | 
        
           |  |  | 213 |         // There should only be one.
 | 
        
           |  |  | 214 |         $iconfile = reset($iconfile);
 | 
        
           |  |  | 215 |   | 
        
           |  |  | 216 |         // Something went wrong while creating temp file - remove the uploaded file.
 | 
        
           |  |  | 217 |         if (!$iconfile = $iconfile->copy_content_to_temp()) {
 | 
        
           |  |  | 218 |             $fs->delete_area_files($context->id, 'user', 'newicon');
 | 
        
           |  |  | 219 |             return self::PROFILE_IMAGE_UPDATE_FAILED;
 | 
        
           |  |  | 220 |         }
 | 
        
           |  |  | 221 |   | 
        
           |  |  | 222 |         // Copy file to temporary location and the send it for processing icon.
 | 
        
           |  |  | 223 |         $newpicture = (int) process_new_icon($context, 'user', 'icon', 0, $iconfile);
 | 
        
           |  |  | 224 |         // Delete temporary file.
 | 
        
           |  |  | 225 |         @unlink($iconfile);
 | 
        
           |  |  | 226 |         // Remove uploaded file.
 | 
        
           |  |  | 227 |         $fs->delete_area_files($context->id, 'user', 'newicon');
 | 
        
           |  |  | 228 |         // Set the user's picture.
 | 
        
           |  |  | 229 |         $DB->set_field('user', 'picture', $newpicture, array('id' => $userid));
 | 
        
           |  |  | 230 |         return self::PROFILE_IMAGE_UPDATE_SUCCESSFUL;
 | 
        
           |  |  | 231 |     }
 | 
        
           |  |  | 232 |   | 
        
           |  |  | 233 |     /**
 | 
        
           |  |  | 234 |      * Enrol a user in a course.
 | 
        
           |  |  | 235 |      *
 | 
        
           |  |  | 236 |      * @param \stdclass $tool The tool object (retrieved using self::get_lti_tool() or self::get_lti_tools())
 | 
        
           |  |  | 237 |      * @param int $userid The user id
 | 
        
           |  |  | 238 |      * @return bool|string returns true if successful, else an error code
 | 
        
           |  |  | 239 |      */
 | 
        
           |  |  | 240 |     public static function enrol_user($tool, $userid) {
 | 
        
           |  |  | 241 |         global $DB;
 | 
        
           |  |  | 242 |   | 
        
           |  |  | 243 |         // Check if the user enrolment exists.
 | 
        
           |  |  | 244 |         if (!$DB->record_exists('user_enrolments', array('enrolid' => $tool->enrolid, 'userid' => $userid))) {
 | 
        
           |  |  | 245 |             // Check if the maximum enrolled limit has been met.
 | 
        
           |  |  | 246 |             if ($tool->maxenrolled) {
 | 
        
           |  |  | 247 |                 if ($DB->count_records('user_enrolments', array('enrolid' => $tool->enrolid)) >= $tool->maxenrolled) {
 | 
        
           |  |  | 248 |                     return self::ENROLMENT_MAX_ENROLLED;
 | 
        
           |  |  | 249 |                 }
 | 
        
           |  |  | 250 |             }
 | 
        
           |  |  | 251 |             // Check if the enrolment has not started.
 | 
        
           |  |  | 252 |             if ($tool->enrolstartdate && time() < $tool->enrolstartdate) {
 | 
        
           |  |  | 253 |                 return self::ENROLMENT_NOT_STARTED;
 | 
        
           |  |  | 254 |             }
 | 
        
           |  |  | 255 |             // Check if the enrolment has finished.
 | 
        
           |  |  | 256 |             if ($tool->enrolenddate && time() > $tool->enrolenddate) {
 | 
        
           |  |  | 257 |                 return self::ENROLMENT_FINISHED;
 | 
        
           |  |  | 258 |             }
 | 
        
           |  |  | 259 |   | 
        
           |  |  | 260 |             $timeend = 0;
 | 
        
           |  |  | 261 |             if ($tool->enrolperiod) {
 | 
        
           |  |  | 262 |                 $timeend = time() + $tool->enrolperiod;
 | 
        
           |  |  | 263 |             }
 | 
        
           |  |  | 264 |   | 
        
           |  |  | 265 |             // Finally, enrol the user.
 | 
        
           |  |  | 266 |             $instance = new \stdClass();
 | 
        
           |  |  | 267 |             $instance->id = $tool->enrolid;
 | 
        
           |  |  | 268 |             $instance->courseid = $tool->courseid;
 | 
        
           |  |  | 269 |             $instance->enrol = 'lti';
 | 
        
           |  |  | 270 |             $instance->status = $tool->status;
 | 
        
           |  |  | 271 |             $ltienrol = enrol_get_plugin('lti');
 | 
        
           |  |  | 272 |   | 
        
           |  |  | 273 |             // Hack - need to do this to workaround DB caching hack. See MDL-53977.
 | 
        
           |  |  | 274 |             $timestart = intval(substr(time(), 0, 8) . '00') - 1;
 | 
        
           |  |  | 275 |             $ltienrol->enrol_user($instance, $userid, null, $timestart, $timeend);
 | 
        
           |  |  | 276 |         }
 | 
        
           |  |  | 277 |   | 
        
           |  |  | 278 |         return self::ENROLMENT_SUCCESSFUL;
 | 
        
           |  |  | 279 |     }
 | 
        
           |  |  | 280 |   | 
        
           |  |  | 281 |     /**
 | 
        
           |  |  | 282 |      * Returns the LTI tool.
 | 
        
           |  |  | 283 |      *
 | 
        
           |  |  | 284 |      * @param int $toolid
 | 
        
           |  |  | 285 |      * @return \stdClass the tool
 | 
        
           |  |  | 286 |      */
 | 
        
           |  |  | 287 |     public static function get_lti_tool($toolid) {
 | 
        
           |  |  | 288 |         global $DB;
 | 
        
           |  |  | 289 |   | 
        
           |  |  | 290 |         $sql = "SELECT elt.*, e.name, e.courseid, e.status, e.enrolstartdate, e.enrolenddate, e.enrolperiod
 | 
        
           |  |  | 291 |                   FROM {enrol_lti_tools} elt
 | 
        
           |  |  | 292 |                   JOIN {enrol} e
 | 
        
           |  |  | 293 |                     ON elt.enrolid = e.id
 | 
        
           |  |  | 294 |                  WHERE elt.id = :tid";
 | 
        
           |  |  | 295 |   | 
        
           |  |  | 296 |         return $DB->get_record_sql($sql, array('tid' => $toolid), MUST_EXIST);
 | 
        
           |  |  | 297 |     }
 | 
        
           |  |  | 298 |   | 
        
           |  |  | 299 |     /**
 | 
        
           |  |  | 300 |      * Returns the LTI tools requested.
 | 
        
           |  |  | 301 |      *
 | 
        
           |  |  | 302 |      * @param array $params The list of SQL params (eg. array('columnname' => value, 'columnname2' => value)).
 | 
        
           |  |  | 303 |      * @param int $limitfrom return a subset of records, starting at this point (optional).
 | 
        
           |  |  | 304 |      * @param int $limitnum return a subset comprising this many records in total
 | 
        
           |  |  | 305 |      * @return array of tools
 | 
        
           |  |  | 306 |      */
 | 
        
           |  |  | 307 |     public static function get_lti_tools($params = array(), $limitfrom = 0, $limitnum = 0) {
 | 
        
           |  |  | 308 |         global $DB;
 | 
        
           |  |  | 309 |   | 
        
           |  |  | 310 |         $sql = "SELECT elt.*, e.name, e.courseid, e.status, e.enrolstartdate, e.enrolenddate, e.enrolperiod
 | 
        
           |  |  | 311 |                   FROM {enrol_lti_tools} elt
 | 
        
           |  |  | 312 |                   JOIN {enrol} e
 | 
        
           |  |  | 313 |                     ON elt.enrolid = e.id";
 | 
        
           |  |  | 314 |         if ($params) {
 | 
        
           |  |  | 315 |             $where = "WHERE";
 | 
        
           |  |  | 316 |             foreach ($params as $colname => $value) {
 | 
        
           |  |  | 317 |                 $sql .= " $where $colname = :$colname";
 | 
        
           |  |  | 318 |                 $where = "AND";
 | 
        
           |  |  | 319 |             }
 | 
        
           |  |  | 320 |         }
 | 
        
           |  |  | 321 |         $sql .= " ORDER BY elt.timecreated";
 | 
        
           |  |  | 322 |   | 
        
           |  |  | 323 |         return $DB->get_records_sql($sql, $params, $limitfrom, $limitnum);
 | 
        
           |  |  | 324 |     }
 | 
        
           |  |  | 325 |   | 
        
           |  |  | 326 |     /**
 | 
        
           |  |  | 327 |      * Returns the number of LTI tools.
 | 
        
           |  |  | 328 |      *
 | 
        
           |  |  | 329 |      * @param array $params The list of SQL params (eg. array('columnname' => value, 'columnname2' => value)).
 | 
        
           |  |  | 330 |      * @return int The number of tools
 | 
        
           |  |  | 331 |      */
 | 
        
           |  |  | 332 |     public static function count_lti_tools($params = array()) {
 | 
        
           |  |  | 333 |         global $DB;
 | 
        
           |  |  | 334 |   | 
        
           |  |  | 335 |         $sql = "SELECT COUNT(*)
 | 
        
           |  |  | 336 |                   FROM {enrol_lti_tools} elt
 | 
        
           |  |  | 337 |                   JOIN {enrol} e
 | 
        
           |  |  | 338 |                     ON elt.enrolid = e.id";
 | 
        
           |  |  | 339 |         if ($params) {
 | 
        
           |  |  | 340 |             $where = "WHERE";
 | 
        
           |  |  | 341 |             foreach ($params as $colname => $value) {
 | 
        
           |  |  | 342 |                 $sql .= " $where $colname = :$colname";
 | 
        
           |  |  | 343 |                 $where = "AND";
 | 
        
           |  |  | 344 |             }
 | 
        
           |  |  | 345 |         }
 | 
        
           |  |  | 346 |   | 
        
           |  |  | 347 |         return $DB->count_records_sql($sql, $params);
 | 
        
           |  |  | 348 |     }
 | 
        
           |  |  | 349 |   | 
        
           |  |  | 350 |     /**
 | 
        
           |  |  | 351 |      * Create a IMS POX body request for sync grades.
 | 
        
           |  |  | 352 |      *
 | 
        
           |  |  | 353 |      * @param string $source Sourceid required for the request
 | 
        
           |  |  | 354 |      * @param float $grade User final grade
 | 
        
           |  |  | 355 |      * @return string
 | 
        
           |  |  | 356 |      */
 | 
        
           |  |  | 357 |     public static function create_service_body($source, $grade) {
 | 
        
           |  |  | 358 |         return '<?xml version="1.0" encoding="UTF-8"?>
 | 
        
           |  |  | 359 |             <imsx_POXEnvelopeRequest xmlns="http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0">
 | 
        
           |  |  | 360 |               <imsx_POXHeader>
 | 
        
           |  |  | 361 |                 <imsx_POXRequestHeaderInfo>
 | 
        
           |  |  | 362 |                   <imsx_version>V1.0</imsx_version>
 | 
        
           |  |  | 363 |                   <imsx_messageIdentifier>' . (time()) . '</imsx_messageIdentifier>
 | 
        
           |  |  | 364 |                 </imsx_POXRequestHeaderInfo>
 | 
        
           |  |  | 365 |               </imsx_POXHeader>
 | 
        
           |  |  | 366 |               <imsx_POXBody>
 | 
        
           |  |  | 367 |                 <replaceResultRequest>
 | 
        
           |  |  | 368 |                   <resultRecord>
 | 
        
           |  |  | 369 |                     <sourcedGUID>
 | 
        
           |  |  | 370 |                       <sourcedId>' . $source . '</sourcedId>
 | 
        
           |  |  | 371 |                     </sourcedGUID>
 | 
        
           |  |  | 372 |                     <result>
 | 
        
           |  |  | 373 |                       <resultScore>
 | 
        
           |  |  | 374 |                         <language>en-us</language>
 | 
        
           |  |  | 375 |                         <textString>' . $grade . '</textString>
 | 
        
           |  |  | 376 |                       </resultScore>
 | 
        
           |  |  | 377 |                     </result>
 | 
        
           |  |  | 378 |                   </resultRecord>
 | 
        
           |  |  | 379 |                 </replaceResultRequest>
 | 
        
           |  |  | 380 |               </imsx_POXBody>
 | 
        
           |  |  | 381 |             </imsx_POXEnvelopeRequest>';
 | 
        
           |  |  | 382 |     }
 | 
        
           |  |  | 383 |   | 
        
           |  |  | 384 |     /**
 | 
        
           |  |  | 385 |      * Returns the url to launch the lti tool.
 | 
        
           |  |  | 386 |      *
 | 
        
           |  |  | 387 |      * @param int $toolid the id of the shared tool
 | 
        
           |  |  | 388 |      * @return \moodle_url the url to launch the tool
 | 
        
           |  |  | 389 |      * @since Moodle 3.2
 | 
        
           |  |  | 390 |      */
 | 
        
           |  |  | 391 |     public static function get_launch_url($toolid) {
 | 
        
           |  |  | 392 |         return new \moodle_url('/enrol/lti/tool.php', array('id' => $toolid));
 | 
        
           |  |  | 393 |     }
 | 
        
           |  |  | 394 |   | 
        
           |  |  | 395 |     /**
 | 
        
           |  |  | 396 |      * Returns the name of the lti enrolment instance, or the name of the course/module being shared.
 | 
        
           |  |  | 397 |      *
 | 
        
           |  |  | 398 |      * @param \stdClass $tool The lti tool
 | 
        
           |  |  | 399 |      * @return string The name of the tool
 | 
        
           |  |  | 400 |      * @since Moodle 3.2
 | 
        
           |  |  | 401 |      */
 | 
        
           |  |  | 402 |     public static function get_name($tool) {
 | 
        
           |  |  | 403 |         $name = null;
 | 
        
           |  |  | 404 |   | 
        
           |  |  | 405 |         if (empty($tool->name)) {
 | 
        
           |  |  | 406 |             $toolcontext = \context::instance_by_id($tool->contextid);
 | 
        
           |  |  | 407 |             $name = $toolcontext->get_context_name();
 | 
        
           |  |  | 408 |         } else {
 | 
        
           |  |  | 409 |             $name = $tool->name;
 | 
        
           |  |  | 410 |         };
 | 
        
           |  |  | 411 |   | 
        
           |  |  | 412 |         return $name;
 | 
        
           |  |  | 413 |     }
 | 
        
           |  |  | 414 |   | 
        
           |  |  | 415 |     /**
 | 
        
           |  |  | 416 |      * Returns a description of the course or module that this lti instance points to.
 | 
        
           |  |  | 417 |      *
 | 
        
           |  |  | 418 |      * @param \stdClass $tool The lti tool
 | 
        
           |  |  | 419 |      * @return string A description of the tool
 | 
        
           |  |  | 420 |      * @since Moodle 3.2
 | 
        
           |  |  | 421 |      */
 | 
        
           |  |  | 422 |     public static function get_description($tool) {
 | 
        
           |  |  | 423 |         global $DB;
 | 
        
           |  |  | 424 |         $description = '';
 | 
        
           |  |  | 425 |         $context = \context::instance_by_id($tool->contextid);
 | 
        
           |  |  | 426 |         if ($context->contextlevel == CONTEXT_COURSE) {
 | 
        
           |  |  | 427 |             $course = $DB->get_record('course', array('id' => $context->instanceid));
 | 
        
           |  |  | 428 |             $description = $course->summary;
 | 
        
           |  |  | 429 |         } else if ($context->contextlevel == CONTEXT_MODULE) {
 | 
        
           |  |  | 430 |             $cmid = $context->instanceid;
 | 
        
           |  |  | 431 |             $cm = get_coursemodule_from_id(false, $context->instanceid, 0, false, MUST_EXIST);
 | 
        
           |  |  | 432 |             $module = $DB->get_record($cm->modname, array('id' => $cm->instance));
 | 
        
           |  |  | 433 |             $description = $module->intro;
 | 
        
           |  |  | 434 |         }
 | 
        
           |  |  | 435 |         return trim(html_to_text($description));
 | 
        
           |  |  | 436 |     }
 | 
        
           |  |  | 437 |   | 
        
           |  |  | 438 |     /**
 | 
        
           |  |  | 439 |      * Returns the icon of the tool.
 | 
        
           |  |  | 440 |      *
 | 
        
           |  |  | 441 |      * @param \stdClass $tool The lti tool
 | 
        
           |  |  | 442 |      * @return \moodle_url A url to the icon of the tool
 | 
        
           |  |  | 443 |      * @since Moodle 3.2
 | 
        
           |  |  | 444 |      */
 | 
        
           |  |  | 445 |     public static function get_icon($tool) {
 | 
        
           |  |  | 446 |         global $OUTPUT;
 | 
        
           |  |  | 447 |         return $OUTPUT->favicon();
 | 
        
           |  |  | 448 |     }
 | 
        
           |  |  | 449 |   | 
        
           |  |  | 450 |     /**
 | 
        
           |  |  | 451 |      * Returns the url to the cartridge representing the tool.
 | 
        
           |  |  | 452 |      *
 | 
        
           |  |  | 453 |      * If you have slash arguments enabled, this will be a nice url ending in cartridge.xml.
 | 
        
           |  |  | 454 |      * If not it will be a php page with some parameters passed.
 | 
        
           |  |  | 455 |      *
 | 
        
           |  |  | 456 |      * @param \stdClass $tool The lti tool
 | 
        
           |  |  | 457 |      * @return string The url to the cartridge representing the tool
 | 
        
           |  |  | 458 |      * @since Moodle 3.2
 | 
        
           |  |  | 459 |      */
 | 
        
           |  |  | 460 |     public static function get_cartridge_url($tool) {
 | 
        
           |  |  | 461 |         global $CFG;
 | 
        
           |  |  | 462 |         $url = null;
 | 
        
           |  |  | 463 |   | 
        
           |  |  | 464 |         $id = $tool->id;
 | 
        
           |  |  | 465 |         $token = self::generate_cartridge_token($tool->id);
 | 
        
           |  |  | 466 |         if ($CFG->slasharguments) {
 | 
        
           |  |  | 467 |             $url = new \moodle_url('/enrol/lti/cartridge.php/' . $id . '/' . $token . '/cartridge.xml');
 | 
        
           |  |  | 468 |         } else {
 | 
        
           |  |  | 469 |             $url = new \moodle_url('/enrol/lti/cartridge.php',
 | 
        
           |  |  | 470 |                     array(
 | 
        
           |  |  | 471 |                         'id' => $id,
 | 
        
           |  |  | 472 |                         'token' => $token
 | 
        
           |  |  | 473 |                     )
 | 
        
           |  |  | 474 |                 );
 | 
        
           |  |  | 475 |         }
 | 
        
           |  |  | 476 |         return $url;
 | 
        
           |  |  | 477 |     }
 | 
        
           |  |  | 478 |   | 
        
           |  |  | 479 |     /**
 | 
        
           |  |  | 480 |      * Returns the url to the tool proxy registration url.
 | 
        
           |  |  | 481 |      *
 | 
        
           |  |  | 482 |      * If you have slash arguments enabled, this will be a nice url ending in cartridge.xml.
 | 
        
           |  |  | 483 |      * If not it will be a php page with some parameters passed.
 | 
        
           |  |  | 484 |      *
 | 
        
           |  |  | 485 |      * @param \stdClass $tool The lti tool
 | 
        
           |  |  | 486 |      * @return string The url to the cartridge representing the tool
 | 
        
           |  |  | 487 |      */
 | 
        
           |  |  | 488 |     public static function get_proxy_url($tool) {
 | 
        
           |  |  | 489 |         global $CFG;
 | 
        
           |  |  | 490 |         $url = null;
 | 
        
           |  |  | 491 |   | 
        
           |  |  | 492 |         $id = $tool->id;
 | 
        
           |  |  | 493 |         $token = self::generate_proxy_token($tool->id);
 | 
        
           |  |  | 494 |         if ($CFG->slasharguments) {
 | 
        
           |  |  | 495 |             $url = new \moodle_url('/enrol/lti/proxy.php/' . $id . '/' . $token . '/');
 | 
        
           |  |  | 496 |         } else {
 | 
        
           |  |  | 497 |             $url = new \moodle_url('/enrol/lti/proxy.php',
 | 
        
           |  |  | 498 |                     array(
 | 
        
           |  |  | 499 |                         'id' => $id,
 | 
        
           |  |  | 500 |                         'token' => $token
 | 
        
           |  |  | 501 |                     )
 | 
        
           |  |  | 502 |                 );
 | 
        
           |  |  | 503 |         }
 | 
        
           |  |  | 504 |         return $url;
 | 
        
           |  |  | 505 |     }
 | 
        
           |  |  | 506 |   | 
        
           |  |  | 507 |     /**
 | 
        
           |  |  | 508 |      * Returns a unique hash for this site and this enrolment instance.
 | 
        
           |  |  | 509 |      *
 | 
        
           |  |  | 510 |      * Used to verify that the link to the cartridge has not just been guessed.
 | 
        
           |  |  | 511 |      *
 | 
        
           |  |  | 512 |      * @param int $toolid The id of the shared tool
 | 
        
           |  |  | 513 |      * @return string MD5 hash of combined site ID and enrolment instance ID.
 | 
        
           |  |  | 514 |      * @since Moodle 3.2
 | 
        
           |  |  | 515 |      */
 | 
        
           |  |  | 516 |     public static function generate_cartridge_token($toolid) {
 | 
        
           |  |  | 517 |         $siteidentifier = get_site_identifier();
 | 
        
           |  |  | 518 |         $checkhash = md5($siteidentifier . '_enrol_lti_cartridge_' . $toolid);
 | 
        
           |  |  | 519 |         return $checkhash;
 | 
        
           |  |  | 520 |     }
 | 
        
           |  |  | 521 |   | 
        
           |  |  | 522 |     /**
 | 
        
           |  |  | 523 |      * Returns a unique hash for this site and this enrolment instance.
 | 
        
           |  |  | 524 |      *
 | 
        
           |  |  | 525 |      * Used to verify that the link to the proxy has not just been guessed.
 | 
        
           |  |  | 526 |      *
 | 
        
           |  |  | 527 |      * @param int $toolid The id of the shared tool
 | 
        
           |  |  | 528 |      * @return string MD5 hash of combined site ID and enrolment instance ID.
 | 
        
           |  |  | 529 |      * @since Moodle 3.2
 | 
        
           |  |  | 530 |      */
 | 
        
           |  |  | 531 |     public static function generate_proxy_token($toolid) {
 | 
        
           |  |  | 532 |         $siteidentifier = get_site_identifier();
 | 
        
           |  |  | 533 |         $checkhash = md5($siteidentifier . '_enrol_lti_proxy_' . $toolid);
 | 
        
           |  |  | 534 |         return $checkhash;
 | 
        
           |  |  | 535 |     }
 | 
        
           |  |  | 536 |   | 
        
           |  |  | 537 |     /**
 | 
        
           |  |  | 538 |      * Verifies that the given token matches the cartridge token of the given shared tool.
 | 
        
           |  |  | 539 |      *
 | 
        
           |  |  | 540 |      * @param int $toolid The id of the shared tool
 | 
        
           |  |  | 541 |      * @param string $token hash for this site and this enrolment instance
 | 
        
           |  |  | 542 |      * @return boolean True if the token matches, false if it does not
 | 
        
           |  |  | 543 |      * @since Moodle 3.2
 | 
        
           |  |  | 544 |      */
 | 
        
           |  |  | 545 |     public static function verify_cartridge_token($toolid, $token) {
 | 
        
           |  |  | 546 |         return $token == self::generate_cartridge_token($toolid);
 | 
        
           |  |  | 547 |     }
 | 
        
           |  |  | 548 |   | 
        
           |  |  | 549 |     /**
 | 
        
           |  |  | 550 |      * Verifies that the given token matches the proxy token of the given shared tool.
 | 
        
           |  |  | 551 |      *
 | 
        
           |  |  | 552 |      * @param int $toolid The id of the shared tool
 | 
        
           |  |  | 553 |      * @param string $token hash for this site and this enrolment instance
 | 
        
           |  |  | 554 |      * @return boolean True if the token matches, false if it does not
 | 
        
           |  |  | 555 |      * @since Moodle 3.2
 | 
        
           |  |  | 556 |      */
 | 
        
           |  |  | 557 |     public static function verify_proxy_token($toolid, $token) {
 | 
        
           |  |  | 558 |         return $token == self::generate_proxy_token($toolid);
 | 
        
           |  |  | 559 |     }
 | 
        
           |  |  | 560 |   | 
        
           |  |  | 561 |     /**
 | 
        
           |  |  | 562 |      * Returns the parameters of the cartridge as an associative array of partial xpath.
 | 
        
           |  |  | 563 |      *
 | 
        
           |  |  | 564 |      * @param int $toolid The id of the shared tool
 | 
        
           |  |  | 565 |      * @return array Recursive associative array with partial xpath to be concatenated into an xpath expression
 | 
        
           |  |  | 566 |      *     before setting the value.
 | 
        
           |  |  | 567 |      * @since Moodle 3.2
 | 
        
           |  |  | 568 |      */
 | 
        
           |  |  | 569 |     protected static function get_cartridge_parameters($toolid) {
 | 
        
           |  |  | 570 |         global $PAGE, $SITE;
 | 
        
           |  |  | 571 |         $PAGE->set_context(\context_system::instance());
 | 
        
           |  |  | 572 |   | 
        
           |  |  | 573 |         // Get the tool.
 | 
        
           |  |  | 574 |         $tool = self::get_lti_tool($toolid);
 | 
        
           |  |  | 575 |   | 
        
           |  |  | 576 |         // Work out the name of the tool.
 | 
        
           |  |  | 577 |         $title = self::get_name($tool);
 | 
        
           |  |  | 578 |         $launchurl = self::get_launch_url($toolid);
 | 
        
           |  |  | 579 |         $launchurl = $launchurl->out(false);
 | 
        
           |  |  | 580 |         $iconurl = self::get_icon($tool);
 | 
        
           |  |  | 581 |         $iconurl = $iconurl->out(false);
 | 
        
           |  |  | 582 |         $securelaunchurl = null;
 | 
        
           |  |  | 583 |         $secureiconurl = null;
 | 
        
           |  |  | 584 |         $vendorurl = new \moodle_url('/');
 | 
        
           |  |  | 585 |         $vendorurl = $vendorurl->out(false);
 | 
        
           |  |  | 586 |         $description = self::get_description($tool);
 | 
        
           |  |  | 587 |   | 
        
           |  |  | 588 |         // If we are a https site, we can add the launch url and icon urls as secure equivalents.
 | 
        
           |  |  | 589 |         if (\is_https()) {
 | 
        
           |  |  | 590 |             $securelaunchurl = $launchurl;
 | 
        
           |  |  | 591 |             $secureiconurl = $iconurl;
 | 
        
           |  |  | 592 |         }
 | 
        
           |  |  | 593 |   | 
        
           |  |  | 594 |         return array(
 | 
        
           |  |  | 595 |                 "/cc:cartridge_basiclti_link" => array(
 | 
        
           |  |  | 596 |                     "/blti:title" => $title,
 | 
        
           |  |  | 597 |                     "/blti:description" => $description,
 | 
        
           |  |  | 598 |                     "/blti:extensions" => array(
 | 
        
           |  |  | 599 |                             "/lticm:property[@name='icon_url']" => $iconurl,
 | 
        
           |  |  | 600 |                             "/lticm:property[@name='secure_icon_url']" => $secureiconurl
 | 
        
           |  |  | 601 |                         ),
 | 
        
           |  |  | 602 |                     "/blti:launch_url" => $launchurl,
 | 
        
           |  |  | 603 |                     "/blti:secure_launch_url" => $securelaunchurl,
 | 
        
           |  |  | 604 |                     "/blti:icon" => $iconurl,
 | 
        
           |  |  | 605 |                     "/blti:secure_icon" => $secureiconurl,
 | 
        
           |  |  | 606 |                     "/blti:vendor" => array(
 | 
        
           |  |  | 607 |                             "/lticp:code" => $SITE->shortname,
 | 
        
           |  |  | 608 |                             "/lticp:name" => $SITE->fullname,
 | 
        
           |  |  | 609 |                             "/lticp:description" => trim(html_to_text($SITE->summary)),
 | 
        
           |  |  | 610 |                             "/lticp:url" => $vendorurl
 | 
        
           |  |  | 611 |                         )
 | 
        
           |  |  | 612 |                 )
 | 
        
           |  |  | 613 |             );
 | 
        
           |  |  | 614 |     }
 | 
        
           |  |  | 615 |   | 
        
           |  |  | 616 |     /**
 | 
        
           |  |  | 617 |      * Traverses a recursive associative array, setting the properties of the corresponding
 | 
        
           |  |  | 618 |      * xpath element.
 | 
        
           |  |  | 619 |      *
 | 
        
           |  |  | 620 |      * @param \DOMXPath $xpath The xpath with the xml to modify
 | 
        
           |  |  | 621 |      * @param array $parameters The array of xpaths to search through
 | 
        
           |  |  | 622 |      * @param string $prefix The current xpath prefix (gets longer the deeper into the array you go)
 | 
        
           |  |  | 623 |      * @return void
 | 
        
           |  |  | 624 |      * @since Moodle 3.2
 | 
        
           |  |  | 625 |      */
 | 
        
           |  |  | 626 |     protected static function set_xpath($xpath, $parameters, $prefix = '') {
 | 
        
           |  |  | 627 |         foreach ($parameters as $key => $value) {
 | 
        
           |  |  | 628 |             if (is_array($value)) {
 | 
        
           |  |  | 629 |                 self::set_xpath($xpath, $value, $prefix . $key);
 | 
        
           |  |  | 630 |             } else {
 | 
        
           |  |  | 631 |                 $result = @$xpath->query($prefix . $key);
 | 
        
           |  |  | 632 |                 if ($result) {
 | 
        
           |  |  | 633 |                     $node = $result->item(0);
 | 
        
           |  |  | 634 |                     if ($node) {
 | 
        
           |  |  | 635 |                         if (is_null($value)) {
 | 
        
           |  |  | 636 |                             $node->parentNode->removeChild($node);
 | 
        
           |  |  | 637 |                         } else {
 | 
        
           |  |  | 638 |                             $node->nodeValue = s($value);
 | 
        
           |  |  | 639 |                         }
 | 
        
           |  |  | 640 |                     }
 | 
        
           |  |  | 641 |                 } else {
 | 
        
           |  |  | 642 |                     throw new \coding_exception('Please check your XPATH and try again.');
 | 
        
           |  |  | 643 |                 }
 | 
        
           |  |  | 644 |             }
 | 
        
           |  |  | 645 |         }
 | 
        
           |  |  | 646 |     }
 | 
        
           |  |  | 647 |   | 
        
           |  |  | 648 |     /**
 | 
        
           |  |  | 649 |      * Create an IMS cartridge for the tool.
 | 
        
           |  |  | 650 |      *
 | 
        
           |  |  | 651 |      * @param int $toolid The id of the shared tool
 | 
        
           |  |  | 652 |      * @return string representing the generated cartridge
 | 
        
           |  |  | 653 |      * @since Moodle 3.2
 | 
        
           |  |  | 654 |      */
 | 
        
           |  |  | 655 |     public static function create_cartridge($toolid) {
 | 
        
           |  |  | 656 |         $cartridge = new \DOMDocument();
 | 
        
           |  |  | 657 |         $cartridge->load(realpath(__DIR__ . '/../xml/imslticc.xml'));
 | 
        
           |  |  | 658 |         $xpath = new \DOMXpath($cartridge);
 | 
        
           |  |  | 659 |         $xpath->registerNamespace('cc', 'http://www.imsglobal.org/xsd/imslticc_v1p0');
 | 
        
           |  |  | 660 |         $parameters = self::get_cartridge_parameters($toolid);
 | 
        
           |  |  | 661 |         self::set_xpath($xpath, $parameters);
 | 
        
           |  |  | 662 |   | 
        
           |  |  | 663 |         return $cartridge->saveXML();
 | 
        
           |  |  | 664 |     }
 | 
        
           |  |  | 665 | }
 |