Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403] [Versions 402 and 403]
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 web service endpoints 19 * 20 * @package mod_lti 21 * @copyright Copyright (c) 2011 Moodlerooms Inc. (http://www.moodlerooms.com) 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 * @author Chris Scribner 24 */ 25 26 define('NO_DEBUG_DISPLAY', true); 27 define('NO_MOODLE_COOKIES', true); 28 29 require_once(__DIR__ . "/../../config.php"); 30 require_once($CFG->dirroot.'/mod/lti/locallib.php'); 31 require_once($CFG->dirroot.'/mod/lti/servicelib.php'); 32 33 // TODO: Switch to core oauthlib once implemented - MDL-30149. 34 use mod_lti\service_exception_handler; 35 use moodle\mod\lti as lti; 36 use ltiservice_basicoutcomes\local\service\basicoutcomes; 37 38 $rawbody = file_get_contents("php://input"); 39 40 $logrequests = lti_should_log_request($rawbody); 41 $errorhandler = new service_exception_handler($logrequests); 42 43 // Register our own error handler so we can always send valid XML response. 44 set_exception_handler(array($errorhandler, 'handle')); 45 46 if ($logrequests) { 47 lti_log_request($rawbody); 48 } 49 50 $ok = true; 51 $type = null; 52 $toolproxy = false; 53 54 $consumerkey = lti\get_oauth_key_from_headers(null, array(basicoutcomes::SCOPE_BASIC_OUTCOMES)); 55 if ($consumerkey === false) { 56 throw new Exception('Missing or invalid consumer key or access token.'); 57 } else if (is_string($consumerkey)) { 58 $toolproxy = lti_get_tool_proxy_from_guid($consumerkey); 59 if ($toolproxy !== false) { 60 $secrets = array($toolproxy->secret); 61 } else if (!empty($tool)) { 62 $secrets = array($typeconfig['password']); 63 } else { 64 $secrets = lti_get_shared_secrets_by_key($consumerkey); 65 } 66 $sharedsecret = lti_verify_message($consumerkey, lti_get_shared_secrets_by_key($consumerkey), $rawbody); 67 if ($sharedsecret === false) { 68 throw new Exception('Message signature not valid'); 69 } 70 } 71 72 // TODO MDL-46023 Replace this code with a call to the new library. 73 $xml = simplexml_load_string($rawbody); 74 if (!$xml) { 75 throw new Exception('Invalid XML content'); 76 } 77 78 $body = $xml->imsx_POXBody; 79 foreach ($body->children() as $child) { 80 $messagetype = $child->getName(); 81 } 82 83 // We know more about the message, update error handler to send better errors. 84 $errorhandler->set_message_id(lti_parse_message_id($xml)); 85 $errorhandler->set_message_type($messagetype); 86 87 switch ($messagetype) { 88 case 'replaceResultRequest': 89 $parsed = lti_parse_grade_replace_message($xml); 90 91 $ltiinstance = $DB->get_record('lti', array('id' => $parsed->instanceid)); 92 93 if (!lti_accepts_grades($ltiinstance)) { 94 throw new Exception('Tool does not accept grades'); 95 } 96 97 lti_verify_sourcedid($ltiinstance, $parsed); 98 lti_set_session_user($parsed->userid); 99 100 $gradestatus = lti_update_grade($ltiinstance, $parsed->userid, $parsed->launchid, $parsed->gradeval); 101 102 if (!$gradestatus) { 103 throw new Exception('Grade replace response'); 104 } 105 106 $responsexml = lti_get_response_xml( 107 'success', 108 'Grade replace response', 109 $parsed->messageid, 110 'replaceResultResponse' 111 ); 112 113 echo $responsexml->asXML(); 114 115 break; 116 117 case 'readResultRequest': 118 $parsed = lti_parse_grade_read_message($xml); 119 120 $ltiinstance = $DB->get_record('lti', array('id' => $parsed->instanceid)); 121 122 if (!lti_accepts_grades($ltiinstance)) { 123 throw new Exception('Tool does not accept grades'); 124 } 125 126 // Getting the grade requires the context is set. 127 $context = context_course::instance($ltiinstance->course); 128 $PAGE->set_context($context); 129 130 lti_verify_sourcedid($ltiinstance, $parsed); 131 132 $grade = lti_read_grade($ltiinstance, $parsed->userid); 133 134 $responsexml = lti_get_response_xml( 135 'success', // Empty grade is also 'success'. 136 'Result read', 137 $parsed->messageid, 138 'readResultResponse' 139 ); 140 141 $node = $responsexml->imsx_POXBody->readResultResponse; 142 $node = $node->addChild('result')->addChild('resultScore'); 143 $node->addChild('language', 'en'); 144 $node->addChild('textString', isset($grade) ? $grade : ''); 145 146 echo $responsexml->asXML(); 147 148 break; 149 150 case 'deleteResultRequest': 151 $parsed = lti_parse_grade_delete_message($xml); 152 153 $ltiinstance = $DB->get_record('lti', array('id' => $parsed->instanceid)); 154 155 if (!lti_accepts_grades($ltiinstance)) { 156 throw new Exception('Tool does not accept grades'); 157 } 158 159 lti_verify_sourcedid($ltiinstance, $parsed); 160 lti_set_session_user($parsed->userid); 161 162 $gradestatus = lti_delete_grade($ltiinstance, $parsed->userid); 163 164 if (!$gradestatus) { 165 throw new Exception('Grade delete request'); 166 } 167 168 $responsexml = lti_get_response_xml( 169 'success', 170 'Grade delete request', 171 $parsed->messageid, 172 'deleteResultResponse' 173 ); 174 175 echo $responsexml->asXML(); 176 177 break; 178 179 default: 180 // Fire an event if we get a web service request which we don't support directly. 181 // This will allow others to extend the LTI services, which I expect to be a common 182 // use case, at least until the spec matures. 183 $data = new stdClass(); 184 $data->body = $rawbody; 185 $data->xml = $xml; 186 $data->messageid = lti_parse_message_id($xml); 187 $data->messagetype = $messagetype; 188 $data->consumerkey = $consumerkey; 189 $data->sharedsecret = $sharedsecret; 190 $eventdata = array(); 191 $eventdata['other'] = array(); 192 $eventdata['other']['messageid'] = $data->messageid; 193 $eventdata['other']['messagetype'] = $messagetype; 194 $eventdata['other']['consumerkey'] = $consumerkey; 195 196 // Before firing the event, allow subplugins a chance to handle. 197 if (lti_extend_lti_services($data)) { 198 break; 199 } 200 201 // If an event handler handles the web service, it should set this global to true 202 // So this code knows whether to send an "operation not supported" or not. 203 global $ltiwebservicehandled; 204 $ltiwebservicehandled = false; 205 206 try { 207 $event = \mod_lti\event\unknown_service_api_called::create($eventdata); 208 $event->set_message_data($data); 209 $event->trigger(); 210 } catch (Exception $e) { 211 $ltiwebservicehandled = false; 212 } 213 214 if (!$ltiwebservicehandled) { 215 $responsexml = lti_get_response_xml( 216 'unsupported', 217 'unsupported', 218 lti_parse_message_id($xml), 219 $messagetype 220 ); 221 222 echo $responsexml->asXML(); 223 } 224 225 break; 226 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body