Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 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 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

   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   * Contains the tests for the content_item_service class.
  19   *
  20   * @package    core
  21   * @subpackage course
  22   * @copyright  2020 Jake Dallimore <jrhdallimore@gmail.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  namespace tests\course;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  use \core_course\local\service\content_item_service;
  30  use \core_course\local\repository\content_item_readonly_repository;
  31  
  32  /**
  33   * The tests for the content_item_service class.
  34   *
  35   * @copyright  2020 Jake Dallimore <jrhdallimore@gmail.com>
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class services_content_item_service_testcase extends \advanced_testcase {
  39  
  40      /**
  41       * Test confirming that content items are returned by the service.
  42       */
  43      public function test_get_content_items_for_user_in_course_basic() {
  44          $this->resetAfterTest();
  45  
  46          // Create a user in a course.
  47          $course = $this->getDataGenerator()->create_course();
  48          $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
  49  
  50          $cis = new content_item_service(new content_item_readonly_repository());
  51          $contentitems = $cis->get_content_items_for_user_in_course($user, $course);
  52  
  53          foreach ($contentitems as $key => $contentitem) {
  54              $this->assertObjectHasAttribute('id', $contentitem);
  55              $this->assertObjectHasAttribute('name', $contentitem);
  56              $this->assertObjectHasAttribute('title', $contentitem);
  57              $this->assertObjectHasAttribute('link', $contentitem);
  58              $this->assertObjectHasAttribute('icon', $contentitem);
  59              $this->assertObjectHasAttribute('help', $contentitem);
  60              $this->assertObjectHasAttribute('archetype', $contentitem);
  61              $this->assertObjectHasAttribute('componentname', $contentitem);
  62          }
  63      }
  64  
  65      /**
  66       * Test confirming that access control is performed when asking the service to return content items for a user in a course.
  67       */
  68      public function test_get_content_items_for_user_in_course_permissions() {
  69          $this->resetAfterTest();
  70          global $DB;
  71  
  72          // Create a user in a course.
  73          $course = $this->getDataGenerator()->create_course();
  74          $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
  75  
  76          // No cap override, so assign should be returned.
  77          $cis = new content_item_service(new content_item_readonly_repository());
  78          $contentitems = $cis->get_content_items_for_user_in_course($user, $course);
  79          $this->assertContains('assign', array_column($contentitems, 'name'));
  80  
  81          // Override the capability 'mod/assign:addinstance' for the 'editing teacher' role.
  82          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
  83          assign_capability('mod/assign:addinstance', CAP_PROHIBIT, $teacherrole->id, \context_course::instance($course->id));
  84  
  85          $contentitems = $cis->get_content_items_for_user_in_course($user, $course);
  86          $this->assertArrayNotHasKey('assign', $contentitems);
  87      }
  88  
  89      /**
  90       * Test confirming that params can be added to the content item's link.
  91       */
  92      public function test_get_content_item_for_user_in_course_link_params() {
  93          $this->resetAfterTest();
  94  
  95          // Create a user in a course.
  96          $course = $this->getDataGenerator()->create_course();
  97          $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
  98  
  99          $cis = new content_item_service(new content_item_readonly_repository());
 100          $contentitems = $cis->get_content_items_for_user_in_course($user, $course, ['sr' => 7]);
 101  
 102          foreach ($contentitems as $item) {
 103              $this->assertStringContainsString('sr=7', $item->link);
 104          }
 105      }
 106  
 107      /**
 108       * Test confirming that all content items can be fetched irrespective of permissions.
 109       */
 110      public function test_get_all_content_items() {
 111          $this->resetAfterTest();
 112          global $DB;
 113  
 114          // Create a user in a course.
 115          $course = $this->getDataGenerator()->create_course();
 116          $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 117  
 118          $cis = new content_item_service(new content_item_readonly_repository());
 119          $allcontentitems = $cis->get_all_content_items($user);
 120          $coursecontentitems = $cis->get_content_items_for_user_in_course($user, $course);
 121  
 122          // The call to get_all_content_items() should return the same items as for the course,
 123          // given the user in an editing teacher and can add manual lti instances.
 124          $this->assertContains('lti', array_column($coursecontentitems, 'name'));
 125          $this->assertContains('lti', array_column($allcontentitems, 'name'));
 126  
 127          // Now removing the cap 'mod/lti:addinstance'. This will restrict those items returned by the course-specific method.
 128          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 129          assign_capability('mod/lti:addinstance', CAP_PROHIBIT, $teacherrole->id, \context_course::instance($course->id));
 130  
 131          // Verify that all items, including lti, are still returned by the get_all_content_items() call.
 132          $allcontentitems = $cis->get_all_content_items($user);
 133          $coursecontentitems = $cis->get_content_items_for_user_in_course($user, $course);
 134          $this->assertNotContains('lti', array_column($coursecontentitems, 'name'));
 135          $this->assertContains('lti', array_column($allcontentitems, 'name'));
 136      }
 137  
 138      /**
 139       * Test confirming that content items which title match a certain pattern can be fetched irrespective of permissions.
 140       */
 141      public function test_get_content_items_by_name_pattern() {
 142          $this->resetAfterTest();
 143  
 144          // Create a user in a course.
 145          $course = $this->getDataGenerator()->create_course();
 146          $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 147  
 148          // Pattern that does exist.
 149          $pattern1 = "assign";
 150          // Pattern that does not exist.
 151          $pattern2 = "random string";
 152  
 153          $cis = new content_item_service(new content_item_readonly_repository());
 154          $matchingcontentitems1 = $cis->get_content_items_by_name_pattern($user, $pattern1);
 155          $matchingcontentitems2 = $cis->get_content_items_by_name_pattern($user, $pattern2);
 156  
 157          // The pattern "assign" should return at least 1 content item (ex. "Assignment").
 158          $this->assertGreaterThanOrEqual(1, count($matchingcontentitems1));
 159          // Verify the pattern "assign" can be found in the title of each returned content item.
 160          foreach ($matchingcontentitems1 as $contentitem) {
 161              $this->assertEquals(1, preg_match("/$pattern1/i", $contentitem->title));
 162          }
 163          // The pattern "random string" should not return any content items.
 164          $this->assertEmpty($matchingcontentitems2);
 165      }
 166  
 167      /**
 168       * Test confirming that a content item can be added to a user's favourites.
 169       */
 170      public function test_add_to_user_favourites() {
 171          $this->resetAfterTest();
 172  
 173          // Create a user in a course.
 174          $course = $this->getDataGenerator()->create_course();
 175          $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 176          $cis = new content_item_service(new content_item_readonly_repository());
 177  
 178          // Grab a the assign content item, which we'll favourite for the user.
 179          $items = $cis->get_all_content_items($user);
 180          $assign = $items[array_search('assign', array_column($items, 'name'))];
 181          $contentitem = $cis->add_to_user_favourites($user, 'mod_assign', $assign->id);
 182  
 183          // Verify the exported result is marked as a favourite.
 184          $this->assertEquals('assign', $contentitem->name);
 185          $this->assertTrue($contentitem->favourite);
 186  
 187          // Verify the item is marked as a favourite when returned from the other service methods.
 188          $allitems = $cis->get_all_content_items($user);
 189          $allitemsassign = $allitems[array_search('assign', array_column($allitems, 'name'))];
 190  
 191          $courseitems = $cis->get_content_items_for_user_in_course($user, $course);
 192          $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
 193          $this->assertTrue($allitemsassign->favourite);
 194          $this->assertTrue($courseitemsassign->favourite);
 195      }
 196  
 197      /**
 198       * Test verifying that content items can be removed from a user's favourites.
 199       */
 200      public function test_remove_from_user_favourites() {
 201          $this->resetAfterTest();
 202  
 203          // Create a user in a course.
 204          $course = $this->getDataGenerator()->create_course();
 205          $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 206          $cis = new content_item_service(new content_item_readonly_repository());
 207  
 208          // Grab a the assign content item, which we'll favourite for the user.
 209          $items = $cis->get_all_content_items($user);
 210          $assign = $items[array_search('assign', array_column($items, 'name'))];
 211          $cis->add_to_user_favourites($user, 'mod_assign', $assign->id);
 212  
 213          // Now, remove the favourite, and verify it.
 214          $contentitem = $cis->remove_from_user_favourites($user, 'mod_assign', $assign->id);
 215  
 216          // Verify the exported result is not marked as a favourite.
 217          $this->assertEquals('assign', $contentitem->name);
 218          $this->assertFalse($contentitem->favourite);
 219  
 220          // Verify the item is not marked as a favourite when returned from the other service methods.
 221          $allitems = $cis->get_all_content_items($user);
 222          $allitemsassign = $allitems[array_search('assign', array_column($allitems, 'name'))];
 223          $courseitems = $cis->get_content_items_for_user_in_course($user, $course);
 224          $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
 225          $this->assertFalse($allitemsassign->favourite);
 226          $this->assertFalse($courseitemsassign->favourite);
 227      }
 228  
 229      /**
 230       * Test that toggling a recommendation works as anticipated.
 231       */
 232      public function test_toggle_recommendation() {
 233          $this->resetAfterTest();
 234  
 235          // Create a user in a course.
 236          $course = $this->getDataGenerator()->create_course();
 237          $user = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 238          $cis = new content_item_service(new content_item_readonly_repository());
 239  
 240          // Grab a the assign content item, which we'll recommend for the user.
 241          $items = $cis->get_all_content_items($user);
 242          $assign = $items[array_search('assign', array_column($items, 'name'))];
 243          $result = $cis->toggle_recommendation($assign->componentname, $assign->id);
 244          $this->assertTrue($result);
 245  
 246          $courseitems = $cis->get_all_content_items($user);
 247          $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
 248          $this->assertTrue($courseitemsassign->recommended);
 249  
 250          // Let's toggle the recommendation off.
 251          $result = $cis->toggle_recommendation($assign->componentname, $assign->id);
 252          $this->assertFalse($result);
 253  
 254          $courseitems = $cis->get_all_content_items($user);
 255          $courseitemsassign = $courseitems[array_search('assign', array_column($courseitems, 'name'))];
 256          $this->assertFalse($courseitemsassign->recommended);
 257      }
 258  }