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] [Versions 39 and 310]

   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   * Wiki module external functions tests.
  19   *
  20   * @package    mod_wiki
  21   * @category   external
  22   * @copyright  2015 Dani Palou <dani@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   * @since      Moodle 3.1
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  global $CFG;
  30  
  31  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  32  require_once($CFG->dirroot . '/mod/wiki/lib.php');
  33  
  34  /**
  35   * Wiki module external functions tests
  36   *
  37   * @package    mod_wiki
  38   * @category   external
  39   * @copyright  2015 Dani Palou <dani@moodle.com>
  40   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   * @since      Moodle 3.1
  42   */
  43  class mod_wiki_external_testcase extends externallib_advanced_testcase {
  44  
  45      /**
  46       * Set up for every test
  47       */
  48      public function setUp(): void {
  49          global $DB;
  50          $this->resetAfterTest();
  51          $this->setAdminUser();
  52  
  53          // Setup test data.
  54          $this->course = $this->getDataGenerator()->create_course();
  55          $this->wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $this->course->id));
  56          $this->context = context_module::instance($this->wiki->cmid);
  57          $this->cm = get_coursemodule_from_instance('wiki', $this->wiki->id);
  58  
  59          // Create users.
  60          $this->student = self::getDataGenerator()->create_user();
  61          $this->student2 = self::getDataGenerator()->create_user();
  62          $this->teacher = self::getDataGenerator()->create_user();
  63  
  64          // Users enrolments.
  65          $this->studentrole = $DB->get_record('role', array('shortname' => 'student'));
  66          $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
  67          $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual');
  68          $this->getDataGenerator()->enrol_user($this->student2->id, $this->course->id, $this->studentrole->id, 'manual');
  69          $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual');
  70  
  71          // Create first pages.
  72          $this->firstpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_first_page($this->wiki,
  73              array('tags' => array('Cats', 'Dogs')));
  74      }
  75  
  76      /**
  77       * Create two collaborative wikis (separate/visible groups), 2 groups and a first page for each wiki and group.
  78       */
  79      private function create_collaborative_wikis_with_groups() {
  80          // Create groups and add student to one of them.
  81          if (!isset($this->group1)) {
  82              $this->group1 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
  83              $this->getDataGenerator()->create_group_member(array('userid' => $this->student->id, 'groupid' => $this->group1->id));
  84              $this->getDataGenerator()->create_group_member(array('userid' => $this->student2->id, 'groupid' => $this->group1->id));
  85          }
  86          if (!isset($this->group2)) {
  87              $this->group2 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
  88          }
  89  
  90          // Create two collaborative wikis.
  91          $this->wikisep = $this->getDataGenerator()->create_module('wiki',
  92                                                          array('course' => $this->course->id, 'groupmode' => SEPARATEGROUPS));
  93          $this->wikivis = $this->getDataGenerator()->create_module('wiki',
  94                                                          array('course' => $this->course->id, 'groupmode' => VISIBLEGROUPS));
  95  
  96          // Create pages.
  97          $wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
  98          $this->fpsepg1 = $wikigenerator->create_first_page($this->wikisep, array('group' => $this->group1->id));
  99          $this->fpsepg2 = $wikigenerator->create_first_page($this->wikisep, array('group' => $this->group2->id));
 100          $this->fpsepall = $wikigenerator->create_first_page($this->wikisep, array('group' => 0)); // All participants.
 101          $this->fpvisg1 = $wikigenerator->create_first_page($this->wikivis, array('group' => $this->group1->id));
 102          $this->fpvisg2 = $wikigenerator->create_first_page($this->wikivis, array('group' => $this->group2->id));
 103          $this->fpvisall = $wikigenerator->create_first_page($this->wikivis, array('group' => 0)); // All participants.
 104      }
 105  
 106      /**
 107       * Create two individual wikis (separate/visible groups), 2 groups and a first page for each wiki and group.
 108       */
 109      private function create_individual_wikis_with_groups() {
 110          // Create groups and add student to one of them.
 111          if (!isset($this->group1)) {
 112              $this->group1 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
 113              $this->getDataGenerator()->create_group_member(array('userid' => $this->student->id, 'groupid' => $this->group1->id));
 114              $this->getDataGenerator()->create_group_member(array('userid' => $this->student2->id, 'groupid' => $this->group1->id));
 115          }
 116          if (!isset($this->group2)) {
 117              $this->group2 = $this->getDataGenerator()->create_group(array('courseid' => $this->course->id));
 118          }
 119  
 120          // Create two individual wikis.
 121          $this->wikisepind = $this->getDataGenerator()->create_module('wiki', array('course' => $this->course->id,
 122                                                          'groupmode' => SEPARATEGROUPS, 'wikimode' => 'individual'));
 123          $this->wikivisind = $this->getDataGenerator()->create_module('wiki', array('course' => $this->course->id,
 124                                                          'groupmode' => VISIBLEGROUPS, 'wikimode' => 'individual'));
 125  
 126          // Create pages. Student can only create pages in his groups.
 127          $wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
 128          $this->setUser($this->teacher);
 129          $this->fpsepg1indt = $wikigenerator->create_first_page($this->wikisepind, array('group' => $this->group1->id));
 130          $this->fpsepg2indt = $wikigenerator->create_first_page($this->wikisepind, array('group' => $this->group2->id));
 131          $this->fpsepallindt = $wikigenerator->create_first_page($this->wikisepind, array('group' => 0)); // All participants.
 132          $this->fpvisg1indt = $wikigenerator->create_first_page($this->wikivisind, array('group' => $this->group1->id));
 133          $this->fpvisg2indt = $wikigenerator->create_first_page($this->wikivisind, array('group' => $this->group2->id));
 134          $this->fpvisallindt = $wikigenerator->create_first_page($this->wikivisind, array('group' => 0)); // All participants.
 135  
 136          $this->setUser($this->student);
 137          $this->fpsepg1indstu = $wikigenerator->create_first_page($this->wikisepind, array('group' => $this->group1->id));
 138          $this->fpvisg1indstu = $wikigenerator->create_first_page($this->wikivisind, array('group' => $this->group1->id));
 139  
 140          $this->setUser($this->student2);
 141          $this->fpsepg1indstu2 = $wikigenerator->create_first_page($this->wikisepind, array('group' => $this->group1->id));
 142          $this->fpvisg1indstu2 = $wikigenerator->create_first_page($this->wikivisind, array('group' => $this->group1->id));
 143  
 144      }
 145  
 146      /*
 147       * Test get wikis by courses
 148       */
 149      public function test_mod_wiki_get_wikis_by_courses() {
 150  
 151          // Create additional course.
 152          $course2 = self::getDataGenerator()->create_course();
 153  
 154          // Second wiki.
 155          $record = new stdClass();
 156          $record->course = $course2->id;
 157          $wiki2 = self::getDataGenerator()->create_module('wiki', $record);
 158  
 159          // Execute real Moodle enrolment as we'll call unenrol() method on the instance later.
 160          $enrol = enrol_get_plugin('manual');
 161          $enrolinstances = enrol_get_instances($course2->id, true);
 162          foreach ($enrolinstances as $courseenrolinstance) {
 163              if ($courseenrolinstance->enrol == "manual") {
 164                  $instance2 = $courseenrolinstance;
 165                  break;
 166              }
 167          }
 168          $enrol->enrol_user($instance2, $this->student->id, $this->studentrole->id);
 169  
 170          self::setUser($this->student);
 171  
 172          $returndescription = mod_wiki_external::get_wikis_by_courses_returns();
 173  
 174          // Create what we expect to be returned when querying the two courses.
 175          // First for the student user.
 176          $expectedfields = array('id', 'coursemodule', 'course', 'name', 'intro', 'introformat', 'introfiles', 'firstpagetitle',
 177                                  'wikimode', 'defaultformat', 'forceformat', 'editbegin', 'editend', 'section', 'visible',
 178                                  'groupmode', 'groupingid');
 179  
 180          // Add expected coursemodule and data.
 181          $wiki1 = $this->wiki;
 182          $wiki1->coursemodule = $wiki1->cmid;
 183          $wiki1->introformat = 1;
 184          $wiki1->section = 0;
 185          $wiki1->visible = true;
 186          $wiki1->groupmode = 0;
 187          $wiki1->groupingid = 0;
 188          $wiki1->introfiles = [];
 189  
 190          $wiki2->coursemodule = $wiki2->cmid;
 191          $wiki2->introformat = 1;
 192          $wiki2->section = 0;
 193          $wiki2->visible = true;
 194          $wiki2->groupmode = 0;
 195          $wiki2->groupingid = 0;
 196          $wiki2->introfiles = [];
 197  
 198          foreach ($expectedfields as $field) {
 199              $expected1[$field] = $wiki1->{$field};
 200              $expected2[$field] = $wiki2->{$field};
 201          }
 202          // Users can create pages by default.
 203          $expected1['cancreatepages'] = true;
 204          $expected2['cancreatepages'] = true;
 205  
 206          $expectedwikis = array($expected2, $expected1);
 207  
 208          // Call the external function passing course ids.
 209          $result = mod_wiki_external::get_wikis_by_courses(array($course2->id, $this->course->id));
 210          $result = external_api::clean_returnvalue($returndescription, $result);
 211  
 212          $this->assertEquals($expectedwikis, $result['wikis']);
 213          $this->assertCount(0, $result['warnings']);
 214  
 215          // Call the external function without passing course id.
 216          $result = mod_wiki_external::get_wikis_by_courses();
 217          $result = external_api::clean_returnvalue($returndescription, $result);
 218          $this->assertEquals($expectedwikis, $result['wikis']);
 219          $this->assertCount(0, $result['warnings']);
 220  
 221          // Unenrol user from second course and alter expected wikis.
 222          $enrol->unenrol_user($instance2, $this->student->id);
 223          array_shift($expectedwikis);
 224  
 225          // Call the external function without passing course id.
 226          $result = mod_wiki_external::get_wikis_by_courses();
 227          $result = external_api::clean_returnvalue($returndescription, $result);
 228          $this->assertEquals($expectedwikis, $result['wikis']);
 229  
 230          // Call for the second course we unenrolled the user from, expected warning.
 231          $result = mod_wiki_external::get_wikis_by_courses(array($course2->id));
 232          $this->assertCount(1, $result['warnings']);
 233          $this->assertEquals('1', $result['warnings'][0]['warningcode']);
 234          $this->assertEquals($course2->id, $result['warnings'][0]['itemid']);
 235  
 236          // Now, try as a teacher for getting all the additional fields.
 237          self::setUser($this->teacher);
 238  
 239          $additionalfields = array('timecreated', 'timemodified');
 240  
 241          foreach ($additionalfields as $field) {
 242              $expectedwikis[0][$field] = $wiki1->{$field};
 243          }
 244  
 245          $result = mod_wiki_external::get_wikis_by_courses();
 246          $result = external_api::clean_returnvalue($returndescription, $result);
 247          $this->assertEquals($expectedwikis, $result['wikis']);
 248  
 249          // Admin also should get all the information.
 250          self::setAdminUser();
 251  
 252          $result = mod_wiki_external::get_wikis_by_courses(array($this->course->id));
 253          $result = external_api::clean_returnvalue($returndescription, $result);
 254          $this->assertEquals($expectedwikis, $result['wikis']);
 255  
 256          // Now, prohibit capabilities.
 257          $this->setUser($this->student);
 258          $contextcourse1 = context_course::instance($this->course->id);
 259  
 260          // Default student role allows to view wiki and create pages.
 261          $wikis = mod_wiki_external::get_wikis_by_courses(array($this->course->id));
 262          $wikis = external_api::clean_returnvalue(mod_wiki_external::get_wikis_by_courses_returns(), $wikis);
 263          $this->assertEquals('Test wiki 1', $wikis['wikis'][0]['intro']);
 264          $this->assertEquals(1, $wikis['wikis'][0]['cancreatepages']);
 265  
 266          // Prohibit capability = mod:wiki:viewpage on Course1 for students.
 267          assign_capability('mod/wiki:viewpage', CAP_PROHIBIT, $this->studentrole->id, $contextcourse1->id, true);
 268          accesslib_clear_all_caches_for_unit_testing();
 269          course_modinfo::clear_instance_cache(null);
 270  
 271          $wikis = mod_wiki_external::get_wikis_by_courses(array($this->course->id));
 272          $wikis = external_api::clean_returnvalue(mod_wiki_external::get_wikis_by_courses_returns(), $wikis);
 273          $this->assertEquals(0, count($wikis['wikis']));
 274  
 275          // Prohibit capability = mod:wiki:createpage on Course1 for students.
 276          assign_capability('mod/wiki:viewpage', CAP_ALLOW, $this->studentrole->id, $contextcourse1->id, true);
 277          assign_capability('mod/wiki:createpage', CAP_PROHIBIT, $this->studentrole->id, $contextcourse1->id);
 278          accesslib_clear_all_caches_for_unit_testing();
 279          course_modinfo::clear_instance_cache(null);
 280  
 281          $wikis = mod_wiki_external::get_wikis_by_courses(array($this->course->id));
 282          $wikis = external_api::clean_returnvalue(mod_wiki_external::get_wikis_by_courses_returns(), $wikis);
 283          $this->assertFalse($wikis['wikis'][0]['cancreatepages']);
 284  
 285      }
 286  
 287      /**
 288       * Test view_wiki.
 289       */
 290      public function test_view_wiki() {
 291  
 292          // Test invalid instance id.
 293          try {
 294              mod_wiki_external::view_wiki(0);
 295              $this->fail('Exception expected due to invalid mod_wiki instance id.');
 296          } catch (moodle_exception $e) {
 297              $this->assertEquals('incorrectwikiid', $e->errorcode);
 298          }
 299  
 300          // Test not-enrolled user.
 301          $usernotenrolled = self::getDataGenerator()->create_user();
 302          $this->setUser($usernotenrolled);
 303          try {
 304              mod_wiki_external::view_wiki($this->wiki->id);
 305              $this->fail('Exception expected due to not enrolled user.');
 306          } catch (moodle_exception $e) {
 307              $this->assertEquals('requireloginerror', $e->errorcode);
 308          }
 309  
 310          // Test user with full capabilities.
 311          $this->setUser($this->student);
 312  
 313          // Trigger and capture the event.
 314          $sink = $this->redirectEvents();
 315  
 316          $result = mod_wiki_external::view_wiki($this->wiki->id);
 317          $result = external_api::clean_returnvalue(mod_wiki_external::view_wiki_returns(), $result);
 318  
 319          $events = $sink->get_events();
 320          $this->assertCount(1, $events);
 321          $event = array_shift($events);
 322  
 323          // Checking that the event contains the expected values.
 324          $this->assertInstanceOf('\mod_wiki\event\course_module_viewed', $event);
 325          $this->assertEquals($this->context, $event->get_context());
 326          $moodlewiki = new \moodle_url('/mod/wiki/view.php', array('id' => $this->cm->id));
 327          $this->assertEquals($moodlewiki, $event->get_url());
 328          $this->assertEventContextNotUsed($event);
 329          $this->assertNotEmpty($event->get_name());
 330  
 331          // Test user with no capabilities.
 332          // We need a explicit prohibit since this capability is allowed for students by default.
 333          assign_capability('mod/wiki:viewpage', CAP_PROHIBIT, $this->studentrole->id, $this->context->id);
 334          accesslib_clear_all_caches_for_unit_testing();
 335  
 336          try {
 337              mod_wiki_external::view_wiki($this->wiki->id);
 338              $this->fail('Exception expected due to missing capability.');
 339          } catch (moodle_exception $e) {
 340              $this->assertEquals('cannotviewpage', $e->errorcode);
 341          }
 342  
 343      }
 344  
 345      /**
 346       * Test view_page.
 347       */
 348      public function test_view_page() {
 349  
 350          // Test invalid page id.
 351          try {
 352              mod_wiki_external::view_page(0);
 353              $this->fail('Exception expected due to invalid view_page page id.');
 354          } catch (moodle_exception $e) {
 355              $this->assertEquals('incorrectpageid', $e->errorcode);
 356          }
 357  
 358          // Test not-enrolled user.
 359          $usernotenrolled = self::getDataGenerator()->create_user();
 360          $this->setUser($usernotenrolled);
 361          try {
 362              mod_wiki_external::view_page($this->firstpage->id);
 363              $this->fail('Exception expected due to not enrolled user.');
 364          } catch (moodle_exception $e) {
 365              $this->assertEquals('requireloginerror', $e->errorcode);
 366          }
 367  
 368          // Test user with full capabilities.
 369          $this->setUser($this->student);
 370  
 371          // Trigger and capture the event.
 372          $sink = $this->redirectEvents();
 373  
 374          $result = mod_wiki_external::view_page($this->firstpage->id);
 375          $result = external_api::clean_returnvalue(mod_wiki_external::view_page_returns(), $result);
 376  
 377          $events = $sink->get_events();
 378          $this->assertCount(1, $events);
 379          $event = array_shift($events);
 380  
 381          // Checking that the event contains the expected values.
 382          $this->assertInstanceOf('\mod_wiki\event\page_viewed', $event);
 383          $this->assertEquals($this->context, $event->get_context());
 384          $pageurl = new \moodle_url('/mod/wiki/view.php', array('pageid' => $this->firstpage->id));
 385          $this->assertEquals($pageurl, $event->get_url());
 386          $this->assertEventContextNotUsed($event);
 387          $this->assertNotEmpty($event->get_name());
 388  
 389          // Test user with no capabilities.
 390          // We need a explicit prohibit since this capability is allowed for students by default.
 391          assign_capability('mod/wiki:viewpage', CAP_PROHIBIT, $this->studentrole->id, $this->context->id);
 392          accesslib_clear_all_caches_for_unit_testing();
 393  
 394          try {
 395              mod_wiki_external::view_page($this->firstpage->id);
 396              $this->fail('Exception expected due to missing capability.');
 397          } catch (moodle_exception $e) {
 398              $this->assertEquals('cannotviewpage', $e->errorcode);
 399          }
 400  
 401      }
 402  
 403      /**
 404       * Test get_subwikis.
 405       */
 406      public function test_get_subwikis() {
 407  
 408          // Test invalid wiki id.
 409          try {
 410              mod_wiki_external::get_subwikis(0);
 411              $this->fail('Exception expected due to invalid get_subwikis wiki id.');
 412          } catch (moodle_exception $e) {
 413              $this->assertEquals('incorrectwikiid', $e->errorcode);
 414          }
 415  
 416          // Test not-enrolled user.
 417          $usernotenrolled = self::getDataGenerator()->create_user();
 418          $this->setUser($usernotenrolled);
 419          try {
 420              mod_wiki_external::get_subwikis($this->wiki->id);
 421              $this->fail('Exception expected due to not enrolled user.');
 422          } catch (moodle_exception $e) {
 423              $this->assertEquals('requireloginerror', $e->errorcode);
 424          }
 425  
 426          // Test user with full capabilities.
 427          $this->setUser($this->student);
 428  
 429          // Create what we expect to be returned. We only test a basic case because deep testing is already done
 430          // in the tests for wiki_get_visible_subwikis.
 431          $expectedsubwikis = array();
 432          $expectedsubwiki = array(
 433                  'id' => $this->firstpage->subwikiid,
 434                  'wikiid' => $this->wiki->id,
 435                  'groupid' => 0,
 436                  'userid' => 0,
 437                  'canedit' => true
 438              );
 439          $expectedsubwikis[] = $expectedsubwiki;
 440  
 441          $result = mod_wiki_external::get_subwikis($this->wiki->id);
 442          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwikis_returns(), $result);
 443          $this->assertEquals($expectedsubwikis, $result['subwikis']);
 444          $this->assertCount(0, $result['warnings']);
 445  
 446          // Test user with no capabilities.
 447          // We need a explicit prohibit since this capability is allowed for students by default.
 448          assign_capability('mod/wiki:viewpage', CAP_PROHIBIT, $this->studentrole->id, $this->context->id);
 449          accesslib_clear_all_caches_for_unit_testing();
 450  
 451          try {
 452              mod_wiki_external::get_subwikis($this->wiki->id);
 453              $this->fail('Exception expected due to missing capability.');
 454          } catch (moodle_exception $e) {
 455              $this->assertEquals('nopermissions', $e->errorcode);
 456          }
 457  
 458      }
 459  
 460      /**
 461       * Test get_subwiki_pages using an invalid wiki instance.
 462       */
 463      public function test_get_subwiki_pages_invalid_instance() {
 464          $this->expectException(moodle_exception::class);
 465          mod_wiki_external::get_subwiki_pages(0);
 466      }
 467  
 468      /**
 469       * Test get_subwiki_pages using a user not enrolled in the course.
 470       */
 471      public function test_get_subwiki_pages_unenrolled_user() {
 472          // Create and use the user.
 473          $usernotenrolled = self::getDataGenerator()->create_user();
 474          $this->setUser($usernotenrolled);
 475  
 476          $this->expectException(require_login_exception::class);
 477          mod_wiki_external::get_subwiki_pages($this->wiki->id);
 478      }
 479  
 480      /**
 481       * Test get_subwiki_pages using a hidden wiki as student.
 482       */
 483      public function test_get_subwiki_pages_hidden_wiki_as_student() {
 484          // Create a hidden wiki and try to get the list of pages.
 485          $hiddenwiki = $this->getDataGenerator()->create_module('wiki',
 486                              array('course' => $this->course->id, 'visible' => false));
 487  
 488          $this->setUser($this->student);
 489          $this->expectException(require_login_exception::class);
 490          mod_wiki_external::get_subwiki_pages($hiddenwiki->id);
 491      }
 492  
 493      /**
 494       * Test get_subwiki_pages without the viewpage capability.
 495       */
 496      public function test_get_subwiki_pages_without_viewpage_capability() {
 497          // Prohibit capability = mod/wiki:viewpage on the course for students.
 498          $contextcourse = context_course::instance($this->course->id);
 499          assign_capability('mod/wiki:viewpage', CAP_PROHIBIT, $this->studentrole->id, $contextcourse->id);
 500          accesslib_clear_all_caches_for_unit_testing();
 501  
 502          $this->setUser($this->student);
 503          $this->expectException(moodle_exception::class);
 504          mod_wiki_external::get_subwiki_pages($this->wiki->id);
 505      }
 506  
 507      /**
 508       * Test get_subwiki_pages using an invalid userid.
 509       */
 510      public function test_get_subwiki_pages_invalid_userid() {
 511          // Create an individual wiki.
 512          $indwiki = $this->getDataGenerator()->create_module('wiki',
 513                                  array('course' => $this->course->id, 'wikimode' => 'individual'));
 514  
 515          $this->expectException(moodle_exception::class);
 516          mod_wiki_external::get_subwiki_pages($indwiki->id, 0, -10);
 517      }
 518  
 519      /**
 520       * Test get_subwiki_pages using an invalid groupid.
 521       */
 522      public function test_get_subwiki_pages_invalid_groupid() {
 523          // Create testing data.
 524          $this->create_collaborative_wikis_with_groups();
 525  
 526          $this->expectException(moodle_exception::class);
 527          mod_wiki_external::get_subwiki_pages($this->wikisep->id, -111);
 528      }
 529  
 530      /**
 531       * Test get_subwiki_pages, check that a student can't see another user pages in an individual wiki without groups.
 532       */
 533      public function test_get_subwiki_pages_individual_student_see_other_user() {
 534          // Create an individual wiki.
 535          $indwiki = $this->getDataGenerator()->create_module('wiki',
 536                                  array('course' => $this->course->id, 'wikimode' => 'individual'));
 537  
 538          $this->setUser($this->student);
 539          $this->expectException(moodle_exception::class);
 540          mod_wiki_external::get_subwiki_pages($indwiki->id, 0, $this->teacher->id);
 541      }
 542  
 543      /**
 544       * Test get_subwiki_pages, check that a student can't get the pages from another group in
 545       * a collaborative wiki using separate groups.
 546       */
 547      public function test_get_subwiki_pages_collaborative_separate_groups_student_see_other_group() {
 548          // Create testing data.
 549          $this->create_collaborative_wikis_with_groups();
 550  
 551          $this->setUser($this->student);
 552          $this->expectException(moodle_exception::class);
 553          mod_wiki_external::get_subwiki_pages($this->wikisep->id, $this->group2->id);
 554      }
 555  
 556      /**
 557       * Test get_subwiki_pages, check that a student can't get the pages from another group in
 558       * an individual wiki using separate groups.
 559       */
 560      public function test_get_subwiki_pages_individual_separate_groups_student_see_other_group() {
 561          // Create testing data.
 562          $this->create_individual_wikis_with_groups();
 563  
 564          $this->setUser($this->student);
 565          $this->expectException(moodle_exception::class);
 566          mod_wiki_external::get_subwiki_pages($this->wikisepind->id, $this->group2->id, $this->teacher->id);
 567      }
 568  
 569      /**
 570       * Test get_subwiki_pages, check that a student can't get the pages from all participants in
 571       * a collaborative wiki using separate groups.
 572       */
 573      public function test_get_subwiki_pages_collaborative_separate_groups_student_see_all_participants() {
 574          // Create testing data.
 575          $this->create_collaborative_wikis_with_groups();
 576  
 577          $this->setUser($this->student);
 578          $this->expectException(moodle_exception::class);
 579          mod_wiki_external::get_subwiki_pages($this->wikisep->id, 0);
 580      }
 581  
 582      /**
 583       * Test get_subwiki_pages, check that a student can't get the pages from all participants in
 584       * an individual wiki using separate groups.
 585       */
 586      public function test_get_subwiki_pages_individual_separate_groups_student_see_all_participants() {
 587          // Create testing data.
 588          $this->create_individual_wikis_with_groups();
 589  
 590          $this->setUser($this->student);
 591          $this->expectException(moodle_exception::class);
 592          mod_wiki_external::get_subwiki_pages($this->wikisepind->id, 0, $this->teacher->id);
 593      }
 594  
 595      /**
 596       * Test get_subwiki_pages without groups and collaborative wiki.
 597       */
 598      public function test_get_subwiki_pages_collaborative() {
 599  
 600          // Test user with full capabilities.
 601          $this->setUser($this->student);
 602  
 603          // Set expected result: first page.
 604          $expectedpages = array();
 605          $expectedfirstpage = (array) $this->firstpage;
 606          $expectedfirstpage['caneditpage'] = true; // No groups and students have 'mod/wiki:editpage' capability.
 607          $expectedfirstpage['firstpage'] = true;
 608          $expectedfirstpage['contentformat'] = 1;
 609          $expectedfirstpage['tags'] = \core_tag\external\util::get_item_tags('mod_wiki', 'wiki_pages', $this->firstpage->id);
 610          // Cast to expected.
 611          $expectedfirstpage['tags'][0]['isstandard'] = (bool) $expectedfirstpage['tags'][0]['isstandard'];
 612          $expectedfirstpage['tags'][1]['isstandard'] = (bool) $expectedfirstpage['tags'][1]['isstandard'];
 613          $expectedpages[] = $expectedfirstpage;
 614  
 615          $result = mod_wiki_external::get_subwiki_pages($this->wiki->id);
 616          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 617          $this->assertEquals($expectedpages, $result['pages']);
 618  
 619          // Check that groupid param is ignored since the wiki isn't using groups.
 620          $result = mod_wiki_external::get_subwiki_pages($this->wiki->id, 1234);
 621          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 622          $this->assertEquals($expectedpages, $result['pages']);
 623  
 624          // Check that userid param is ignored since the wiki is collaborative.
 625          $result = mod_wiki_external::get_subwiki_pages($this->wiki->id, 1234, 1234);
 626          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 627          $this->assertEquals($expectedpages, $result['pages']);
 628  
 629          // Add a new page to the wiki and test again. We'll use a custom title so it's returned first if sorted by title.
 630          $newpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_page(
 631                                  $this->wiki, array('title' => 'AAA'));
 632  
 633          $expectednewpage = (array) $newpage;
 634          $expectednewpage['caneditpage'] = true; // No groups and students have 'mod/wiki:editpage' capability.
 635          $expectednewpage['firstpage'] = false;
 636          $expectednewpage['contentformat'] = 1;
 637          $expectednewpage['tags'] = array();
 638          array_unshift($expectedpages, $expectednewpage); // Add page to the beginning since it orders by title by default.
 639  
 640          $result = mod_wiki_external::get_subwiki_pages($this->wiki->id);
 641          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 642          $this->assertEquals($expectedpages, $result['pages']);
 643  
 644          // Now we'll order by ID. Since first page was created first it'll have a lower ID.
 645          $expectedpages = array($expectedfirstpage, $expectednewpage);
 646          $result = mod_wiki_external::get_subwiki_pages($this->wiki->id, 0, 0, array('sortby' => 'id'));
 647          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 648          $this->assertEquals($expectedpages, $result['pages']);
 649  
 650          // Check that WS doesn't return page content if includecontent is false, it returns the size instead.
 651          foreach ($expectedpages as $i => $expectedpage) {
 652              if (function_exists('mb_strlen') && ((int)ini_get('mbstring.func_overload') & 2)) {
 653                  $expectedpages[$i]['contentsize'] = mb_strlen($expectedpages[$i]['cachedcontent'], '8bit');
 654              } else {
 655                  $expectedpages[$i]['contentsize'] = strlen($expectedpages[$i]['cachedcontent']);
 656              }
 657              unset($expectedpages[$i]['cachedcontent']);
 658              unset($expectedpages[$i]['contentformat']);
 659          }
 660          $result = mod_wiki_external::get_subwiki_pages($this->wiki->id, 0, 0, array('sortby' => 'id', 'includecontent' => 0));
 661          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 662          $this->assertEquals($expectedpages, $result['pages']);
 663      }
 664  
 665      /**
 666       * Test get_subwiki_pages without groups.
 667       */
 668      public function test_get_subwiki_pages_individual() {
 669  
 670          // Create an individual wiki to test userid param.
 671          $indwiki = $this->getDataGenerator()->create_module('wiki',
 672                                  array('course' => $this->course->id, 'wikimode' => 'individual'));
 673  
 674          // Perform a request before creating any page to check that an empty array is returned if subwiki doesn't exist.
 675          $result = mod_wiki_external::get_subwiki_pages($indwiki->id);
 676          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 677          $this->assertEquals(array(), $result['pages']);
 678  
 679          // Create first pages as student and teacher.
 680          $this->setUser($this->student);
 681          $indfirstpagestudent = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_first_page($indwiki);
 682          $this->setUser($this->teacher);
 683          $indfirstpageteacher = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_first_page($indwiki);
 684  
 685          // Check that teacher can get his pages.
 686          $expectedteacherpage = (array) $indfirstpageteacher;
 687          $expectedteacherpage['caneditpage'] = true;
 688          $expectedteacherpage['firstpage'] = true;
 689          $expectedteacherpage['contentformat'] = 1;
 690          $expectedteacherpage['tags'] = array();
 691          $expectedpages = array($expectedteacherpage);
 692  
 693          $result = mod_wiki_external::get_subwiki_pages($indwiki->id, 0, $this->teacher->id);
 694          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 695          $this->assertEquals($expectedpages, $result['pages']);
 696  
 697          // Check that the teacher can see the student's pages.
 698          $expectedstudentpage = (array) $indfirstpagestudent;
 699          $expectedstudentpage['caneditpage'] = true;
 700          $expectedstudentpage['firstpage'] = true;
 701          $expectedstudentpage['contentformat'] = 1;
 702          $expectedstudentpage['tags'] = array();
 703          $expectedpages = array($expectedstudentpage);
 704  
 705          $result = mod_wiki_external::get_subwiki_pages($indwiki->id, 0, $this->student->id);
 706          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 707          $this->assertEquals($expectedpages, $result['pages']);
 708  
 709          // Now check that student can get his pages.
 710          $this->setUser($this->student);
 711  
 712          $result = mod_wiki_external::get_subwiki_pages($indwiki->id, 0, $this->student->id);
 713          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 714          $this->assertEquals($expectedpages, $result['pages']);
 715  
 716          // Check that not using userid uses current user.
 717          $result = mod_wiki_external::get_subwiki_pages($indwiki->id, 0);
 718          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 719          $this->assertEquals($expectedpages, $result['pages']);
 720      }
 721  
 722      /**
 723       * Test get_subwiki_pages with groups and collaborative wikis.
 724       */
 725      public function test_get_subwiki_pages_separate_groups_collaborative() {
 726  
 727          // Create testing data.
 728          $this->create_collaborative_wikis_with_groups();
 729  
 730          $this->setUser($this->student);
 731  
 732          // Try to get pages from a valid group in separate groups wiki.
 733  
 734          $expectedpage = (array) $this->fpsepg1;
 735          $expectedpage['caneditpage'] = true; // User belongs to group and has 'mod/wiki:editpage' capability.
 736          $expectedpage['firstpage'] = true;
 737          $expectedpage['contentformat'] = 1;
 738          $expectedpage['tags'] = array();
 739          $expectedpages = array($expectedpage);
 740  
 741          $result = mod_wiki_external::get_subwiki_pages($this->wikisep->id, $this->group1->id);
 742          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 743          $this->assertEquals($expectedpages, $result['pages']);
 744  
 745          // Let's check that not using groupid returns the same result (current group).
 746          $result = mod_wiki_external::get_subwiki_pages($this->wikisep->id);
 747          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 748          $this->assertEquals($expectedpages, $result['pages']);
 749  
 750          // Check that teacher can view a group pages without belonging to it.
 751          $this->setUser($this->teacher);
 752          $result = mod_wiki_external::get_subwiki_pages($this->wikisep->id, $this->group1->id);
 753          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 754          $this->assertEquals($expectedpages, $result['pages']);
 755  
 756          // Check that teacher can get the pages from all participants.
 757          $expectedpage = (array) $this->fpsepall;
 758          $expectedpage['caneditpage'] = true;
 759          $expectedpage['firstpage'] = true;
 760          $expectedpage['contentformat'] = 1;
 761          $expectedpage['tags'] = array();
 762          $expectedpages = array($expectedpage);
 763  
 764          $result = mod_wiki_external::get_subwiki_pages($this->wikisep->id, 0);
 765          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 766          $this->assertEquals($expectedpages, $result['pages']);
 767      }
 768  
 769      /**
 770       * Test get_subwiki_pages with groups and collaborative wikis.
 771       */
 772      public function test_get_subwiki_pages_visible_groups_collaborative() {
 773  
 774          // Create testing data.
 775          $this->create_collaborative_wikis_with_groups();
 776  
 777          $this->setUser($this->student);
 778  
 779          // Try to get pages from a valid group in visible groups wiki.
 780  
 781          $expectedpage = (array) $this->fpvisg1;
 782          $expectedpage['caneditpage'] = true; // User belongs to group and has 'mod/wiki:editpage' capability.
 783          $expectedpage['firstpage'] = true;
 784          $expectedpage['contentformat'] = 1;
 785          $expectedpage['tags'] = array();
 786          $expectedpages = array($expectedpage);
 787  
 788          $result = mod_wiki_external::get_subwiki_pages($this->wikivis->id, $this->group1->id);
 789          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 790          $this->assertEquals($expectedpages, $result['pages']);
 791  
 792          // Check that with visible groups a student can get the pages of groups he doesn't belong to.
 793          $expectedpage = (array) $this->fpvisg2;
 794          $expectedpage['caneditpage'] = false; // User doesn't belong to group so he can't edit the page.
 795          $expectedpage['firstpage'] = true;
 796          $expectedpage['contentformat'] = 1;
 797          $expectedpage['tags'] = array();
 798          $expectedpages = array($expectedpage);
 799  
 800          $result = mod_wiki_external::get_subwiki_pages($this->wikivis->id, $this->group2->id);
 801          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 802          $this->assertEquals($expectedpages, $result['pages']);
 803  
 804          // Check that with visible groups a student can get the pages of all participants.
 805          $expectedpage = (array) $this->fpvisall;
 806          $expectedpage['caneditpage'] = false;
 807          $expectedpage['firstpage'] = true;
 808          $expectedpage['contentformat'] = 1;
 809          $expectedpage['tags'] = array();
 810          $expectedpages = array($expectedpage);
 811  
 812          $result = mod_wiki_external::get_subwiki_pages($this->wikivis->id, 0);
 813          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 814          $this->assertEquals($expectedpages, $result['pages']);
 815      }
 816  
 817      /**
 818       * Test get_subwiki_pages with groups and individual wikis.
 819       */
 820      public function test_get_subwiki_pages_separate_groups_individual() {
 821  
 822          // Create testing data.
 823          $this->create_individual_wikis_with_groups();
 824  
 825          $this->setUser($this->student);
 826  
 827          // Check that student can retrieve his pages from separate wiki.
 828          $expectedpage = (array) $this->fpsepg1indstu;
 829          $expectedpage['caneditpage'] = true;
 830          $expectedpage['firstpage'] = true;
 831          $expectedpage['contentformat'] = 1;
 832          $expectedpage['tags'] = array();
 833          $expectedpages = array($expectedpage);
 834  
 835          $result = mod_wiki_external::get_subwiki_pages($this->wikisepind->id, $this->group1->id, $this->student->id);
 836          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 837          $this->assertEquals($expectedpages, $result['pages']);
 838  
 839          // Check that not using userid uses current user.
 840          $result = mod_wiki_external::get_subwiki_pages($this->wikisepind->id, $this->group1->id);
 841          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 842          $this->assertEquals($expectedpages, $result['pages']);
 843  
 844          // Check that the teacher can see the student pages.
 845          $this->setUser($this->teacher);
 846          $result = mod_wiki_external::get_subwiki_pages($this->wikisepind->id, $this->group1->id, $this->student->id);
 847          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 848          $this->assertEquals($expectedpages, $result['pages']);
 849  
 850          // Check that a student can see pages from another user that belongs to his groups.
 851          $this->setUser($this->student);
 852          $expectedpage = (array) $this->fpsepg1indstu2;
 853          $expectedpage['caneditpage'] = false;
 854          $expectedpage['firstpage'] = true;
 855          $expectedpage['contentformat'] = 1;
 856          $expectedpage['tags'] = array();
 857          $expectedpages = array($expectedpage);
 858  
 859          $result = mod_wiki_external::get_subwiki_pages($this->wikisepind->id, $this->group1->id, $this->student2->id);
 860          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 861          $this->assertEquals($expectedpages, $result['pages']);
 862      }
 863  
 864      /**
 865       * Test get_subwiki_pages with groups and individual wikis.
 866       */
 867      public function test_get_subwiki_pages_visible_groups_individual() {
 868  
 869          // Create testing data.
 870          $this->create_individual_wikis_with_groups();
 871  
 872          $this->setUser($this->student);
 873  
 874          // Check that student can retrieve his pages from visible wiki.
 875          $expectedpage = (array) $this->fpvisg1indstu;
 876          $expectedpage['caneditpage'] = true;
 877          $expectedpage['firstpage'] = true;
 878          $expectedpage['contentformat'] = 1;
 879          $expectedpage['tags'] = array();
 880          $expectedpages = array($expectedpage);
 881  
 882          $result = mod_wiki_external::get_subwiki_pages($this->wikivisind->id, $this->group1->id, $this->student->id);
 883          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 884          $this->assertEquals($expectedpages, $result['pages']);
 885  
 886          // Check that student can see teacher pages in visible groups, even if the user doesn't belong to the group.
 887          $expectedpage = (array) $this->fpvisg2indt;
 888          $expectedpage['caneditpage'] = false;
 889          $expectedpage['firstpage'] = true;
 890          $expectedpage['contentformat'] = 1;
 891          $expectedpage['tags'] = array();
 892          $expectedpages = array($expectedpage);
 893  
 894          $result = mod_wiki_external::get_subwiki_pages($this->wikivisind->id, $this->group2->id, $this->teacher->id);
 895          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 896          $this->assertEquals($expectedpages, $result['pages']);
 897  
 898          // Check that with visible groups a student can get the pages of all participants.
 899          $expectedpage = (array) $this->fpvisallindt;
 900          $expectedpage['caneditpage'] = false;
 901          $expectedpage['firstpage'] = true;
 902          $expectedpage['contentformat'] = 1;
 903          $expectedpage['tags'] = array();
 904          $expectedpages = array($expectedpage);
 905  
 906          $result = mod_wiki_external::get_subwiki_pages($this->wikivisind->id, 0, $this->teacher->id);
 907          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_pages_returns(), $result);
 908          $this->assertEquals($expectedpages, $result['pages']);
 909      }
 910  
 911      /**
 912       * Test get_page_contents using an invalid pageid.
 913       */
 914      public function test_get_page_contents_invalid_pageid() {
 915          $this->expectException(moodle_exception::class);
 916          mod_wiki_external::get_page_contents(0);
 917      }
 918  
 919      /**
 920       * Test get_page_contents using a user not enrolled in the course.
 921       */
 922      public function test_get_page_contents_unenrolled_user() {
 923          // Create and use the user.
 924          $usernotenrolled = self::getDataGenerator()->create_user();
 925          $this->setUser($usernotenrolled);
 926  
 927          $this->expectException(require_login_exception::class);
 928          mod_wiki_external::get_page_contents($this->firstpage->id);
 929      }
 930  
 931      /**
 932       * Test get_page_contents using a hidden wiki as student.
 933       */
 934      public function test_get_page_contents_hidden_wiki_as_student() {
 935          // Create a hidden wiki and try to get a page contents.
 936          $hiddenwiki = $this->getDataGenerator()->create_module('wiki',
 937                              array('course' => $this->course->id, 'visible' => false));
 938          $hiddenpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_page($hiddenwiki);
 939  
 940          $this->setUser($this->student);
 941          $this->expectException(require_login_exception::class);
 942          mod_wiki_external::get_page_contents($hiddenpage->id);
 943      }
 944  
 945      /**
 946       * Test get_page_contents without the viewpage capability.
 947       */
 948      public function test_get_page_contents_without_viewpage_capability() {
 949          // Prohibit capability = mod/wiki:viewpage on the course for students.
 950          $contextcourse = context_course::instance($this->course->id);
 951          assign_capability('mod/wiki:viewpage', CAP_PROHIBIT, $this->studentrole->id, $contextcourse->id);
 952          accesslib_clear_all_caches_for_unit_testing();
 953  
 954          $this->setUser($this->student);
 955          $this->expectException(moodle_exception::class);
 956          mod_wiki_external::get_page_contents($this->firstpage->id);
 957      }
 958  
 959      /**
 960       * Test get_page_contents, check that a student can't get a page from another group when
 961       * using separate groups.
 962       */
 963      public function test_get_page_contents_separate_groups_student_see_other_group() {
 964          // Create testing data.
 965          $this->create_individual_wikis_with_groups();
 966  
 967          $this->setUser($this->student);
 968          $this->expectException(moodle_exception::class);
 969          mod_wiki_external::get_page_contents($this->fpsepg2indt->id);
 970      }
 971  
 972      /**
 973       * Test get_page_contents without groups. We won't test all the possible cases because that's already
 974       * done in the tests for get_subwiki_pages.
 975       */
 976      public function test_get_page_contents() {
 977  
 978          // Test user with full capabilities.
 979          $this->setUser($this->student);
 980  
 981          // Set expected result: first page.
 982          $expectedpage = array(
 983              'id' => $this->firstpage->id,
 984              'wikiid' => $this->wiki->id,
 985              'subwikiid' => $this->firstpage->subwikiid,
 986              'groupid' => 0, // No groups.
 987              'userid' => 0, // Collaborative.
 988              'title' => $this->firstpage->title,
 989              'cachedcontent' => $this->firstpage->cachedcontent,
 990              'contentformat' => 1,
 991              'caneditpage' => true,
 992              'version' => 1,
 993              'tags' => \core_tag\external\util::get_item_tags('mod_wiki', 'wiki_pages', $this->firstpage->id),
 994          );
 995          // Cast to expected.
 996          $expectedpage['tags'][0]['isstandard'] = (bool) $expectedpage['tags'][0]['isstandard'];
 997          $expectedpage['tags'][1]['isstandard'] = (bool) $expectedpage['tags'][1]['isstandard'];
 998  
 999          $result = mod_wiki_external::get_page_contents($this->firstpage->id);
1000          $result = external_api::clean_returnvalue(mod_wiki_external::get_page_contents_returns(), $result);
1001          $this->assertEquals($expectedpage, $result['page']);
1002  
1003          // Add a new page to the wiki and test with it.
1004          $newpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_page($this->wiki);
1005  
1006          $expectedpage['id'] = $newpage->id;
1007          $expectedpage['title'] = $newpage->title;
1008          $expectedpage['cachedcontent'] = $newpage->cachedcontent;
1009          $expectedpage['tags'] = array();
1010  
1011          $result = mod_wiki_external::get_page_contents($newpage->id);
1012          $result = external_api::clean_returnvalue(mod_wiki_external::get_page_contents_returns(), $result);
1013          $this->assertEquals($expectedpage, $result['page']);
1014      }
1015  
1016      /**
1017       * Test get_page_contents with groups. We won't test all the possible cases because that's already
1018       * done in the tests for get_subwiki_pages.
1019       */
1020      public function test_get_page_contents_with_groups() {
1021  
1022          // Create testing data.
1023          $this->create_individual_wikis_with_groups();
1024  
1025          // Try to get page from a valid group in separate groups wiki.
1026          $this->setUser($this->student);
1027  
1028          $expectedfpsepg1indstu = array(
1029              'id' => $this->fpsepg1indstu->id,
1030              'wikiid' => $this->wikisepind->id,
1031              'subwikiid' => $this->fpsepg1indstu->subwikiid,
1032              'groupid' => $this->group1->id,
1033              'userid' => $this->student->id,
1034              'title' => $this->fpsepg1indstu->title,
1035              'cachedcontent' => $this->fpsepg1indstu->cachedcontent,
1036              'contentformat' => 1,
1037              'caneditpage' => true,
1038              'version' => 1,
1039              'tags' => array(),
1040          );
1041  
1042          $result = mod_wiki_external::get_page_contents($this->fpsepg1indstu->id);
1043          $result = external_api::clean_returnvalue(mod_wiki_external::get_page_contents_returns(), $result);
1044          $this->assertEquals($expectedfpsepg1indstu, $result['page']);
1045  
1046          // Check that teacher can view a group pages without belonging to it.
1047          $this->setUser($this->teacher);
1048          $result = mod_wiki_external::get_page_contents($this->fpsepg1indstu->id);
1049          $result = external_api::clean_returnvalue(mod_wiki_external::get_page_contents_returns(), $result);
1050          $this->assertEquals($expectedfpsepg1indstu, $result['page']);
1051      }
1052  
1053      /**
1054       * Test get_subwiki_files using a wiki without files.
1055       */
1056      public function test_get_subwiki_files_no_files() {
1057          $result = mod_wiki_external::get_subwiki_files($this->wiki->id);
1058          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_files_returns(), $result);
1059          $this->assertCount(0, $result['files']);
1060          $this->assertCount(0, $result['warnings']);
1061      }
1062  
1063      /**
1064       * Test get_subwiki_files, check that a student can't get files from another group's subwiki when
1065       * using separate groups.
1066       */
1067      public function test_get_subwiki_files_separate_groups_student_see_other_group() {
1068          // Create testing data.
1069          $this->create_collaborative_wikis_with_groups();
1070  
1071          $this->setUser($this->student);
1072          $this->expectException(moodle_exception::class);
1073          mod_wiki_external::get_subwiki_files($this->wikisep->id, $this->group2->id);
1074      }
1075  
1076      /**
1077       * Test get_subwiki_files using a collaborative wiki without groups.
1078       */
1079      public function test_get_subwiki_files_collaborative_no_groups() {
1080          $this->setUser($this->student);
1081  
1082          // Add a file as subwiki attachment.
1083          $fs = get_file_storage();
1084          $file = array('component' => 'mod_wiki', 'filearea' => 'attachments',
1085                  'contextid' => $this->context->id, 'itemid' => $this->firstpage->subwikiid,
1086                  'filename' => 'image.jpg', 'filepath' => '/', 'timemodified' => time());
1087          $content = 'IMAGE';
1088          $fs->create_file_from_string($file, $content);
1089  
1090          $expectedfile = array(
1091              'filename' => $file['filename'],
1092              'filepath' => $file['filepath'],
1093              'mimetype' => 'image/jpeg',
1094              'isexternalfile' => false,
1095              'filesize' => strlen($content),
1096              'timemodified' => $file['timemodified'],
1097              'fileurl' => moodle_url::make_webservice_pluginfile_url($file['contextid'], $file['component'],
1098                              $file['filearea'], $file['itemid'], $file['filepath'], $file['filename']),
1099          );
1100  
1101          // Call the WS and check that it returns this file.
1102          $result = mod_wiki_external::get_subwiki_files($this->wiki->id);
1103          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_files_returns(), $result);
1104          $this->assertCount(1, $result['files']);
1105          $this->assertEquals($expectedfile, $result['files'][0]);
1106  
1107          // Now add another file to the same subwiki.
1108          $file['filename'] = 'Another image.jpg';
1109          $file['timemodified'] = time();
1110          $content = 'ANOTHER IMAGE';
1111          $fs->create_file_from_string($file, $content);
1112  
1113          $expectedfile['filename'] = $file['filename'];
1114          $expectedfile['timemodified'] = $file['timemodified'];
1115          $expectedfile['filesize'] = strlen($content);
1116          $expectedfile['fileurl'] = moodle_url::make_webservice_pluginfile_url($file['contextid'], $file['component'],
1117                              $file['filearea'], $file['itemid'], $file['filepath'], $file['filename']);
1118  
1119          // Call the WS and check that it returns both files file.
1120          $result = mod_wiki_external::get_subwiki_files($this->wiki->id);
1121          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_files_returns(), $result);
1122          $this->assertCount(2, $result['files']);
1123          // The new file is returned first because they're returned in alphabetical order.
1124          $this->assertEquals($expectedfile, $result['files'][0]);
1125      }
1126  
1127      /**
1128       * Test get_subwiki_files using an individual wiki with visible groups.
1129       */
1130      public function test_get_subwiki_files_visible_groups_individual() {
1131          // Create testing data.
1132          $this->create_individual_wikis_with_groups();
1133  
1134          $this->setUser($this->student);
1135  
1136          // Add a file as subwiki attachment in the student group 1 subwiki.
1137          $fs = get_file_storage();
1138          $contextwiki = context_module::instance($this->wikivisind->cmid);
1139          $file = array('component' => 'mod_wiki', 'filearea' => 'attachments',
1140                  'contextid' => $contextwiki->id, 'itemid' => $this->fpvisg1indstu->subwikiid,
1141                  'filename' => 'image.jpg', 'filepath' => '/', 'timemodified' => time());
1142          $content = 'IMAGE';
1143          $fs->create_file_from_string($file, $content);
1144  
1145          $expectedfile = array(
1146              'filename' => $file['filename'],
1147              'filepath' => $file['filepath'],
1148              'mimetype' => 'image/jpeg',
1149              'isexternalfile' => false,
1150              'filesize' => strlen($content),
1151              'timemodified' => $file['timemodified'],
1152              'fileurl' => moodle_url::make_webservice_pluginfile_url($file['contextid'], $file['component'],
1153                              $file['filearea'], $file['itemid'], $file['filepath'], $file['filename']),
1154          );
1155  
1156          // Call the WS and check that it returns this file.
1157          $result = mod_wiki_external::get_subwiki_files($this->wikivisind->id, $this->group1->id);
1158          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_files_returns(), $result);
1159          $this->assertCount(1, $result['files']);
1160          $this->assertEquals($expectedfile, $result['files'][0]);
1161  
1162          // Now check that a teacher can see it too.
1163          $this->setUser($this->teacher);
1164          $result = mod_wiki_external::get_subwiki_files($this->wikivisind->id, $this->group1->id, $this->student->id);
1165          $result = external_api::clean_returnvalue(mod_wiki_external::get_subwiki_files_returns(), $result);
1166          $this->assertCount(1, $result['files']);
1167          $this->assertEquals($expectedfile, $result['files'][0]);
1168      }
1169  
1170  
1171      /**
1172       * Test get_page_for_editing. We won't test all the possible cases because that's already
1173       * done in the tests for wiki_parser_proxy::get_section.
1174       */
1175      public function test_get_page_for_editing() {
1176  
1177          $this->create_individual_wikis_with_groups();
1178  
1179          // We add a <span> in the first title to verify the WS works sending HTML in section.
1180          $sectioncontent = '<h1><span>Title1</span></h1>Text inside section';
1181          $pagecontent = $sectioncontent.'<h1>Title2</h1>Text inside section';
1182          $newpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_page(
1183                                  $this->wiki, array('content' => $pagecontent));
1184  
1185          // Test user with full capabilities.
1186          $this->setUser($this->student);
1187  
1188          // Set expected result: Full Page content.
1189          $expected = array(
1190              'content' => $pagecontent,
1191              'contentformat' => 'html',
1192              'version' => '1'
1193          );
1194  
1195          $result = mod_wiki_external::get_page_for_editing($newpage->id);
1196          $result = external_api::clean_returnvalue(mod_wiki_external::get_page_for_editing_returns(), $result);
1197          $this->assertEquals($expected, $result['pagesection']);
1198  
1199          // Set expected result: Section Page content.
1200          $expected = array(
1201              'content' => $sectioncontent,
1202              'contentformat' => 'html',
1203              'version' => '1'
1204          );
1205  
1206          $result = mod_wiki_external::get_page_for_editing($newpage->id, '<span>Title1</span>');
1207          $result = external_api::clean_returnvalue(mod_wiki_external::get_page_for_editing_returns(), $result);
1208          $this->assertEquals($expected, $result['pagesection']);
1209      }
1210  
1211      /**
1212       * Test test_get_page_locking.
1213       */
1214      public function test_get_page_locking() {
1215  
1216          $this->create_individual_wikis_with_groups();
1217  
1218          $pagecontent = '<h1>Title1</h1>Text inside section<h1>Title2</h1>Text inside section';
1219          $newpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_page(
1220                                  $this->wiki, array('content' => $pagecontent));
1221  
1222          // Test user with full capabilities.
1223          $this->setUser($this->student);
1224  
1225          // Test Section locking.
1226          $expected = array(
1227              'version' => '1'
1228          );
1229  
1230          $result = mod_wiki_external::get_page_for_editing($newpage->id, 'Title1', true);
1231          $result = external_api::clean_returnvalue(mod_wiki_external::get_page_for_editing_returns(), $result);
1232          $this->assertEquals($expected, $result['pagesection']);
1233  
1234          // Test the section is locked.
1235          $this->setUser($this->student2);
1236          try {
1237              mod_wiki_external::get_page_for_editing($newpage->id, 'Title1', true);
1238              $this->fail('Exception expected due to not page locking.');
1239          } catch (moodle_exception $e) {
1240              $this->assertEquals('pageislocked', $e->errorcode);
1241          }
1242  
1243          // Test the page is locked.
1244          try {
1245              mod_wiki_external::get_page_for_editing($newpage->id, null, true);
1246              $this->fail('Exception expected due to not page locking.');
1247          } catch (moodle_exception $e) {
1248              $this->assertEquals('pageislocked', $e->errorcode);
1249          }
1250  
1251          // Test the other section is not locked.
1252          $result = mod_wiki_external::get_page_for_editing($newpage->id, 'Title2', true);
1253          $result = external_api::clean_returnvalue(mod_wiki_external::get_page_for_editing_returns(), $result);
1254          $this->assertEquals($expected, $result['pagesection']);
1255  
1256          // Back to the original user to test version change when editing.
1257          $this->setUser($this->student);
1258          $newsectioncontent = '<h1>Title2</h1>New test2';
1259          $result = mod_wiki_external::edit_page($newpage->id, $newsectioncontent, 'Title1');
1260  
1261          $expected = array(
1262              'version' => '2'
1263          );
1264          $result = mod_wiki_external::get_page_for_editing($newpage->id, 'Title1', true);
1265          $result = external_api::clean_returnvalue(mod_wiki_external::get_page_for_editing_returns(), $result);
1266          $this->assertEquals($expected, $result['pagesection']);
1267      }
1268  
1269      /**
1270       * Test new_page. We won't test all the possible cases because that's already
1271       * done in the tests for wiki_create_page.
1272       */
1273      public function test_new_page() {
1274  
1275          $this->create_individual_wikis_with_groups();
1276  
1277          $sectioncontent = '<h1>Title1</h1>Text inside section';
1278          $pagecontent = $sectioncontent.'<h1>Title2</h1>Text inside section';
1279          $pagetitle = 'Page Title';
1280  
1281          // Test user with full capabilities.
1282          $this->setUser($this->student);
1283  
1284          // Test on existing subwiki.
1285          $result = mod_wiki_external::new_page($pagetitle, $pagecontent, 'html', $this->fpsepg1indstu->subwikiid);
1286          $result = external_api::clean_returnvalue(mod_wiki_external::new_page_returns(), $result);
1287          $this->assertIsInt($result['pageid']);
1288  
1289          $version = wiki_get_current_version($result['pageid']);
1290          $this->assertEquals($pagecontent, $version->content);
1291          $this->assertEquals('html', $version->contentformat);
1292  
1293          $page = wiki_get_page($result['pageid']);
1294          $this->assertEquals($pagetitle, $page->title);
1295  
1296          // Test existing page creation.
1297          try {
1298              mod_wiki_external::new_page($pagetitle, $pagecontent, 'html', $this->fpsepg1indstu->subwikiid);
1299              $this->fail('Exception expected due to creation of an existing page.');
1300          } catch (moodle_exception $e) {
1301              $this->assertEquals('pageexists', $e->errorcode);
1302          }
1303  
1304          // Test on non existing subwiki. Add student to group2 to have a new subwiki to be created.
1305          $this->getDataGenerator()->create_group_member(array('userid' => $this->student->id, 'groupid' => $this->group2->id));
1306          $result = mod_wiki_external::new_page($pagetitle, $pagecontent, 'html', null, $this->wikisepind->id, $this->student->id,
1307              $this->group2->id);
1308          $result = external_api::clean_returnvalue(mod_wiki_external::new_page_returns(), $result);
1309          $this->assertIsInt($result['pageid']);
1310  
1311          $version = wiki_get_current_version($result['pageid']);
1312          $this->assertEquals($pagecontent, $version->content);
1313          $this->assertEquals('html', $version->contentformat);
1314  
1315          $page = wiki_get_page($result['pageid']);
1316          $this->assertEquals($pagetitle, $page->title);
1317  
1318          $subwiki = wiki_get_subwiki($page->subwikiid);
1319          $expected = new StdClass();
1320          $expected->id = $subwiki->id;
1321          $expected->wikiid = $this->wikisepind->id;
1322          $expected->groupid = $this->group2->id;
1323          $expected->userid = $this->student->id;
1324          $this->assertEquals($expected, $subwiki);
1325  
1326          // Check page creation for a user not in course.
1327          $this->studentnotincourse = self::getDataGenerator()->create_user();
1328          $this->anothercourse = $this->getDataGenerator()->create_course();
1329          $this->groupnotincourse = $this->getDataGenerator()->create_group(array('courseid' => $this->anothercourse->id));
1330  
1331          try {
1332              mod_wiki_external::new_page($pagetitle, $pagecontent, 'html', null, $this->wikisepind->id,
1333                  $this->studentnotincourse->id, $this->groupnotincourse->id);
1334              $this->fail('Exception expected due to creation of an invalid subwiki creation.');
1335          } catch (moodle_exception $e) {
1336              $this->assertEquals('cannoteditpage', $e->errorcode);
1337          }
1338  
1339      }
1340  
1341      /**
1342       * Test edit_page. We won't test all the possible cases because that's already
1343       * done in the tests for wiki_save_section / wiki_save_page.
1344       */
1345      public function test_edit_page() {
1346  
1347          $this->create_individual_wikis_with_groups();
1348  
1349          // Test user with full capabilities.
1350          $this->setUser($this->student);
1351  
1352          $newpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_page($this->wikisepind,
1353              array('group' => $this->group1->id, 'content' => 'Test'));
1354  
1355          // Test edit whole page.
1356          // We add <span> in the titles to verify the WS works sending HTML in section.
1357          $sectioncontent = '<h1><span>Title1</span></h1>Text inside section';
1358          $newpagecontent = $sectioncontent.'<h1><span>Title2</span></h1>Text inside section';
1359  
1360          $result = mod_wiki_external::edit_page($newpage->id, $newpagecontent);
1361          $result = external_api::clean_returnvalue(mod_wiki_external::edit_page_returns(), $result);
1362          $this->assertIsInt($result['pageid']);
1363  
1364          $version = wiki_get_current_version($result['pageid']);
1365          $this->assertEquals($newpagecontent, $version->content);
1366  
1367          // Test edit section.
1368          $newsectioncontent = '<h1><span>Title2</span></h1>New test2';
1369          $section = '<span>Title2</span>';
1370  
1371          $result = mod_wiki_external::edit_page($newpage->id, $newsectioncontent, $section);
1372          $result = external_api::clean_returnvalue(mod_wiki_external::edit_page_returns(), $result);
1373          $this->assertIsInt($result['pageid']);
1374  
1375          $expected = $sectioncontent . $newsectioncontent;
1376  
1377          $version = wiki_get_current_version($result['pageid']);
1378          $this->assertEquals($expected, $version->content);
1379  
1380          // Test locked section.
1381          $newsectioncontent = '<h1><span>Title2</span></h1>New test2';
1382          $section = '<span>Title2</span>';
1383  
1384          try {
1385              // Using user 1 to avoid other users to edit.
1386              wiki_set_lock($newpage->id, 1, $section, true);
1387              mod_wiki_external::edit_page($newpage->id, $newsectioncontent, $section);
1388              $this->fail('Exception expected due to locked section');
1389          } catch (moodle_exception $e) {
1390              $this->assertEquals('pageislocked', $e->errorcode);
1391          }
1392  
1393          // Test edit non existing section.
1394          $newsectioncontent = '<h1>Title3</h1>New test3';
1395          $section = 'Title3';
1396  
1397          try {
1398              mod_wiki_external::edit_page($newpage->id, $newsectioncontent, $section);
1399              $this->fail('Exception expected due to non existing section in the page.');
1400          } catch (moodle_exception $e) {
1401              $this->assertEquals('invalidsection', $e->errorcode);
1402          }
1403  
1404      }
1405  
1406  }