Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

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