Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
   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   * This file contains a class definition for the Tool Consumer Profile resource
  19   *
  20   * @package    ltiservice_profile
  21   * @copyright  2014 Vital Source Technologies http://vitalsource.com
  22   * @author     Stephen Vickers
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  
  27  namespace ltiservice_profile\local\resources;
  28  
  29  use \mod_lti\local\ltiservice\service_base;
  30  
  31  defined('MOODLE_INTERNAL') || die();
  32  
  33  /**
  34   * A resource implementing the Tool Consumer Profile.
  35   *
  36   * @package    ltiservice_profile
  37   * @since      Moodle 2.8
  38   * @copyright  2014 Vital Source Technologies http://vitalsource.com
  39   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  40   */
  41  class profile extends \mod_lti\local\ltiservice\resource_base {
  42  
  43      /**
  44       * Class constructor.
  45       *
  46       * @param service_base $service Service instance
  47       */
  48      public function __construct($service) {
  49  
  50          parent::__construct($service);
  51          $this->id = 'ToolConsumerProfile';
  52          $this->template = '/profile/{tool_proxy_id}';
  53          $this->variables[] = 'ToolConsumerProfile.url';
  54          $this->formats[] = 'application/vnd.ims.lti.v2.toolconsumerprofile+json';
  55          $this->methods[] = 'GET';
  56  
  57      }
  58  
  59      /**
  60       * Get the path for this resource.
  61       *
  62       * @return string
  63       */
  64      public function get_path() {
  65  
  66          $path = $this->template;
  67          $toolproxy = $this->get_service()->get_tool_proxy();
  68          if (!empty($toolproxy)) {
  69              $path = str_replace('{tool_proxy_id}', $toolproxy->guid, $path);
  70          }
  71  
  72          return $path;
  73  
  74      }
  75  
  76      /**
  77       * Execute the request for this resource.
  78       *
  79       * @param \mod_lti\local\ltiservice\response $response  Response object for this request.
  80       */
  81      public function execute($response) {
  82          global $CFG;
  83  
  84          $version = service_base::LTI_VERSION2P0;
  85          $params = $this->parse_template();
  86          if (optional_param('lti_version', service_base::LTI_VERSION2P0, PARAM_ALPHANUMEXT) != $version) {
  87              $ok = false;
  88              $response->set_code(400);
  89          } else {
  90              $toolproxy = lti_get_tool_proxy_from_guid($params['tool_proxy_id']);
  91              $ok = $toolproxy !== false;
  92          }
  93          if ($ok) {
  94              $this->get_service()->set_tool_proxy($toolproxy);
  95              $response->set_content_type($this->formats[0]);
  96  
  97              $servicepath = $this->get_service()->get_service_path();
  98              $id = $servicepath . $this->get_path();
  99              $now = date('Y-m-d\TH:iO');
 100              $capabilityofferedarr = explode("\n", $toolproxy->capabilityoffered);
 101              $serviceofferedarr = explode("\n", $toolproxy->serviceoffered);
 102              $serviceoffered = '';
 103              $sep = '';
 104              $services = \core_component::get_plugin_list('ltiservice');
 105              foreach ($services as $name => $location) {
 106                  if (in_array($name, $serviceofferedarr)) {
 107                      $classname = "\\ltiservice_{$name}\\local\\service\\{$name}";
 108                      /** @var service_base $service */
 109                      $service = new $classname();
 110                      $service->set_tool_proxy($toolproxy);
 111                      $resources = $service->get_resources();
 112                      foreach ($resources as $resource) {
 113                          $formats = implode("\", \"", $resource->get_formats());
 114                          $methods = implode("\", \"", $resource->get_methods());
 115                          $capabilityofferedarr = array_merge($capabilityofferedarr, $resource->get_variables());
 116                          $template = $resource->get_path();
 117                          if (!empty($template)) {
 118                              $path = $servicepath . preg_replace('/[\(\)]/', '', $template);
 119                          } else {
 120                              $path = $resource->get_endpoint();
 121                          }
 122                          $serviceoffered .= <<< EOD
 123  {$sep}
 124      {
 125        "@type":"{$resource->get_type()}",
 126        "@id":"tcp:{$resource->get_id()}",
 127        "endpoint":"{$path}",
 128        "format":["{$formats}"],
 129        "action":["{$methods}"]
 130      }
 131  EOD;
 132                          $sep = ',';
 133                      }
 134                  }
 135              }
 136              $capabilityoffered = implode("\",\n    \"", $capabilityofferedarr);
 137              if (strlen($capabilityoffered) > 0) {
 138                  $capabilityoffered = "\n    \"{$capabilityoffered}\"";
 139              }
 140              $urlparts = parse_url($CFG->wwwroot);
 141              $orgid = $urlparts['host'];
 142              $name = 'Moodle';
 143              $code = 'moodle';
 144              $vendorname = 'Moodle.org';
 145              $vendorcode = 'mdl';
 146              $prodversion = strval($CFG->version);
 147              if (!empty($CFG->mod_lti_institution_name)) {
 148                  $consumername = $CFG->mod_lti_institution_name;
 149                  $consumerdesc = '';
 150              } else {
 151                  $consumername = get_site()->fullname;
 152                  $consumerdesc = strip_tags(get_site()->summary);
 153              }
 154              $profile = <<< EOD
 155  {
 156    "@context":[
 157      "http://purl.imsglobal.org/ctx/lti/v2/ToolConsumerProfile",
 158      {
 159        "tcp":"{$id}#"
 160      }
 161    ],
 162    "@type":"ToolConsumerProfile",
 163    "@id":"{$id}",
 164    "lti_version":"{$version}",
 165    "guid":"{$toolproxy->guid}",
 166    "product_instance":{
 167      "guid":"{$orgid}",
 168      "product_info":{
 169        "product_name":{
 170          "default_value":"{$name}",
 171          "key":"product.name"
 172        },
 173        "product_version":"{$prodversion}",
 174        "product_family":{
 175          "code":"{$code}",
 176          "vendor":{
 177            "code":"{$vendorcode}",
 178            "vendor_name":{
 179              "default_value":"{$vendorname}",
 180              "key":"product.vendor.name"
 181            },
 182            "timestamp":"{$now}"
 183          }
 184        }
 185      },
 186      "service_owner":{
 187        "@id":"ServiceOwner",
 188        "service_owner_name":{
 189          "default_value":"{$consumername}",
 190          "key":"service_owner.name"
 191        },
 192        "description":{
 193          "default_value":"{$consumerdesc}",
 194          "key":"service_owner.description"
 195        }
 196      }
 197    },
 198    "capability_offered":[{$capabilityoffered}
 199    ],
 200    "service_offered":[{$serviceoffered}
 201    ]
 202  }
 203  EOD;
 204              $response->set_body($profile);
 205  
 206          }
 207      }
 208  
 209      /**
 210       * Parse a value for custom parameter substitution variables.
 211       *
 212       * @param string $value String to be parsed
 213       *
 214       * @return string
 215       */
 216      public function parse_value($value) {
 217          if (!empty($this->get_service()->get_tool_proxy()) && (strpos($value, '$ToolConsumerProfile.url') !== false)) {
 218              $value = str_replace('$ToolConsumerProfile.url', $this->get_endpoint(), $value);
 219          }
 220          return $value;
 221  
 222      }
 223  
 224  }