Merge branch 'MDL-30328' of git://github.com/scriby/moodle
[moodle.git] / mod / lti / service.php
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/>.
17 /**
18  * LTI web service endpoints
19  *
20  * @package    mod
21  * @subpackage lti
22  * @copyright  Copyright (c) 2011 Moodlerooms Inc. (http://www.moodlerooms.com)
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  * @author     Chris Scribner
25  */
27 require_once(dirname(__FILE__) . "/../../config.php");
28 require_once($CFG->dirroot.'/mod/lti/locallib.php');
29 require_once($CFG->dirroot.'/mod/lti/servicelib.php');
31 // TODO: Switch to core oauthlib once implemented - MDL-30149
32 use moodle\mod\lti as lti;
34 $rawbody = file_get_contents("php://input");
36 foreach (getallheaders() as $name => $value) {
37     if ($name === 'Authorization') {
38         // TODO: Switch to core oauthlib once implemented - MDL-30149
39         $oauthparams = lti\OAuthUtil::split_header($value);
41         $consumerkey = $oauthparams['oauth_consumer_key'];
42         break;
43     }
44 }
46 if (empty($consumerkey)) {
47     throw new Exception('Consumer key is missing.');
48 }
50 $sharedsecret = lti_verify_message($consumerkey, lti_get_shared_secrets_by_key($consumerkey), $rawbody);
52 if ($sharedsecret === false) {
53     throw new Exception('Message signature not valid');
54 }
56 $xml = new SimpleXMLElement($rawbody);
58 $body = $xml->imsx_POXBody;
59 foreach ($body->children() as $child) {
60     $messagetype = $child->getName();
61 }
63 switch ($messagetype) {
64     case 'replaceResultRequest':
65         try {
66             $parsed = lti_parse_grade_replace_message($xml);
67         } catch (Exception $e) {
68             $responsexml = lti_get_response_xml(
69                 'failure',
70                 $e->getMessage(),
71                 uniqid(),
72                 'replaceResultResponse');
74             echo $responsexml->asXML();
75             break;
76         }
78         $ltiinstance = $DB->get_record('lti', array('id' => $parsed->instanceid));
80         lti_verify_sourcedid($ltiinstance, $parsed);
82         $gradestatus = lti_update_grade($ltiinstance, $parsed->userid, $parsed->launchid, $parsed->gradeval);
84         $responsexml = lti_get_response_xml(
85                 $gradestatus ? 'success' : 'failure',
86                 'Grade replace response',
87                 $parsed->messageid,
88                 'replaceResultResponse'
89         );
91         echo $responsexml->asXML();
93         break;
95     case 'readResultRequest':
96         $parsed = lti_parse_grade_read_message($xml);
98         $ltiinstance = $DB->get_record('lti', array('id' => $parsed->instanceid));
100         //Getting the grade requires the context is set
101         $context = get_context_instance(CONTEXT_COURSE, $ltiinstance->course);
102         $PAGE->set_context($context);
104         lti_verify_sourcedid($ltiinstance, $parsed);
106         $grade = lti_read_grade($ltiinstance, $parsed->userid);
108         $responsexml = lti_get_response_xml(
109                 isset($grade) ? 'success' : 'failure',
110                 'Result read',
111                 $parsed->messageid,
112                 'readResultResponse'
113         );
115         $node = $responsexml->imsx_POXBody->readResultResponse;
116         $node = $node->addChild('result')->addChild('resultScore');
117         $node->addChild('language', 'en');
118         $node->addChild('textString', isset($grade) ? $grade : '');
120         echo $responsexml->asXML();
122         break;
124     case 'deleteResultRequest':
125         $parsed = lti_parse_grade_delete_message($xml);
127         $ltiinstance = $DB->get_record('lti', array('id' => $parsed->instanceid));
129         lti_verify_sourcedid($ltiinstance, $parsed);
131         $gradestatus = lti_delete_grade($ltiinstance, $parsed->userid);
133         $responsexml = lti_get_response_xml(
134                 $gradestatus ? 'success' : 'failure',
135                 'Grade delete request',
136                 $parsed->messageid,
137                 'deleteResultResponse'
138         );
140         echo $responsexml->asXML();
142         break;
144     default:
145         //Fire an event if we get a web service request which we don't support directly.
146         //This will allow others to extend the LTI services, which I expect to be a common
147         //use case, at least until the spec matures.
148         $data = new stdClass();
149         $data->body = $rawbody;
150         $data->xml = $xml;
151         $data->messagetype = $messagetype;
152         $data->consumerkey = $consumerkey;
153         $data->sharedsecret = $sharedsecret;
155         //If an event handler handles the web service, it should set this global to true
156         //So this code knows whether to send an "operation not supported" or not.
157         global $lti_web_service_handled;
158         $lti_web_service_handled = false;
160         events_trigger('lti_unknown_service_api_call', $data);
162         if (!$lti_web_service_handled) {
163             $responsexml = lti_get_response_xml(
164                 'unsupported',
165                 'unsupported',
166                  lti_parse_message_id($xml),
167                  $messagetype
168             );
170             echo $responsexml->asXML();
171         }
173         break;
177 //echo print_r(apache_request_headers(), true);
179 //echo '<br />';
181 //echo file_get_contents("php://input");