Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.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  namespace enrol_lti\local\ltiadvantage\entity;
  18  
  19  /**
  20   * The ags_info class, instances of which represent grade service information for a resource_link or context.
  21   *
  22   * For information about Assignment and Grade Services 2.0, see https://www.imsglobal.org/spec/lti-ags/v2p0/.
  23   *
  24   * @package    enrol_lti
  25   * @copyright  2021 Jake Dallimore <jrhdallimore@gmail.com>
  26   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   */
  28  class ags_info {
  29      /** @var string Scope for lineitem management, used when a platform allows the tool to create lineitems.*/
  30      private const SCOPES_LINEITEM_MANAGE = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem';
  31  
  32      /** @var string Scope for lineitem reads, used when a tool only grants read access to line items.*/
  33      private const SCOPES_LINEITEM_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly';
  34  
  35      /** @var string Scope for reading results.*/
  36      private const SCOPES_RESULT_READONLY = 'https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly';
  37  
  38      /** @var string Scope for posting scores.*/
  39      private const SCOPES_SCORES_POST = 'https://purl.imsglobal.org/spec/lti-ags/scope/score';
  40  
  41      /** @var \moodle_url|null The service URL used to get/put lineitems, if supported*/
  42      private $lineitemsurl;
  43  
  44      /** @var \moodle_url|null The lineitemurl, which is only present when a single lineitem is supported.*/
  45      private $lineitemurl;
  46  
  47      /** @var array The array of supported lineitem-related scopes for this service instance.*/
  48      private $lineitemscopes = [];
  49  
  50      /** @var string|null The supported result scope for this service instance.*/
  51      private $resultscope = null;
  52  
  53      /** @var string|null The supported score scope for this service instance.*/
  54      private $scorescope = null;
  55  
  56      /**
  57       * The ags_info constructor.
  58       *
  59       * @param \moodle_url|null $lineitemsurl The service URL used to get/put lineitems, if supported.
  60       * @param \moodle_url|null $lineitemurl The lineitemurl, which is only present when a single lineitem is supported.
  61       * @param array $scopes The array of supported scopes for this service instance.
  62       */
  63      private function __construct(?\moodle_url $lineitemsurl, ?\moodle_url $lineitemurl, array $scopes) {
  64  
  65          // Platforms may support just lineitemurl, just lineitemsurl or both. At least one of the two is required.
  66          if (is_null($lineitemsurl) && is_null($lineitemurl)) {
  67              throw new \coding_exception("Missing lineitem or lineitems URL");
  68          }
  69  
  70          $this->lineitemsurl = $lineitemsurl;
  71          $this->lineitemurl = $lineitemurl;
  72          $this->validate_scopes($scopes);
  73      }
  74  
  75      /**
  76       * Factory method to create a new ags_info instance.
  77       *
  78       * @param \moodle_url|null $lineitemsurl The service URL used to get/put lineitems, if supported.
  79       * @param \moodle_url|null $lineitemurl The lineitemurl, which is only present when a single lineitem is supported.
  80       * @param array $scopes The array of supported scopes for this service instance.
  81       * @return ags_info the object instance.
  82       */
  83      public static function create(?\moodle_url $lineitemsurl = null, ?\moodle_url $lineitemurl = null,
  84              array $scopes = []): ags_info {
  85          return new self($lineitemsurl, $lineitemurl, $scopes);
  86      }
  87  
  88      /**
  89       * Check the supplied scopes for validity and set instance vars if appropriate.
  90       *
  91       * @param array $scopes the array of string scopes to check.
  92       * @throws \coding_exception if any of the scopes is invalid.
  93       */
  94      private function validate_scopes(array $scopes): void {
  95          $supportedscopes = [
  96              self::SCOPES_LINEITEM_READONLY,
  97              self::SCOPES_LINEITEM_MANAGE,
  98              self::SCOPES_RESULT_READONLY,
  99              self::SCOPES_SCORES_POST
 100          ];
 101          foreach ($scopes as $scope) {
 102              if (!is_string($scope)) {
 103                  throw new \coding_exception('Scope must be a string value');
 104              }
 105              $key = array_search($scope, $supportedscopes);
 106              if ($key === 0) {
 107                  $this->lineitemscopes[] = self::SCOPES_LINEITEM_READONLY;
 108              } else if ($key === 1) {
 109                  $this->lineitemscopes[] = self::SCOPES_LINEITEM_MANAGE;
 110              } else if ($key === 2) {
 111                  $this->resultscope = self::SCOPES_RESULT_READONLY;
 112              } else if ($key === 3) {
 113                  $this->scorescope = self::SCOPES_SCORES_POST;
 114              }
 115          }
 116      }
 117  
 118      /**
 119       * Get the url for querying line items, if supported.
 120       *
 121       * @return \moodle_url the url.
 122       */
 123      public function get_lineitemsurl(): ?\moodle_url {
 124          return $this->lineitemsurl;
 125      }
 126  
 127      /**
 128       * Get the single line item url, in cases where only one line item exists.
 129       *
 130       * @return \moodle_url|null the url, or null if not present.
 131       */
 132      public function get_lineitemurl(): ?\moodle_url {
 133          return $this->lineitemurl;
 134      }
 135  
 136      /**
 137       * Get the authorization scope for lineitems.
 138       *
 139       * @return array|null the scopes, if present, else null.
 140       */
 141      public function get_lineitemscope(): ?array {
 142          return !empty($this->lineitemscopes) ? $this->lineitemscopes : null;
 143      }
 144  
 145      /**
 146       * Get the authorization scope for results.
 147       *
 148       * @return string|null the scope, if present, else null.
 149       */
 150      public function get_resultscope(): ?string {
 151          return $this->resultscope;
 152      }
 153  
 154      /**
 155       * Get the authorization scope for scores.
 156       *
 157       * @return string|null the scope, if present, else null.
 158       */
 159      public function get_scorescope(): ?string {
 160          return $this->scorescope;
 161      }
 162  
 163      /**
 164       * Get all supported scopes for this service.
 165       *
 166       * @return string[] the array of supported scopes.
 167       */
 168      public function get_scopes(): array {
 169          $scopes = [];
 170          foreach ($this->lineitemscopes as $lineitemscope) {
 171              $scopes[] = $lineitemscope;
 172          }
 173          if (!empty($this->resultscope)) {
 174              $scopes[] = $this->resultscope;
 175          }
 176          if (!empty($this->scorescope)) {
 177              $scopes[] = $this->scorescope;
 178          }
 179          return $scopes;
 180      }
 181  }