Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   1  <?php
   2  
   3  require_once  'OAuth.php';
   4  
   5    // Replace this with some real function that pulls from the LMS.
   6    function getLMSDummyData() {
   7      $parms = array(
   8        "resource_link_id" => "120988f929-274612",
   9        "resource_link_title" => "Weekly Blog",
  10        "resource_link_description" => "Each student needs to reflect on the weekly reading.  These should be one paragraph long.",
  11        "user_id" => "292832126",
  12        "roles" => "Instructor",  // or Learner
  13        "lis_person_name_full" => 'Jane Q. Public',
  14        "lis_person_contact_email_primary" => "user@school.edu",
  15        "lis_person_sourcedid" => "school.edu:user",
  16        "context_id" => "456434513",
  17        "context_title" => "Design of Personal Environments",
  18        "context_label" => "SI182",
  19        );
  20  
  21      return $parms;
  22    }
  23  
  24    function validateDescriptor($descriptor)
  25    {
  26      $xml = new SimpleXMLElement($xmldata);
  27      if ( ! $xml ) {
  28         echo("Error parsing Descriptor XML\n");
  29         return;
  30      }
  31      $launch_url = $xml->secure_launch_url[0];
  32      if ( ! $launch_url ) $launch_url = $xml->launch_url[0];
  33      if ( $launch_url ) $launch_url = (string) $launch_url;
  34      return $launch_url;
  35    }
  36  
  37    // Parse a descriptor
  38    function launchInfo($xmldata) {
  39      $xml = new SimpleXMLElement($xmldata);
  40      if ( ! $xml ) {
  41         echo("Error parsing Descriptor XML\n");
  42         return;
  43      }
  44      $launch_url = $xml->secure_launch_url[0];
  45      if ( ! $launch_url ) $launch_url = $xml->launch_url[0];
  46      if ( $launch_url ) $launch_url = (string) $launch_url;
  47      $custom = array();
  48      if ( $xml->custom[0]->parameter )
  49      foreach ( $xml->custom[0]->parameter as $resource) {
  50        $key = (string) $resource['key'];
  51        $key = strtolower($key);
  52        $nk = "";
  53        for($i=0; $i < strlen($key); $i++) {
  54          $ch = substr($key,$i,1);
  55          if ( $ch >= "a" && $ch <= "z" ) $nk .= $ch;
  56          else if ( $ch >= "0" && $ch <= "9" ) $nk .= $ch;
  57          else $nk .= "_";
  58        }
  59        $value = (string) $resource;
  60        $custom["custom_".$nk] = $value;
  61      }
  62      return array("launch_url" => $launch_url, "custom" => $custom ) ;
  63    }
  64  
  65  function signParameters($oldparms, $endpoint, $method, $oauth_consumer_key, $oauth_consumer_secret,
  66      $submit_text = false, $org_id = false, $org_desc = false)
  67  {
  68      global $last_base_string;
  69      $parms = $oldparms;
  70      if ( ! isset($parms["lti_version"]) ) $parms["lti_version"] = "LTI-1p0";
  71      if ( ! isset($parms["lti_message_type"]) ) $parms["lti_message_type"] = "basic-lti-launch-request";
  72      if ( ! isset($parms["oauth_callback"]) ) $parms["oauth_callback"] = "about:blank";
  73      if ( $org_id ) $parms["tool_consumer_instance_guid"] = $org_id;
  74      if ( $org_desc ) $parms["tool_consumer_instance_description"] = $org_desc;
  75      if ( $submit_text ) $parms["ext_submit"] = $submit_text;
  76  
  77      $test_token = '';
  78  
  79      $hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
  80      $test_consumer = new OAuthConsumer($oauth_consumer_key, $oauth_consumer_secret, NULL);
  81  
  82      $acc_req = OAuthRequest::from_consumer_and_token($test_consumer, $test_token, $method, $endpoint, $parms);
  83  
  84      $acc_req->sign_request($hmac_method, $test_consumer, $test_token);
  85  
  86      // Pass this back up "out of band" for debugging
  87      $last_base_string = $acc_req->get_signature_base_string();
  88  
  89      $newparms = $acc_req->get_parameters();
  90  
  91      return $newparms;
  92  }
  93  
  94  function signOnly($oldparms, $endpoint, $method, $oauth_consumer_key, $oauth_consumer_secret)
  95  {
  96      global $last_base_string;
  97      $parms = $oldparms;
  98  
  99      $test_token = '';
 100  
 101      $hmac_method = new OAuthSignatureMethod_HMAC_SHA1();
 102      $test_consumer = new OAuthConsumer($oauth_consumer_key, $oauth_consumer_secret, NULL);
 103  
 104      $acc_req = OAuthRequest::from_consumer_and_token($test_consumer, $test_token, $method, $endpoint, $parms);
 105      $acc_req->sign_request($hmac_method, $test_consumer, $test_token);
 106  
 107      // Pass this back up "out of band" for debugging
 108      $last_base_string = $acc_req->get_signature_base_string();
 109  
 110      $newparms = $acc_req->get_parameters();
 111  
 112      return $newparms;
 113  }
 114  
 115  function postLaunchHTML($newparms, $endpoint, $debug=false, $iframeattr=false) {
 116      global $last_base_string;
 117      $r = "<div id=\"ltiLaunchFormSubmitArea\">\n";
 118      if ( $iframeattr ) {
 119          $r = "<form action=\"".$endpoint."\" name=\"ltiLaunchForm\" id=\"ltiLaunchForm\" method=\"post\" target=\"basicltiLaunchFrame\" encType=\"application/x-www-form-urlencoded\">\n" ;
 120      } else {
 121          $r = "<form action=\"".$endpoint."\" name=\"ltiLaunchForm\" id=\"ltiLaunchForm\" method=\"post\" encType=\"application/x-www-form-urlencoded\">\n" ;
 122      }
 123      $submit_text = $newparms['ext_submit'];
 124      foreach($newparms as $key => $value ) {
 125          $key = htmlspecialchars($key);
 126          $value = htmlspecialchars($value);
 127          if ( $key == "ext_submit" ) {
 128              $r .= "<input type=\"submit\" name=\"";
 129          } else {
 130              $r .= "<input type=\"hidden\" name=\"";
 131          }
 132          $r .= $key;
 133          $r .= "\" value=\"";
 134          $r .= $value;
 135          $r .= "\"/>\n";
 136      }
 137      if ( $debug ) {
 138          $r .= "<script language=\"javascript\"> \n";
 139          $r .= "  //<![CDATA[ \n" ;
 140          $r .= "function basicltiDebugToggle() {\n";
 141          $r .= "    var ele = document.getElementById(\"basicltiDebug\");\n";
 142          $r .= "    if(ele.style.display == \"block\") {\n";
 143          $r .= "        ele.style.display = \"none\";\n";
 144          $r .= "    }\n";
 145          $r .= "    else {\n";
 146          $r .= "        ele.style.display = \"block\";\n";
 147          $r .= "    }\n";
 148          $r .= "} \n";
 149          $r .= "  //]]> \n" ;
 150          $r .= "</script>\n";
 151          $r .= "<a id=\"displayText\" href=\"javascript:basicltiDebugToggle();\">";
 152          $r .= get_stringIMS("toggle_debug_data","basiclti")."</a>\n";
 153          $r .= "<div id=\"basicltiDebug\" style=\"display:none\">\n";
 154          $r .=  "<b>".get_stringIMS("basiclti_endpoint","basiclti")."</b><br/>\n";
 155          $r .= $endpoint . "<br/>\n&nbsp;<br/>\n";
 156          $r .=  "<b>".get_stringIMS("basiclti_parameters","basiclti")."</b><br/>\n";
 157          foreach($newparms as $key => $value ) {
 158              $key = htmlspecialchars($key);
 159              $value = htmlspecialchars($value);
 160              $r .= "$key = $value<br/>\n";
 161          }
 162          $r .= "&nbsp;<br/>\n";
 163          $r .= "<p><b>".get_stringIMS("basiclti_base_string","basiclti")."</b><br/>\n".$last_base_string."</p>\n";
 164          $r .= "</div>\n";
 165      }
 166      $r .= "</form>\n";
 167      if ( $iframeattr ) {
 168          $r .= "<iframe name=\"basicltiLaunchFrame\"  id=\"basicltiLaunchFrame\" src=\"\"\n";
 169          $r .= $iframeattr . ">\n<p>".get_stringIMS("frames_required","basiclti")."</p>\n</iframe>\n";
 170      }
 171      if ( ! $debug ) {
 172          $ext_submit = "ext_submit";
 173          $ext_submit_text = $submit_text;
 174          $r .= " <script type=\"text/javascript\"> \n" .
 175              "  //<![CDATA[ \n" .
 176              "    document.getElementById(\"ltiLaunchForm\").style.display = \"none\";\n" .
 177              "    nei = document.createElement('input');\n" .
 178              "    nei.setAttribute('type', 'hidden');\n" .
 179              "    nei.setAttribute('name', '".$ext_submit."');\n" .
 180              "    nei.setAttribute('value', '".$ext_submit_text."');\n" .
 181              "    document.getElementById(\"ltiLaunchForm\").appendChild(nei);\n" .
 182              "    document.ltiLaunchForm.submit(); \n" .
 183              "  //]]> \n" .
 184              " </script> \n";
 185      }
 186      $r .= "</div>\n";
 187      return $r;
 188  }
 189  
 190  /* This is a bit of homage to Moodle's pattern of internationalisation */
 191  function get_stringIMS($key,$bundle) {
 192      return $key;
 193  }
 194  
 195  function do_post_request($url, $data, $optional_headers = null)
 196  {
 197    $params = array('http' => array(
 198                'method' => 'POST',
 199                'content' => $data
 200              ));
 201  
 202    if ($optional_headers !== null) {
 203       $header = $optional_headers . "\r\n";
 204    }
 205    // $header = $header . "Content-type: application/x-www-form-urlencoded\r\n";
 206    $params['http']['header'] = $header;
 207    $ctx = stream_context_create($params);
 208    $fp = @fopen($url, 'rb', false, $ctx);
 209    if (!$fp) {
 210      echo @stream_get_contents($fp);
 211      throw new Exception("Problem with $url, $php_errormsg");
 212    }
 213    $response = @stream_get_contents($fp);
 214    if ($response === false) {
 215      throw new Exception("Problem reading data from $url, $php_errormsg");
 216    }
 217    return $response;
 218  }
 219