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 39 and 401]

   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   * Unit tests for mod_wiki lib
  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  namespace mod_wiki;
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  global $CFG;
  31  require_once($CFG->dirroot . '/mod/wiki/lib.php');
  32  require_once($CFG->dirroot . '/mod/wiki/locallib.php');
  33  require_once($CFG->libdir . '/completionlib.php');
  34  
  35  /**
  36   * Unit tests for mod_wiki lib
  37   *
  38   * @package    mod_wiki
  39   * @category   external
  40   * @copyright  2015 Dani Palou <dani@moodle.com>
  41   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   * @since      Moodle 3.1
  43   */
  44  class lib_test extends \advanced_testcase {
  45  
  46      /**
  47       * Test wiki_view.
  48       *
  49       * @return void
  50       */
  51      public function test_wiki_view() {
  52          global $CFG;
  53  
  54          $CFG->enablecompletion = COMPLETION_ENABLED;
  55          $this->resetAfterTest();
  56  
  57          $this->setAdminUser();
  58          // Setup test data.
  59          $course = $this->getDataGenerator()->create_course(array('enablecompletion' => COMPLETION_ENABLED));
  60          $options = array('completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => COMPLETION_VIEW_REQUIRED);
  61          $wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id), $options);
  62          $context = \context_module::instance($wiki->cmid);
  63          $cm = get_coursemodule_from_instance('wiki', $wiki->id);
  64  
  65          // Trigger and capture the event.
  66          $sink = $this->redirectEvents();
  67  
  68          wiki_view($wiki, $course, $cm, $context);
  69  
  70          $events = $sink->get_events();
  71          // 2 additional events thanks to completion.
  72          $this->assertCount(3, $events);
  73          $event = array_shift($events);
  74  
  75          // Checking that the event contains the expected values.
  76          $this->assertInstanceOf('\mod_wiki\event\course_module_viewed', $event);
  77          $this->assertEquals($context, $event->get_context());
  78          $moodleurl = new \moodle_url('/mod/wiki/view.php', array('id' => $cm->id));
  79          $this->assertEquals($moodleurl, $event->get_url());
  80          $this->assertEventContextNotUsed($event);
  81          $this->assertNotEmpty($event->get_name());
  82  
  83          // Check completion status.
  84          $completion = new \completion_info($course);
  85          $completiondata = $completion->get_data($cm);
  86          $this->assertEquals(1, $completiondata->completionstate);
  87  
  88      }
  89  
  90      /**
  91       * Test wiki_page_view.
  92       *
  93       * @return void
  94       */
  95      public function test_wiki_page_view() {
  96          global $CFG;
  97  
  98          $CFG->enablecompletion = COMPLETION_ENABLED;
  99          $this->resetAfterTest();
 100  
 101          $this->setAdminUser();
 102          // Setup test data.
 103          $course = $this->getDataGenerator()->create_course(array('enablecompletion' => COMPLETION_ENABLED));
 104          $options = array('completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => COMPLETION_VIEW_REQUIRED);
 105          $wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id), $options);
 106          $context = \context_module::instance($wiki->cmid);
 107          $cm = get_coursemodule_from_instance('wiki', $wiki->id);
 108          $firstpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_first_page($wiki);
 109  
 110          // Trigger and capture the event.
 111          $sink = $this->redirectEvents();
 112  
 113          wiki_page_view($wiki, $firstpage, $course, $cm, $context);
 114  
 115          $events = $sink->get_events();
 116          // 2 additional events thanks to completion.
 117          $this->assertCount(3, $events);
 118          $event = array_shift($events);
 119  
 120          // Checking that the event contains the expected values.
 121          $this->assertInstanceOf('\mod_wiki\event\page_viewed', $event);
 122          $this->assertEquals($context, $event->get_context());
 123          $pageurl = new \moodle_url('/mod/wiki/view.php', array('pageid' => $firstpage->id));
 124          $this->assertEquals($pageurl, $event->get_url());
 125          $this->assertEventContextNotUsed($event);
 126          $this->assertNotEmpty($event->get_name());
 127  
 128          // Check completion status.
 129          $completion = new \completion_info($course);
 130          $completiondata = $completion->get_data($cm);
 131          $this->assertEquals(1, $completiondata->completionstate);
 132  
 133      }
 134  
 135      /**
 136       * Test wiki_user_can_edit without groups.
 137       *
 138       * @return void
 139       */
 140      public function test_wiki_user_can_edit() {
 141          global $DB;
 142  
 143          $this->resetAfterTest();
 144          $this->setAdminUser();
 145  
 146          // Setup test data.
 147          $course = $this->getDataGenerator()->create_course();
 148          $indwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id, 'wikimode' => 'individual'));
 149          $colwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id, 'wikimode' => 'collaborative'));
 150  
 151          // Create users.
 152          $student = self::getDataGenerator()->create_user();
 153          $teacher = self::getDataGenerator()->create_user();
 154  
 155          // Users enrolments.
 156          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 157          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 158          $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
 159          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
 160  
 161          // Simulate collaborative subwiki.
 162          $swcol = new \stdClass();
 163          $swcol->id = -1;
 164          $swcol->wikiid = $colwiki->id;
 165          $swcol->groupid = 0;
 166          $swcol->userid = 0;
 167  
 168          // Simulate individual subwikis (1 per user).
 169          $swindstudent = clone($swcol);
 170          $swindstudent->wikiid = $indwiki->id;
 171          $swindstudent->userid = $student->id;
 172  
 173          $swindteacher = clone($swindstudent);
 174          $swindteacher->userid = $teacher->id;
 175  
 176          $this->setUser($student);
 177  
 178          // Check that the student can edit the collaborative subwiki.
 179          $this->assertTrue(wiki_user_can_edit($swcol));
 180  
 181          // Check that the student can edit his individual subwiki.
 182          $this->assertTrue(wiki_user_can_edit($swindstudent));
 183  
 184          // Check that the student cannot edit teacher's individual subwiki.
 185          $this->assertFalse(wiki_user_can_edit($swindteacher));
 186  
 187          // Now test as a teacher.
 188          $this->setUser($teacher);
 189  
 190          // Check that the teacher can edit the collaborative subwiki.
 191          $this->assertTrue(wiki_user_can_edit($swcol));
 192  
 193          // Check that the teacher can edit his individual subwiki.
 194          $this->assertTrue(wiki_user_can_edit($swindteacher));
 195  
 196          // Check that the teacher can edit student's individual subwiki.
 197          $this->assertTrue(wiki_user_can_edit($swindstudent));
 198  
 199      }
 200  
 201      /**
 202       * Test wiki_user_can_edit using collaborative wikis with groups.
 203       *
 204       * @return void
 205       */
 206      public function test_wiki_user_can_edit_with_groups_collaborative() {
 207          global $DB;
 208  
 209          $this->resetAfterTest();
 210          $this->setAdminUser();
 211  
 212          // Setup test data.
 213          $course = $this->getDataGenerator()->create_course();
 214          $wikisepcol = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
 215                                                          'groupmode' => SEPARATEGROUPS, 'wikimode' => 'collaborative'));
 216          $wikiviscol = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
 217                                                          'groupmode' => VISIBLEGROUPS, 'wikimode' => 'collaborative'));
 218  
 219          // Create users.
 220          $student = self::getDataGenerator()->create_user();
 221          $student2 = self::getDataGenerator()->create_user();
 222          $teacher = self::getDataGenerator()->create_user();
 223  
 224          // Users enrolments.
 225          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 226          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 227          $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
 228          $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id, 'manual');
 229          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
 230  
 231          // Create groups.
 232          $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 233          $this->getDataGenerator()->create_group_member(array('userid' => $student->id, 'groupid' => $group1->id));
 234          $this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group1->id));
 235          $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 236          $this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group2->id));
 237  
 238          // Simulate all the possible subwikis.
 239          // Subwikis in collaborative wikis: 1 subwiki per group + 1 subwiki for all participants.
 240          $swsepcolg1 = new \stdClass();
 241          $swsepcolg1->id = -1;
 242          $swsepcolg1->wikiid = $wikisepcol->id;
 243          $swsepcolg1->groupid = $group1->id;
 244          $swsepcolg1->userid = 0;
 245  
 246          $swsepcolg2 = clone($swsepcolg1);
 247          $swsepcolg2->groupid = $group2->id;
 248  
 249          $swsepcolallparts = clone($swsepcolg1); // All participants.
 250          $swsepcolallparts->groupid = 0;
 251  
 252          $swviscolg1 = clone($swsepcolg1);
 253          $swviscolg1->wikiid = $wikiviscol->id;
 254  
 255          $swviscolg2 = clone($swviscolg1);
 256          $swviscolg2->groupid = $group2->id;
 257  
 258          $swviscolallparts = clone($swviscolg1); // All participants.
 259          $swviscolallparts->groupid = 0;
 260  
 261          $this->setUser($student);
 262  
 263          // Check that the student can edit his group's subwiki both in separate and visible groups.
 264          $this->assertTrue(wiki_user_can_edit($swsepcolg1));
 265          $this->assertTrue(wiki_user_can_edit($swviscolg1));
 266  
 267          // Check that the student cannot edit subwiki from group 2 both in separate and visible groups.
 268          $this->assertFalse(wiki_user_can_edit($swsepcolg2));
 269          $this->assertFalse(wiki_user_can_edit($swviscolg2));
 270  
 271          // Now test as student 2.
 272          $this->setUser($student2);
 273  
 274          // Check that the student 2 can edit subwikis from both groups both in separate and visible groups.
 275          $this->assertTrue(wiki_user_can_edit($swsepcolg1));
 276          $this->assertTrue(wiki_user_can_edit($swviscolg1));
 277          $this->assertTrue(wiki_user_can_edit($swsepcolg2));
 278          $this->assertTrue(wiki_user_can_edit($swviscolg2));
 279  
 280          // Check that the student 2 cannot edit subwikis from all participants.
 281          $this->assertFalse(wiki_user_can_edit($swsepcolallparts));
 282          $this->assertFalse(wiki_user_can_edit($swviscolallparts));
 283  
 284          // Now test it as a teacher.
 285          $this->setUser($teacher);
 286  
 287          // Check that teacher can edit all subwikis.
 288          $this->assertTrue(wiki_user_can_edit($swsepcolg1));
 289          $this->assertTrue(wiki_user_can_edit($swviscolg1));
 290          $this->assertTrue(wiki_user_can_edit($swsepcolg2));
 291          $this->assertTrue(wiki_user_can_edit($swviscolg2));
 292          $this->assertTrue(wiki_user_can_edit($swsepcolallparts));
 293          $this->assertTrue(wiki_user_can_edit($swviscolallparts));
 294      }
 295  
 296      /**
 297       * Test wiki_user_can_edit using individual wikis with groups.
 298       *
 299       * @return void
 300       */
 301      public function test_wiki_user_can_edit_with_groups_individual() {
 302          global $DB;
 303  
 304          $this->resetAfterTest();
 305          $this->setAdminUser();
 306  
 307          // Setup test data.
 308          $course = $this->getDataGenerator()->create_course();
 309          $wikisepind = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
 310                                                          'groupmode' => SEPARATEGROUPS, 'wikimode' => 'individual'));
 311          $wikivisind = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
 312                                                          'groupmode' => VISIBLEGROUPS, 'wikimode' => 'individual'));
 313  
 314          // Create users.
 315          $student = self::getDataGenerator()->create_user();
 316          $student2 = self::getDataGenerator()->create_user();
 317          $teacher = self::getDataGenerator()->create_user();
 318  
 319          // Users enrolments.
 320          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 321          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 322          $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
 323          $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id, 'manual');
 324          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
 325  
 326          // Create groups.
 327          $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 328          $this->getDataGenerator()->create_group_member(array('userid' => $student->id, 'groupid' => $group1->id));
 329          $this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group1->id));
 330          $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 331          $this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group2->id));
 332  
 333          // Simulate all the possible subwikis.
 334          // Subwikis in collaborative wikis: 1 subwiki per group + 1 subwiki for all participants.
 335          $swsepindg1s1 = new \stdClass();
 336          $swsepindg1s1->id = -1;
 337          $swsepindg1s1->wikiid = $wikisepind->id;
 338          $swsepindg1s1->groupid = $group1->id;
 339          $swsepindg1s1->userid = $student->id;
 340  
 341          $swsepindg1s2 = clone($swsepindg1s1);
 342          $swsepindg1s2->userid = $student2->id;
 343  
 344          $swsepindg2s2 = clone($swsepindg1s2);
 345          $swsepindg2s2->groupid = $group2->id;
 346  
 347          $swsepindteacher = clone($swsepindg1s1);
 348          $swsepindteacher->userid = $teacher->id;
 349          $swsepindteacher->groupid = 0;
 350  
 351          $swvisindg1s1 = clone($swsepindg1s1);
 352          $swvisindg1s1->wikiid = $wikivisind->id;
 353  
 354          $swvisindg1s2 = clone($swvisindg1s1);
 355          $swvisindg1s2->userid = $student2->id;
 356  
 357          $swvisindg2s2 = clone($swvisindg1s2);
 358          $swvisindg2s2->groupid = $group2->id;
 359  
 360          $swvisindteacher = clone($swvisindg1s1);
 361          $swvisindteacher->userid = $teacher->id;
 362          $swvisindteacher->groupid = 0;
 363  
 364          $this->setUser($student);
 365  
 366          // Check that the student can edit his subwiki both in separate and visible groups.
 367          $this->assertTrue(wiki_user_can_edit($swsepindg1s1));
 368          $this->assertTrue(wiki_user_can_edit($swvisindg1s1));
 369  
 370          // Check that the student cannot edit subwikis from another user even if he belongs to his group.
 371          $this->assertFalse(wiki_user_can_edit($swsepindg1s2));
 372          $this->assertFalse(wiki_user_can_edit($swvisindg1s2));
 373  
 374          // Now test as student 2.
 375          $this->setUser($student2);
 376  
 377          // Check that the student 2 can edit his subwikis from both groups both in separate and visible groups.
 378          $this->assertTrue(wiki_user_can_edit($swsepindg1s2));
 379          $this->assertTrue(wiki_user_can_edit($swvisindg1s2));
 380          $this->assertTrue(wiki_user_can_edit($swsepindg2s2));
 381          $this->assertTrue(wiki_user_can_edit($swvisindg2s2));
 382  
 383          // Now test it as a teacher.
 384          $this->setUser($teacher);
 385  
 386          // Check that teacher can edit all subwikis.
 387          $this->assertTrue(wiki_user_can_edit($swsepindg1s1));
 388          $this->assertTrue(wiki_user_can_edit($swsepindg1s2));
 389          $this->assertTrue(wiki_user_can_edit($swsepindg2s2));
 390          $this->assertTrue(wiki_user_can_edit($swsepindteacher));
 391          $this->assertTrue(wiki_user_can_edit($swvisindg1s1));
 392          $this->assertTrue(wiki_user_can_edit($swvisindg1s2));
 393          $this->assertTrue(wiki_user_can_edit($swvisindg2s2));
 394          $this->assertTrue(wiki_user_can_edit($swvisindteacher));
 395      }
 396  
 397      /**
 398       * Test wiki_get_visible_subwikis without groups.
 399       *
 400       * @return void
 401       */
 402      public function test_wiki_get_visible_subwikis_without_groups() {
 403          global $DB;
 404  
 405          $this->resetAfterTest();
 406          $this->setAdminUser();
 407  
 408          // Setup test data.
 409          $course = $this->getDataGenerator()->create_course();
 410          $indwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id, 'wikimode' => 'individual'));
 411          $colwiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id, 'wikimode' => 'collaborative'));
 412  
 413          // Create users.
 414          $student = self::getDataGenerator()->create_user();
 415          $teacher = self::getDataGenerator()->create_user();
 416  
 417          // Users enrolments.
 418          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 419          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 420          $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
 421          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
 422  
 423          $this->setUser($student);
 424  
 425          // Check that not passing a wiki returns empty array.
 426          $result = wiki_get_visible_subwikis(null);
 427          $this->assertEquals(array(), $result);
 428  
 429          // Check that the student can get the only subwiki from the collaborative wiki.
 430          $expectedsubwikis = array();
 431          $expectedsubwiki = new \stdClass();
 432          $expectedsubwiki->id = -1; // We haven't created any page so the subwiki hasn't been created.
 433          $expectedsubwiki->wikiid = $colwiki->id;
 434          $expectedsubwiki->groupid = 0;
 435          $expectedsubwiki->userid = 0;
 436          $expectedsubwikis[] = $expectedsubwiki;
 437  
 438          $result = wiki_get_visible_subwikis($colwiki);
 439          $this->assertEquals($expectedsubwikis, $result);
 440  
 441          // Create a page now so the subwiki is created.
 442          $colfirstpage = $this->getDataGenerator()->get_plugin_generator('mod_wiki')->create_first_page($colwiki);
 443  
 444          // Call the function again, now we expect to have a subwiki ID.
 445          $expectedsubwikis[0]->id = $colfirstpage->subwikiid;
 446          $result = wiki_get_visible_subwikis($colwiki);
 447          $this->assertEquals($expectedsubwikis, $result);
 448  
 449          // Check that the teacher can see it too.
 450          $this->setUser($teacher);
 451          $result = wiki_get_visible_subwikis($colwiki);
 452          $this->assertEquals($expectedsubwikis, $result);
 453  
 454          // Check that the student can only see his subwiki in the individual wiki.
 455          $this->setUser($student);
 456          $expectedsubwikis[0]->id = -1;
 457          $expectedsubwikis[0]->wikiid = $indwiki->id;
 458          $expectedsubwikis[0]->userid = $student->id;
 459          $result = wiki_get_visible_subwikis($indwiki);
 460          $this->assertEquals($expectedsubwikis, $result);
 461  
 462          // Check that the teacher can see his subwiki and the student subwiki in the individual wiki.
 463          $this->setUser($teacher);
 464          $teachersubwiki = new \stdClass();
 465          $teachersubwiki->id = -1;
 466          $teachersubwiki->wikiid = $indwiki->id;
 467          $teachersubwiki->groupid = 0;
 468          $teachersubwiki->userid = $teacher->id;
 469          $expectedsubwikis[] = $teachersubwiki;
 470  
 471          $result = wiki_get_visible_subwikis($indwiki);
 472          $this->assertEqualsCanonicalizing($expectedsubwikis, $result); // Compare without order.
 473      }
 474  
 475      /**
 476       * Test wiki_get_visible_subwikis using collaborative wikis with groups.
 477       *
 478       * @return void
 479       */
 480      public function test_wiki_get_visible_subwikis_with_groups_collaborative() {
 481          global $DB;
 482  
 483          $this->resetAfterTest();
 484          $this->setAdminUser();
 485  
 486          // Setup test data.
 487          $course = $this->getDataGenerator()->create_course();
 488          $wikisepcol = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
 489                                                          'groupmode' => SEPARATEGROUPS, 'wikimode' => 'collaborative'));
 490          $wikiviscol = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
 491                                                          'groupmode' => VISIBLEGROUPS, 'wikimode' => 'collaborative'));
 492  
 493          // Create users.
 494          $student = self::getDataGenerator()->create_user();
 495          $student2 = self::getDataGenerator()->create_user();
 496          $student3 = self::getDataGenerator()->create_user();
 497          $teacher = self::getDataGenerator()->create_user();
 498  
 499          // Users enrolments.
 500          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 501          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 502          $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
 503          $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id, 'manual');
 504          $this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id, 'manual');
 505          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
 506  
 507          // Create groups.
 508          $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 509          $this->getDataGenerator()->create_group_member(array('userid' => $student->id, 'groupid' => $group1->id));
 510          $this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group1->id));
 511          $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 512          $this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group2->id));
 513          $this->getDataGenerator()->create_group_member(array('userid' => $student3->id, 'groupid' => $group2->id));
 514  
 515          $this->setUser($student);
 516  
 517          // Create all the possible subwikis. We haven't created any page so ids will be -1.
 518          // Subwikis in collaborative wikis: 1 subwiki per group + 1 subwiki for all participants.
 519          $swsepcolg1 = new \stdClass();
 520          $swsepcolg1->id = -1;
 521          $swsepcolg1->wikiid = $wikisepcol->id;
 522          $swsepcolg1->groupid = $group1->id;
 523          $swsepcolg1->userid = 0;
 524  
 525          $swsepcolg2 = clone($swsepcolg1);
 526          $swsepcolg2->groupid = $group2->id;
 527  
 528          $swsepcolallparts = clone($swsepcolg1); // All participants.
 529          $swsepcolallparts->groupid = 0;
 530  
 531          $swviscolg1 = clone($swsepcolg1);
 532          $swviscolg1->wikiid = $wikiviscol->id;
 533  
 534          $swviscolg2 = clone($swviscolg1);
 535          $swviscolg2->groupid = $group2->id;
 536  
 537          $swviscolallparts = clone($swviscolg1); // All participants.
 538          $swviscolallparts->groupid = 0;
 539  
 540          // Check that the student can get only the subwiki from his group in collaborative wiki with separate groups.
 541          $expectedsubwikis = array($swsepcolg1);
 542          $result = wiki_get_visible_subwikis($wikisepcol);
 543          $this->assertEquals($expectedsubwikis, $result);
 544  
 545          // Check that he can get subwikis from both groups in collaborative wiki with visible groups, and also all participants.
 546          $expectedsubwikis = array($swviscolallparts, $swviscolg1, $swviscolg2);
 547          $result = wiki_get_visible_subwikis($wikiviscol);
 548          $this->assertEqualsCanonicalizing($expectedsubwikis, $result);
 549  
 550          // Now test it as a teacher. No need to check visible groups wikis because the result is the same as student.
 551          $this->setUser($teacher);
 552  
 553          // Check that he can get the subwikis from all the groups in collaborative wiki with separate groups.
 554          $expectedsubwikis = array($swsepcolg1, $swsepcolg2, $swsepcolallparts);
 555          $result = wiki_get_visible_subwikis($wikisepcol);
 556          $this->assertEqualsCanonicalizing($expectedsubwikis, $result);
 557      }
 558  
 559      /**
 560       * Test wiki_get_visible_subwikis using individual wikis with groups.
 561       *
 562       * @return void
 563       */
 564      public function test_wiki_get_visible_subwikis_with_groups_individual() {
 565          global $DB;
 566  
 567          $this->resetAfterTest();
 568          $this->setAdminUser();
 569  
 570          // Setup test data.
 571          $course = $this->getDataGenerator()->create_course();
 572          $wikisepind = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
 573                                                          'groupmode' => SEPARATEGROUPS, 'wikimode' => 'individual'));
 574          $wikivisind = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id,
 575                                                          'groupmode' => VISIBLEGROUPS, 'wikimode' => 'individual'));
 576  
 577          // Create users.
 578          $student = self::getDataGenerator()->create_user();
 579          $student2 = self::getDataGenerator()->create_user();
 580          $student3 = self::getDataGenerator()->create_user();
 581          $teacher = self::getDataGenerator()->create_user();
 582  
 583          // Users enrolments.
 584          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 585          $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
 586          $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual');
 587          $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id, 'manual');
 588          $this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id, 'manual');
 589          $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id, 'manual');
 590  
 591          // Create groups.
 592          $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 593          $this->getDataGenerator()->create_group_member(array('userid' => $student->id, 'groupid' => $group1->id));
 594          $this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group1->id));
 595          $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
 596          $this->getDataGenerator()->create_group_member(array('userid' => $student2->id, 'groupid' => $group2->id));
 597          $this->getDataGenerator()->create_group_member(array('userid' => $student3->id, 'groupid' => $group2->id));
 598  
 599          $this->setUser($student);
 600  
 601          // Create all the possible subwikis to be returned. We haven't created any page so ids will be -1.
 602          // Subwikis in individual wikis: 1 subwiki per user and group. If user doesn't belong to any group then groupid is 0.
 603          $swsepindg1s1 = new \stdClass();
 604          $swsepindg1s1->id = -1;
 605          $swsepindg1s1->wikiid = $wikisepind->id;
 606          $swsepindg1s1->groupid = $group1->id;
 607          $swsepindg1s1->userid = $student->id;
 608  
 609          $swsepindg1s2 = clone($swsepindg1s1);
 610          $swsepindg1s2->userid = $student2->id;
 611  
 612          $swsepindg2s2 = clone($swsepindg1s2);
 613          $swsepindg2s2->groupid = $group2->id;
 614  
 615          $swsepindg2s3 = clone($swsepindg1s1);
 616          $swsepindg2s3->userid = $student3->id;
 617          $swsepindg2s3->groupid = $group2->id;
 618  
 619          $swsepindteacher = clone($swsepindg1s1);
 620          $swsepindteacher->userid = $teacher->id;
 621          $swsepindteacher->groupid = 0;
 622  
 623          $swvisindg1s1 = clone($swsepindg1s1);
 624          $swvisindg1s1->wikiid = $wikivisind->id;
 625  
 626          $swvisindg1s2 = clone($swvisindg1s1);
 627          $swvisindg1s2->userid = $student2->id;
 628  
 629          $swvisindg2s2 = clone($swvisindg1s2);
 630          $swvisindg2s2->groupid = $group2->id;
 631  
 632          $swvisindg2s3 = clone($swvisindg1s1);
 633          $swvisindg2s3->userid = $student3->id;
 634          $swvisindg2s3->groupid = $group2->id;
 635  
 636          $swvisindteacher = clone($swvisindg1s1);
 637          $swvisindteacher->userid = $teacher->id;
 638          $swvisindteacher->groupid = 0;
 639  
 640          // Check that student can get the subwikis from his group in individual wiki with separate groups.
 641          $expectedsubwikis = array($swsepindg1s1, $swsepindg1s2);
 642          $result = wiki_get_visible_subwikis($wikisepind);
 643          $this->assertEqualsCanonicalizing($expectedsubwikis, $result);
 644  
 645          // Check that he can get subwikis from all users and groups in individual wiki with visible groups.
 646          $expectedsubwikis = array($swvisindg1s1, $swvisindg1s2, $swvisindg2s2, $swvisindg2s3, $swvisindteacher);
 647          $result = wiki_get_visible_subwikis($wikivisind);
 648          $this->assertEqualsCanonicalizing($expectedsubwikis, $result);
 649  
 650          // Now test it as a teacher. No need to check visible groups wikis because the result is the same as student.
 651          $this->setUser($teacher);
 652  
 653          // Check that teacher can get the subwikis from all the groups in individual wiki with separate groups.
 654          $expectedsubwikis = array($swsepindg1s1, $swsepindg1s2, $swsepindg2s2, $swsepindg2s3, $swsepindteacher);
 655          $result = wiki_get_visible_subwikis($wikisepind);
 656          $this->assertEqualsCanonicalizing($expectedsubwikis, $result);
 657      }
 658  
 659      public function test_mod_wiki_get_tagged_pages() {
 660          global $DB;
 661  
 662          $this->resetAfterTest();
 663          $this->setAdminUser();
 664  
 665          // Setup test data.
 666          $wikigenerator = $this->getDataGenerator()->get_plugin_generator('mod_wiki');
 667          $course3 = $this->getDataGenerator()->create_course();
 668          $course2 = $this->getDataGenerator()->create_course();
 669          $course1 = $this->getDataGenerator()->create_course();
 670          $wiki1 = $this->getDataGenerator()->create_module('wiki', array('course' => $course1->id));
 671          $wiki2 = $this->getDataGenerator()->create_module('wiki', array('course' => $course2->id));
 672          $wiki3 = $this->getDataGenerator()->create_module('wiki', array('course' => $course3->id));
 673          $page11 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats', 'Dogs')));
 674          $page12 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats', 'mice')));
 675          $page13 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats')));
 676          $page14 = $wikigenerator->create_content($wiki1);
 677          $page15 = $wikigenerator->create_content($wiki1, array('tags' => array('Cats')));
 678          $page21 = $wikigenerator->create_content($wiki2, array('tags' => array('Cats')));
 679          $page22 = $wikigenerator->create_content($wiki2, array('tags' => array('Cats', 'Dogs')));
 680          $page23 = $wikigenerator->create_content($wiki2, array('tags' => array('mice', 'Cats')));
 681          $page31 = $wikigenerator->create_content($wiki3, array('tags' => array('mice', 'Cats')));
 682  
 683          $tag = \core_tag_tag::get_by_name(0, 'Cats');
 684  
 685          // Admin can see everything.
 686          $res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
 687                  /*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$page = */0);
 688          $this->assertMatchesRegularExpression('/'.$page11->title.'/', $res->content);
 689          $this->assertMatchesRegularExpression('/'.$page12->title.'/', $res->content);
 690          $this->assertMatchesRegularExpression('/'.$page13->title.'/', $res->content);
 691          $this->assertDoesNotMatchRegularExpression('/'.$page14->title.'/', $res->content);
 692          $this->assertMatchesRegularExpression('/'.$page15->title.'/', $res->content);
 693          $this->assertMatchesRegularExpression('/'.$page21->title.'/', $res->content);
 694          $this->assertDoesNotMatchRegularExpression('/'.$page22->title.'/', $res->content);
 695          $this->assertDoesNotMatchRegularExpression('/'.$page23->title.'/', $res->content);
 696          $this->assertDoesNotMatchRegularExpression('/'.$page31->title.'/', $res->content);
 697          $this->assertEmpty($res->prevpageurl);
 698          $this->assertNotEmpty($res->nextpageurl);
 699          $res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
 700                  /*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$page = */1);
 701          $this->assertDoesNotMatchRegularExpression('/'.$page11->title.'/', $res->content);
 702          $this->assertDoesNotMatchRegularExpression('/'.$page12->title.'/', $res->content);
 703          $this->assertDoesNotMatchRegularExpression('/'.$page13->title.'/', $res->content);
 704          $this->assertDoesNotMatchRegularExpression('/'.$page14->title.'/', $res->content);
 705          $this->assertDoesNotMatchRegularExpression('/'.$page15->title.'/', $res->content);
 706          $this->assertDoesNotMatchRegularExpression('/'.$page21->title.'/', $res->content);
 707          $this->assertMatchesRegularExpression('/'.$page22->title.'/', $res->content);
 708          $this->assertMatchesRegularExpression('/'.$page23->title.'/', $res->content);
 709          $this->assertMatchesRegularExpression('/'.$page31->title.'/', $res->content);
 710          $this->assertNotEmpty($res->prevpageurl);
 711          $this->assertEmpty($res->nextpageurl);
 712  
 713          // Create and enrol a user.
 714          $student = self::getDataGenerator()->create_user();
 715          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
 716          $this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id, 'manual');
 717          $this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentrole->id, 'manual');
 718          $this->setUser($student);
 719          \core_tag_index_builder::reset_caches();
 720  
 721          // User can not see pages in course 3 because he is not enrolled.
 722          $res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
 723                  /*$fromctx = */0, /*$ctx = */0, /*$rec = */1, /*$page = */1);
 724          $this->assertMatchesRegularExpression('/'.$page22->title.'/', $res->content);
 725          $this->assertMatchesRegularExpression('/'.$page23->title.'/', $res->content);
 726          $this->assertDoesNotMatchRegularExpression('/'.$page31->title.'/', $res->content);
 727  
 728          // User can search wiki pages inside a course.
 729          $coursecontext = \context_course::instance($course1->id);
 730          $res = mod_wiki_get_tagged_pages($tag, /*$exclusivemode = */false,
 731                  /*$fromctx = */0, /*$ctx = */$coursecontext->id, /*$rec = */1, /*$page = */0);
 732          $this->assertMatchesRegularExpression('/'.$page11->title.'/', $res->content);
 733          $this->assertMatchesRegularExpression('/'.$page12->title.'/', $res->content);
 734          $this->assertMatchesRegularExpression('/'.$page13->title.'/', $res->content);
 735          $this->assertDoesNotMatchRegularExpression('/'.$page14->title.'/', $res->content);
 736          $this->assertMatchesRegularExpression('/'.$page15->title.'/', $res->content);
 737          $this->assertDoesNotMatchRegularExpression('/'.$page21->title.'/', $res->content);
 738          $this->assertDoesNotMatchRegularExpression('/'.$page22->title.'/', $res->content);
 739          $this->assertDoesNotMatchRegularExpression('/'.$page23->title.'/', $res->content);
 740          $this->assertEmpty($res->nextpageurl);
 741      }
 742  
 743      public function test_wiki_core_calendar_provide_event_action() {
 744          $this->resetAfterTest();
 745          $this->setAdminUser();
 746  
 747          // Create the activity.
 748          $course = $this->getDataGenerator()->create_course();
 749          $wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id));
 750  
 751          // Create a calendar event.
 752          $event = $this->create_action_event($course->id, $wiki->id,
 753              \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
 754  
 755          // Create an action factory.
 756          $factory = new \core_calendar\action_factory();
 757  
 758          // Decorate action event.
 759          $actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory);
 760  
 761          // Confirm the event was decorated.
 762          $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
 763          $this->assertEquals(get_string('view'), $actionevent->get_name());
 764          $this->assertInstanceOf('moodle_url', $actionevent->get_url());
 765          $this->assertEquals(1, $actionevent->get_item_count());
 766          $this->assertTrue($actionevent->is_actionable());
 767      }
 768  
 769      public function test_wiki_core_calendar_provide_event_action_for_non_user() {
 770          global $CFG;
 771  
 772          $this->resetAfterTest();
 773          $this->setAdminUser();
 774  
 775          // Create the activity.
 776          $course = $this->getDataGenerator()->create_course();
 777          $wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id));
 778  
 779          // Create a calendar event.
 780          $event = $this->create_action_event($course->id, $wiki->id,
 781                  \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
 782  
 783          // Now, log out.
 784          $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
 785          $this->setUser();
 786  
 787          // Create an action factory.
 788          $factory = new \core_calendar\action_factory();
 789  
 790          // Decorate action event for the student.
 791          $actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory);
 792  
 793          // Confirm the event is not shown at all.
 794          $this->assertNull($actionevent);
 795      }
 796  
 797      public function test_wiki_core_calendar_provide_event_action_for_user() {
 798          global $CFG;
 799  
 800          $this->resetAfterTest();
 801          $this->setAdminUser();
 802  
 803          // Create the activity.
 804          $course = $this->getDataGenerator()->create_course();
 805          $wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id));
 806          $student = $this->getDataGenerator()->create_and_enrol($course, 'student');
 807  
 808          // Create a calendar event.
 809          $event = $this->create_action_event($course->id, $wiki->id,
 810                  \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
 811  
 812          // Now log out.
 813          $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities.
 814          $this->setUser();
 815  
 816          // Create an action factory.
 817          $factory = new \core_calendar\action_factory();
 818  
 819          // Decorate action event for the student.
 820          $actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory, $student->id);
 821  
 822          // Confirm the event was decorated.
 823          $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent);
 824          $this->assertEquals(get_string('view'), $actionevent->get_name());
 825          $this->assertInstanceOf('moodle_url', $actionevent->get_url());
 826          $this->assertEquals(1, $actionevent->get_item_count());
 827          $this->assertTrue($actionevent->is_actionable());
 828      }
 829  
 830      public function test_wiki_core_calendar_provide_event_action_already_completed() {
 831          global $CFG;
 832  
 833          $this->resetAfterTest();
 834          $this->setAdminUser();
 835  
 836          $CFG->enablecompletion = 1;
 837  
 838          // Create the activity.
 839          $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
 840          $wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id),
 841              array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
 842  
 843          // Get some additional data.
 844          $cm = get_coursemodule_from_instance('wiki', $wiki->id);
 845  
 846          // Create a calendar event.
 847          $event = $this->create_action_event($course->id, $wiki->id,
 848              \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
 849  
 850          // Mark the activity as completed.
 851          $completion = new \completion_info($course);
 852          $completion->set_module_viewed($cm);
 853  
 854          // Create an action factory.
 855          $factory = new \core_calendar\action_factory();
 856  
 857          // Decorate action event.
 858          $actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory);
 859  
 860          // Ensure result was null.
 861          $this->assertNull($actionevent);
 862      }
 863  
 864      public function test_wiki_core_calendar_provide_event_action_already_completed_for_user() {
 865          global $CFG;
 866  
 867          $this->resetAfterTest();
 868          $this->setAdminUser();
 869  
 870          $CFG->enablecompletion = 1;
 871  
 872          // Create the activity.
 873          $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1));
 874          $wiki = $this->getDataGenerator()->create_module('wiki', array('course' => $course->id),
 875                  array('completion' => 2, 'completionview' => 1, 'completionexpected' => time() + DAYSECS));
 876  
 877          // Create 2 students and enrol them into the course.
 878          $student1 = $this->getDataGenerator()->create_and_enrol($course, 'student');
 879          $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student');
 880  
 881          // Get some additional data.
 882          $cm = get_coursemodule_from_instance('wiki', $wiki->id);
 883  
 884          // Create a calendar event.
 885          $event = $this->create_action_event($course->id, $wiki->id,
 886                  \core_completion\api::COMPLETION_EVENT_TYPE_DATE_COMPLETION_EXPECTED);
 887  
 888          // Mark the activity as completed for the $student1.
 889          $completion = new \completion_info($course);
 890          $completion->set_module_viewed($cm, $student1->id);
 891  
 892          // Now log in as $student2.
 893          $this->setUser($student2);
 894  
 895          // Create an action factory.
 896          $factory = new \core_calendar\action_factory();
 897  
 898          // Decorate action event for $student1.
 899          $actionevent = mod_wiki_core_calendar_provide_event_action($event, $factory, $student1->id);
 900  
 901          // Ensure result was null.
 902          $this->assertNull($actionevent);
 903      }
 904  
 905      /**
 906       * Creates an action event.
 907       *
 908       * @param int $courseid The course id.
 909       * @param int $instanceid The instance id.
 910       * @param string $eventtype The event type.
 911       * @return bool|calendar_event
 912       */
 913      private function create_action_event($courseid, $instanceid, $eventtype) {
 914          $event = new \stdClass();
 915          $event->name = 'Calendar event';
 916          $event->modulename  = 'wiki';
 917          $event->courseid = $courseid;
 918          $event->instance = $instanceid;
 919          $event->type = CALENDAR_EVENT_TYPE_ACTION;
 920          $event->eventtype = $eventtype;
 921          $event->timestart = time();
 922  
 923          return \calendar_event::create($event);
 924      }
 925  }