[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/mod/lti/ -> servicelib.php (source)

   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   * Utility code for LTI service handling.
  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  defined('MOODLE_INTERNAL') || die;
  27  
  28  require_once($CFG->dirroot.'/mod/lti/OAuthBody.php');
  29  
  30  // TODO: Switch to core oauthlib once implemented - MDL-30149.
  31  use moodle\mod\lti as lti;
  32  
  33  define('LTI_ITEM_TYPE', 'mod');
  34  define('LTI_ITEM_MODULE', 'lti');
  35  define('LTI_SOURCE', 'mod/lti');
  36  
  37  function lti_get_response_xml($codemajor, $description, $messageref, $messagetype) {
  38      $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><imsx_POXEnvelopeResponse />');
  39      $xml->addAttribute('xmlns', 'http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0');
  40  
  41      $headerinfo = $xml->addChild('imsx_POXHeader')->addChild('imsx_POXResponseHeaderInfo');
  42  
  43      $headerinfo->addChild('imsx_version', 'V1.0');
  44      $headerinfo->addChild('imsx_messageIdentifier', (string)mt_rand());
  45  
  46      $statusinfo = $headerinfo->addChild('imsx_statusInfo');
  47      $statusinfo->addchild('imsx_codeMajor', $codemajor);
  48      $statusinfo->addChild('imsx_severity', 'status');
  49      $statusinfo->addChild('imsx_description', $description);
  50      $statusinfo->addChild('imsx_messageRefIdentifier', $messageref);
  51      $incomingtype = str_replace('Response', 'Request', $messagetype);
  52      $statusinfo->addChild('imsx_operationRefIdentifier', $incomingtype);
  53  
  54      $xml->addChild('imsx_POXBody')->addChild($messagetype);
  55  
  56      return $xml;
  57  }
  58  
  59  function lti_parse_message_id($xml) {
  60      $node = $xml->imsx_POXHeader->imsx_POXRequestHeaderInfo->imsx_messageIdentifier;
  61      $messageid = (string)$node;
  62  
  63      return $messageid;
  64  }
  65  
  66  function lti_parse_grade_replace_message($xml) {
  67      $node = $xml->imsx_POXBody->replaceResultRequest->resultRecord->sourcedGUID->sourcedId;
  68      $resultjson = json_decode((string)$node);
  69  
  70      $node = $xml->imsx_POXBody->replaceResultRequest->resultRecord->result->resultScore->textString;
  71  
  72      $score = (string) $node;
  73      if ( ! is_numeric($score) ) {
  74          throw new Exception('Score must be numeric');
  75      }
  76      $grade = floatval($score);
  77      if ( $grade < 0.0 || $grade > 1.0 ) {
  78          throw new Exception('Score not between 0.0 and 1.0');
  79      }
  80  
  81      $parsed = new stdClass();
  82      $parsed->gradeval = $grade;
  83  
  84      $parsed->instanceid = $resultjson->data->instanceid;
  85      $parsed->userid = $resultjson->data->userid;
  86      $parsed->launchid = $resultjson->data->launchid;
  87      $parsed->typeid = $resultjson->data->typeid;
  88      $parsed->sourcedidhash = $resultjson->hash;
  89  
  90      $parsed->messageid = lti_parse_message_id($xml);
  91  
  92      return $parsed;
  93  }
  94  
  95  function lti_parse_grade_read_message($xml) {
  96      $node = $xml->imsx_POXBody->readResultRequest->resultRecord->sourcedGUID->sourcedId;
  97      $resultjson = json_decode((string)$node);
  98  
  99      $parsed = new stdClass();
 100      $parsed->instanceid = $resultjson->data->instanceid;
 101      $parsed->userid = $resultjson->data->userid;
 102      $parsed->launchid = $resultjson->data->launchid;
 103      $parsed->typeid = $resultjson->data->typeid;
 104      $parsed->sourcedidhash = $resultjson->hash;
 105  
 106      $parsed->messageid = lti_parse_message_id($xml);
 107  
 108      return $parsed;
 109  }
 110  
 111  function lti_parse_grade_delete_message($xml) {
 112      $node = $xml->imsx_POXBody->deleteResultRequest->resultRecord->sourcedGUID->sourcedId;
 113      $resultjson = json_decode((string)$node);
 114  
 115      $parsed = new stdClass();
 116      $parsed->instanceid = $resultjson->data->instanceid;
 117      $parsed->userid = $resultjson->data->userid;
 118      $parsed->launchid = $resultjson->data->launchid;
 119      $parsed->typeid = $resultjson->data->typeid;
 120      $parsed->sourcedidhash = $resultjson->hash;
 121  
 122      $parsed->messageid = lti_parse_message_id($xml);
 123  
 124      return $parsed;
 125  }
 126  
 127  function lti_accepts_grades($ltiinstance) {
 128      global $DB;
 129  
 130      $acceptsgrades = true;
 131      $ltitype = $DB->get_record('lti_types', array('id' => $ltiinstance->typeid));
 132  
 133      if (empty($ltitype->toolproxyid)) {
 134          $typeconfig = lti_get_config($ltiinstance);
 135  
 136          $typeacceptgrades = isset($typeconfig['acceptgrades']) ? $typeconfig['acceptgrades'] : LTI_SETTING_DELEGATE;
 137  
 138          if (!($typeacceptgrades == LTI_SETTING_ALWAYS ||
 139              ($typeacceptgrades == LTI_SETTING_DELEGATE && $ltiinstance->instructorchoiceacceptgrades == LTI_SETTING_ALWAYS))) {
 140              $acceptsgrades = false;
 141          }
 142      } else {
 143          $enabledcapabilities = explode("\n", $ltitype->enabledcapability);
 144          $acceptsgrades = in_array('Result.autocreate', $enabledcapabilities);
 145      }
 146  
 147      return $acceptsgrades;
 148  }
 149  
 150  /**
 151   * Set the passed user ID to the session user.
 152   *
 153   * @param int $userid
 154   */
 155  function lti_set_session_user($userid) {
 156      global $DB;
 157  
 158      if ($user = $DB->get_record('user', array('id' => $userid))) {
 159          \core\session\manager::set_user($user);
 160      }
 161  }
 162  
 163  function lti_update_grade($ltiinstance, $userid, $launchid, $gradeval) {
 164      global $CFG, $DB;
 165      require_once($CFG->libdir . '/gradelib.php');
 166  
 167      $params = array();
 168      $params['itemname'] = $ltiinstance->name;
 169  
 170      $gradeval = $gradeval * floatval($ltiinstance->grade);
 171  
 172      $grade = new stdClass();
 173      $grade->userid   = $userid;
 174      $grade->rawgrade = $gradeval;
 175  
 176      $status = grade_update(LTI_SOURCE, $ltiinstance->course, LTI_ITEM_TYPE, LTI_ITEM_MODULE, $ltiinstance->id, 0, $grade, $params);
 177  
 178      $record = $DB->get_record('lti_submission', array('ltiid' => $ltiinstance->id, 'userid' => $userid,
 179          'launchid' => $launchid), 'id');
 180      if ($record) {
 181          $id = $record->id;
 182      } else {
 183          $id = null;
 184      }
 185  
 186      if (!empty($id)) {
 187          $DB->update_record('lti_submission', array(
 188              'id' => $id,
 189              'dateupdated' => time(),
 190              'gradepercent' => $gradeval,
 191              'state' => 2
 192          ));
 193      } else {
 194          $DB->insert_record('lti_submission', array(
 195              'ltiid' => $ltiinstance->id,
 196              'userid' => $userid,
 197              'datesubmitted' => time(),
 198              'dateupdated' => time(),
 199              'gradepercent' => $gradeval,
 200              'originalgrade' => $gradeval,
 201              'launchid' => $launchid,
 202              'state' => 1
 203          ));
 204      }
 205  
 206      return $status == GRADE_UPDATE_OK;
 207  }
 208  
 209  function lti_read_grade($ltiinstance, $userid) {
 210      global $CFG;
 211      require_once($CFG->libdir . '/gradelib.php');
 212  
 213      $grades = grade_get_grades($ltiinstance->course, LTI_ITEM_TYPE, LTI_ITEM_MODULE, $ltiinstance->id, $userid);
 214  
 215      $ltigrade = floatval($ltiinstance->grade);
 216  
 217      if (!empty($ltigrade) && isset($grades) && isset($grades->items[0]) && is_array($grades->items[0]->grades)) {
 218          foreach ($grades->items[0]->grades as $agrade) {
 219              $grade = $agrade->grade;
 220              $grade = $grade / $ltigrade;
 221              break;
 222          }
 223      }
 224  
 225      if (isset($grade)) {
 226          return $grade;
 227      }
 228  }
 229  
 230  function lti_delete_grade($ltiinstance, $userid) {
 231      global $CFG;
 232      require_once($CFG->libdir . '/gradelib.php');
 233  
 234      $grade = new stdClass();
 235      $grade->userid   = $userid;
 236      $grade->rawgrade = null;
 237  
 238      $status = grade_update(LTI_SOURCE, $ltiinstance->course, LTI_ITEM_TYPE, LTI_ITEM_MODULE, $ltiinstance->id, 0, $grade);
 239  
 240      return $status == GRADE_UPDATE_OK;
 241  }
 242  
 243  function lti_verify_message($key, $sharedsecrets, $body, $headers = null) {
 244      foreach ($sharedsecrets as $secret) {
 245          $signaturefailed = false;
 246  
 247          try {
 248              // TODO: Switch to core oauthlib once implemented - MDL-30149.
 249              lti\handle_oauth_body_post($key, $secret, $body, $headers);
 250          } catch (Exception $e) {
 251              $signaturefailed = true;
 252          }
 253  
 254          if (!$signaturefailed) {
 255              return $secret; // Return the secret used to sign the message).
 256          }
 257      }
 258  
 259      return false;
 260  }
 261  
 262  /**
 263   * Validate source ID from external request
 264   *
 265   * @param object $ltiinstance
 266   * @param object $parsed
 267   * @throws Exception
 268   */
 269  function lti_verify_sourcedid($ltiinstance, $parsed) {
 270      $sourceid = lti_build_sourcedid($parsed->instanceid, $parsed->userid,
 271          $ltiinstance->servicesalt, $parsed->typeid, $parsed->launchid);
 272  
 273      if ($sourceid->hash != $parsed->sourcedidhash) {
 274          throw new Exception('SourcedId hash not valid');
 275      }
 276  }
 277  
 278  /**
 279   * Extend the LTI services through the ltisource plugins
 280   *
 281   * @param stdClass $data LTI request data
 282   * @return bool
 283   * @throws coding_exception
 284   */
 285  function lti_extend_lti_services($data) {
 286      $plugins = get_plugin_list_with_function('ltisource', $data->messagetype);
 287      if (!empty($plugins)) {
 288          try {
 289              // There can only be one.
 290              if (count($plugins) > 1) {
 291                  throw new coding_exception('More than one ltisource plugin handler found');
 292              }
 293              $data->xml = new SimpleXMLElement($data->body);
 294              $callback = current($plugins);
 295              call_user_func($callback, $data);
 296          } catch (moodle_exception $e) {
 297              $error = $e->getMessage();
 298              if (debugging('', DEBUG_DEVELOPER)) {
 299                  $error .= ' '.format_backtrace(get_exception_info($e)->backtrace);
 300              }
 301              $responsexml = lti_get_response_xml(
 302                  'failure',
 303                  $error,
 304                  $data->messageid,
 305                  $data->messagetype
 306              );
 307  
 308              header('HTTP/1.0 400 bad request');
 309              echo $responsexml->asXML();
 310          }
 311          return true;
 312      }
 313      return false;
 314  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1