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  namespace ltiservice_gradebookservices;
  18  
  19  use ltiservice_gradebookservices\local\resources\lineitem;
  20  use ltiservice_gradebookservices\local\service\gradebookservices;
  21  
  22  /**
  23   * Unit tests for lti lineitem.
  24   *
  25   * @package    ltiservice_gradebookservices
  26   * @category   test
  27   * @copyright  2022 Cengage Group <claude.vervoort@cengage.com>
  28   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  29   * @coversDefaultClass \mod_lti\service\gradebookservices\local\resources\lineitem
  30   */
  31  class lineitem_test extends \advanced_testcase {
  32  
  33      /**
  34       * @covers ::execute
  35       *
  36       * Test updating the line item with submission review.
  37       */
  38      public function test_execute_put_nosubreview() {
  39          global $CFG;
  40          require_once($CFG->dirroot . '/mod/lti/locallib.php');
  41          $this->resetAfterTest();
  42          $this->setAdminUser();
  43          $resourceid = 'test-resource-id';
  44          $tag = 'tag';
  45          $course = $this->getDataGenerator()->create_course();
  46          $typeid = $this->create_type();
  47  
  48          // The 1st item in the array is the items count.
  49  
  50          $gbservice = new gradebookservices();
  51          $gbservice->set_type(lti_get_type($typeid));
  52          $this->create_graded_lti($typeid, $course, $resourceid, $tag);
  53          $gradeitems = $gbservice->get_lineitems($course->id, null, null, null, null, null, $typeid);
  54          $this->assertEquals(1, $gradeitems[0]);
  55          $lineitem = gradebookservices::item_for_json($gradeitems[1][0], '', $typeid);
  56          $this->assertFalse(isset($lineitem->submissionReview));
  57  
  58          $lineitemresource = new lineitem($gbservice);
  59  
  60          $this->set_server_for_put($course, $typeid, $lineitem);
  61  
  62          $response = new \mod_lti\local\ltiservice\response();
  63          $lineitem->resourceId = $resourceid.'modified';
  64          $lineitem->tag = $tag.'modified';
  65          $response->set_request_data(json_encode($lineitem));
  66  
  67          $lineitemresource->execute($response);
  68  
  69          $lineitem = gradebookservices::item_for_json($gradeitems[1][0], '', $typeid);
  70          $this->assertFalse(isset($lineitem->submissionReview));
  71          $this->assertEquals($resourceid.'modified', $lineitem->resourceId);
  72          $this->assertEquals($tag.'modified', $lineitem->tag);
  73          $responseitem = json_decode($response->get_body());
  74          $this->assertEquals($resourceid.'modified', $responseitem->resourceId);
  75      }
  76  
  77      /**
  78       * @covers ::execute
  79       *
  80       * Test updating the line item with submission review.
  81       */
  82      public function test_execute_put_withsubreview() {
  83          global $CFG;
  84          require_once($CFG->dirroot . '/mod/lti/locallib.php');
  85          $this->resetAfterTest();
  86          $this->setAdminUser();
  87          $resourceid = 'test-resource-id';
  88          $tag = 'tag';
  89          $subreviewurl = 'https://subreview.example.com';
  90          $subreviewparams = 'a=2';
  91          $course = $this->getDataGenerator()->create_course();
  92          $typeid = $this->create_type();
  93  
  94          // The 1st item in the array is the items count.
  95  
  96          $gbservice = new gradebookservices();
  97          $gbservice->set_type(lti_get_type($typeid));
  98          $this->create_graded_lti($typeid, $course, $resourceid, $tag, $subreviewurl, $subreviewparams);
  99          $gradeitems = $gbservice->get_lineitems($course->id, null, null, null, null, null, $typeid);
 100          $this->assertEquals(1, $gradeitems[0]);
 101          $lineitem = gradebookservices::item_for_json($gradeitems[1][0], '', $typeid);
 102          $this->assertTrue(isset($lineitem->submissionReview));
 103  
 104          $lineitemresource = new lineitem($gbservice);
 105  
 106          $this->set_server_for_put($course, $typeid, $lineitem);
 107  
 108          $response = new \mod_lti\local\ltiservice\response();
 109          $lineitem->resourceId = $resourceid.'modified';
 110          $lineitem->tag = $tag.'modified';
 111          $lineitem->submissionReview->url = $subreviewurl.'modified';
 112          $lineitem->submissionReview->custom = ['a' => '3'];
 113          $response->set_request_data(json_encode($lineitem));
 114  
 115          $lineitemresource->execute($response);
 116  
 117          $lineitem = gradebookservices::item_for_json($gradeitems[1][0], '', $typeid);
 118          $this->assertEquals($resourceid.'modified', $lineitem->resourceId);
 119          $this->assertEquals($subreviewurl.'modified', $lineitem->submissionReview->url);
 120          $custom = $lineitem->submissionReview->custom;
 121          $this->assertEquals('a=3', join("\n", array_map(fn($k) => $k.'='.$custom[$k], array_keys($custom))));
 122  
 123          $responseitem = json_decode($response->get_body());
 124          $this->assertEquals($resourceid.'modified', $responseitem->resourceId);
 125          $this->assertEquals($subreviewurl.'modified', $responseitem->submissionReview->url);
 126      }
 127  
 128      /**
 129       * @covers ::execute
 130       *
 131       * Test updating the line item with submission review.
 132       */
 133      public function test_execute_put_addsubreview() {
 134          global $CFG;
 135          require_once($CFG->dirroot . '/mod/lti/locallib.php');
 136          $this->resetAfterTest();
 137          $this->setAdminUser();
 138          $resourceid = 'test-resource-id';
 139          $tag = 'tag';
 140          $subreviewurl = 'https://subreview.example.com';
 141          $course = $this->getDataGenerator()->create_course();
 142          $typeid = $this->create_type();
 143  
 144          // The 1st item in the array is the items count.
 145  
 146          $gbservice = new gradebookservices();
 147          $gbservice->set_type(lti_get_type($typeid));
 148          $this->create_graded_lti($typeid, $course, $resourceid, $tag);
 149          $gradeitems = $gbservice->get_lineitems($course->id, null, null, null, null, null, $typeid);
 150          $this->assertEquals(1, $gradeitems[0]);
 151          $lineitem = gradebookservices::item_for_json($gradeitems[1][0], '', $typeid);
 152          $this->assertFalse(isset($lineitem->submissionReview));
 153  
 154          $lineitemresource = new lineitem($gbservice);
 155  
 156          $this->set_server_for_put($course, $typeid, $lineitem);
 157  
 158          $response = new \mod_lti\local\ltiservice\response();
 159          $lineitem->resourceId = $resourceid.'modified';
 160          $lineitem->tag = $tag.'modified';
 161          $lineitem->submissionReview = ['url' => $subreviewurl];
 162          $response->set_request_data(json_encode($lineitem));
 163  
 164          $lineitemresource->execute($response);
 165  
 166          $lineitem = gradebookservices::item_for_json($gradeitems[1][0], '', $typeid);
 167          $this->assertEquals($resourceid.'modified', $lineitem->resourceId);
 168          $this->assertEquals($subreviewurl, $lineitem->submissionReview->url);
 169          $this->assertFalse(isset($lineitem->submissionReview->custom));
 170  
 171          $responseitem = json_decode($response->get_body());
 172          $this->assertEquals($resourceid.'modified', $responseitem->resourceId);
 173          $this->assertEquals($subreviewurl, $responseitem->submissionReview->url);
 174          $this->assertFalse(isset($responseitem->submissionReview->custom));
 175      }
 176  
 177      /**
 178       * Inserts a graded lti instance, which should create a grade_item and gradebookservices record.
 179       *
 180       * @param int $typeid Type ID of the LTI Tool.
 181       * @param object $course course where to add the lti instance.
 182       * @param string|null $resourceid resource id
 183       * @param string|null $tag tag
 184       * @param string|null $subreviewurl submission review url
 185       * @param string|null $subreviewparams submission review custom params
 186       *
 187       * @return object lti instance created
 188       */
 189      private function create_graded_lti(int $typeid, object $course, ?string $resourceid, ?string $tag,
 190              ?string $subreviewurl = null, ?string $subreviewparams = null) : object {
 191  
 192          $lti = ['course' => $course->id,
 193              'typeid' => $typeid,
 194              'instructorchoiceacceptgrades' => LTI_SETTING_ALWAYS,
 195              'grade' => 10,
 196              'lineitemresourceid' => $resourceid,
 197              'lineitemtag' => $tag,
 198              'lineitemsubreviewurl' => $subreviewurl,
 199              'lineitemsubreviewparams' => $subreviewparams];
 200  
 201          return $this->getDataGenerator()->create_module('lti', $lti, array());
 202      }
 203  
 204      /**
 205       * Creates a new LTI Tool Type.
 206       */
 207      private function create_type() {
 208          $type = new \stdClass();
 209          $type->state = LTI_TOOL_STATE_CONFIGURED;
 210          $type->name = "Test tool";
 211          $type->description = "Example description";
 212          $type->clientid = "Test client ID";
 213          $type->baseurl = $this->getExternalTestFileUrl('/test.html');
 214  
 215          $config = new \stdClass();
 216          $config->ltiservice_gradesynchronization = 2;
 217          return lti_add_type($type, $config);
 218      }
 219  
 220      /**
 221       * Sets the server info and get to be configured for a PUT operation,
 222       * including having a proper auth token attached.
 223       *
 224       * @param object $course course where to add the lti instance.
 225       * @param int $typeid
 226       * @param object $lineitem
 227       */
 228      private function set_server_for_put(object $course, int $typeid, object $lineitem) {
 229          $_SERVER['REQUEST_METHOD'] = \mod_lti\local\ltiservice\resource_base::HTTP_PUT;
 230          $_SERVER['PATH_INFO'] = "/$course->id/lineitems$lineitem->id";
 231  
 232          $token = lti_new_access_token($typeid, ['https://purl.imsglobal.org/spec/lti-ags/scope/lineitem']);
 233          $_SERVER['HTTP_Authorization'] = 'Bearer '.$token->token;
 234          $_GET['type_id'] = (string)$typeid;
 235      }
 236  }