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.
   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   * Data provider tests.
  19   *
  20   * @package    mod_wiki
  21   * @category   test
  22   * @copyright  2018 Marina Glancy
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  namespace mod_wiki\privacy;
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  global $CFG;
  29  
  30  use core_privacy\tests\provider_testcase;
  31  use mod_wiki\privacy\provider;
  32  use core_privacy\local\request\approved_contextlist;
  33  use core_privacy\local\request\approved_userlist;
  34  use core_privacy\local\request\writer;
  35  
  36  require_once($CFG->dirroot.'/mod/wiki/locallib.php');
  37  
  38  /**
  39   * Data provider testcase class.
  40   *
  41   * @package    mod_wiki
  42   * @category   test
  43   * @copyright  2018 Marina Glancy
  44   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  45   */
  46  class provider_test extends provider_testcase {
  47  
  48      /** @var array */
  49      protected $users = [];
  50      /** @var array */
  51      protected $pages = [];
  52      /** @var array */
  53      protected $contexts = [];
  54      /** @var array */
  55      protected $subwikis = [];
  56      /** @var array */
  57      protected $pagepaths = [];
  58  
  59      /**
  60       * Set up for each test.
  61       *
  62       * There are three users and four wikis.
  63       * 1 : collaborative wiki, has context $this->contexts[1] and has a single subwiki $this->subwikis[1]
  64       * 2 : individual wiki, has context $this->contexts[2] and three subwikis (one for each user):
  65       *        $this->subwikis[21], $this->subwikis[22], $this->subwikis[23],
  66       *        the subwiki for the third user is empty
  67       * 3 : collaborative wiki, has context $this->contexts[3] and has a single subwiki $this->subwikis[3]
  68       * 4 : collaborative wiki, has context $this->contexts[4], this wiki is empty
  69       *
  70       * Each subwiki (except for "23") has pages, for example, in $this->subwiki[1] there are pages
  71       *   $this->pages[1][1], $this->pages[1][2] and $this->pages[1][3]
  72       *   In the export data they have paths:
  73       *   $this->pagepaths[1][1], $this->pagepaths[1][2], $this->pagepaths[1][3]
  74       */
  75      public function setUp(): void {
  76          global $DB;
  77          $this->resetAfterTest();
  78  
  79          $dg = $this->getDataGenerator();
  80          $course = $dg->create_course();
  81  
  82          $this->users[1] = $dg->create_user();
  83          $this->users[2] = $dg->create_user();
  84          $this->users[3] = $dg->create_user();
  85          $this->users[4] = $dg->create_user();
  86  
  87          $studentrole = $DB->get_record('role', array('shortname' => 'student'));
  88          $this->getDataGenerator()->enrol_user($this->users[1]->id, $course->id, $studentrole->id, 'manual');
  89          $this->getDataGenerator()->enrol_user($this->users[2]->id, $course->id, $studentrole->id, 'manual');
  90          $this->getDataGenerator()->enrol_user($this->users[3]->id, $course->id, $studentrole->id, 'manual');
  91          $this->getDataGenerator()->enrol_user($this->users[4]->id, $course->id, $studentrole->id, 'manual');
  92  
  93          $cm1 = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id]);
  94          $cm2 = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id, 'wikimode' => 'individual']);
  95          $cm3 = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id]);
  96          $cm4 = $this->getDataGenerator()->create_module('wiki', ['course' => $course->id]); // Empty.
  97  
  98          // User1.
  99          $this->setUser($this->users[1]);
 100  
 101          // Create and modify pages in collaborative wiki.
 102          $this->pages[1][1] = $this->create_first_page($cm1);
 103          $this->pages[1][2] = $this->create_page($cm1, ['content' => 'initial content']);
 104          $this->update_page($cm1, $this->pages[1][2], ['content' => 'update1 <img src="@@PLUGINFILE@@/Dog%20jump.jpg">']);
 105          $this->attach_file($cm1, "Dog jump.jpg", 'jpg:Doggy');
 106          $this->update_page($cm1, $this->pages[1][2], ['content' => 'update2']);
 107  
 108          // Create pages in individual wiki, add files that are not used in text.
 109          $this->pages[21][1] = $this->create_first_page($cm2);
 110          $this->pages[21][2] = $this->create_page($cm2);
 111          $this->attach_file($cm2, "mycat.jpg", 'jpg:Cat');
 112  
 113          // User2.
 114          $this->setUser($this->users[2]);
 115  
 116          // Modify existing pages in the first collaborative wiki.
 117          $this->update_page($cm1, $this->pages[1][2], ['content' => 'update3 <img src="@@PLUGINFILE@@/Hamster.jpg">']);
 118          $this->attach_file($cm1, "Hamster.jpg", 'jpg:Hamster');
 119  
 120          // Create pages in individual wiki.
 121          $this->pages[22][1] = $this->create_first_page($cm2);
 122          $this->pages[22][2] = $this->create_page($cm2);
 123  
 124          // Create pages in the third wiki.
 125          $this->pages[3][1] = $this->create_first_page($cm3);
 126  
 127          // User3 (testing locks and empty subwiki).
 128          $this->setUser($this->users[3]);
 129  
 130          // Create a subwiki in the individual wiki without any pages.
 131          $subwiki23 = $dg->get_plugin_generator('mod_wiki')->get_subwiki($cm2);
 132  
 133          // Create a page in the first wiki and then lock it.
 134          $this->pages[1][3] = $this->create_page($cm1);
 135          wiki_set_lock($this->pages[1][3]->id, $this->users[3]->id, null, true);
 136  
 137          // Lock a page in the third wiki without having any revisions on it.
 138          wiki_set_lock($this->pages[3][1]->id, $this->users[3]->id, null, true);
 139  
 140          // User 4 - added to the first wiki, so all users are not part of all edited contexts.
 141          $this->setUser($this->users[4]);
 142          $this->pages[1][4] = $this->create_page($cm1);
 143  
 144          $this->subwikis = [
 145              1 => $this->pages[1][1]->subwikiid,
 146              21 => $this->pages[21][1]->subwikiid,
 147              22 => $this->pages[22][1]->subwikiid,
 148              23 => $subwiki23,
 149              3 => $this->pages[3][1]->subwikiid,
 150          ];
 151  
 152          $this->contexts = [
 153              1 => \context_module::instance($cm1->cmid),
 154              2 => \context_module::instance($cm2->cmid),
 155              3 => \context_module::instance($cm3->cmid),
 156              4 => \context_module::instance($cm4->cmid),
 157          ];
 158  
 159          $this->pagepaths = [
 160              1 => [
 161                  1 => $this->pages[1][1]->id . ' ' . $this->pages[1][1]->title,
 162                  2 => $this->pages[1][2]->id . ' ' . $this->pages[1][2]->title,
 163                  3 => $this->pages[1][3]->id . ' ' . $this->pages[1][3]->title,
 164                  4 => $this->pages[1][4]->id . ' ' . $this->pages[1][4]->title,
 165              ],
 166              21 => [
 167                  1 => $this->pages[21][1]->id . ' ' . $this->pages[21][1]->title,
 168                  2 => $this->pages[21][2]->id . ' ' . $this->pages[21][2]->title,
 169              ],
 170              22 => [
 171                  1 => $this->pages[22][1]->id . ' ' . $this->pages[22][1]->title,
 172                  2 => $this->pages[22][2]->id . ' ' . $this->pages[22][2]->title,
 173              ],
 174              3 => [
 175                  1 => $this->pages[3][1]->id . ' ' . $this->pages[3][1]->title,
 176              ]
 177          ];
 178      }
 179  
 180      /**
 181       * Generate first page in wiki as current user
 182       *
 183       * @param stdClass $wiki
 184       * @param array $record
 185       * @return mixed
 186       */
 187      protected function create_first_page($wiki, $record = []) {
 188          $dg = $this->getDataGenerator();
 189          $wg = $dg->get_plugin_generator('mod_wiki');
 190          return $wg->create_first_page($wiki, $record);
 191      }
 192  
 193      /**
 194       * Generate a page in wiki as current user
 195       *
 196       * @param stdClass $wiki
 197       * @param array $record
 198       * @return mixed
 199       */
 200      protected function create_page($wiki, $record = []) {
 201          $dg = $this->getDataGenerator();
 202          $wg = $dg->get_plugin_generator('mod_wiki');
 203          return $wg->create_page($wiki, $record);
 204      }
 205  
 206      /**
 207       * Update an existing page in wiki as current user
 208       *
 209       * @param stdClass $wiki
 210       * @param stdClass $page
 211       * @param array $record
 212       * @return mixed
 213       */
 214      protected function update_page($wiki, $page, $record = []) {
 215          $dg = $this->getDataGenerator();
 216          $wg = $dg->get_plugin_generator('mod_wiki');
 217          return $wg->create_page($wiki, ['title' => $page->title] + $record);
 218      }
 219  
 220      /**
 221       * Attach file to a wiki as a current user
 222       *
 223       * @param stdClass $wiki
 224       * @param string $filename
 225       * @param string $filecontent
 226       * @return stored_file
 227       */
 228      protected function attach_file($wiki, $filename, $filecontent) {
 229          $dg = $this->getDataGenerator();
 230          $wg = $dg->get_plugin_generator('mod_wiki');
 231          $subwikiid = $wg->get_subwiki($wiki);
 232  
 233          $fs = get_file_storage();
 234          return $fs->create_file_from_string([
 235              'contextid' => \context_module::instance($wiki->cmid)->id,
 236              'component' => 'mod_wiki',
 237              'filearea' => 'attachments',
 238              'itemid' => $subwikiid,
 239              'filepath' => '/',
 240              'filename' => $filename,
 241          ], $filecontent);
 242      }
 243  
 244      /**
 245       * Test getting the contexts for a user.
 246       */
 247      public function test_get_contexts_for_userid() {
 248  
 249          // Get contexts for the first user.
 250          $contextids = provider::get_contexts_for_userid($this->users[1]->id)->get_contextids();
 251          $this->assertEqualsCanonicalizing([
 252              $this->contexts[1]->id,
 253              $this->contexts[2]->id,
 254          ], $contextids);
 255  
 256          // Get contexts for the second user.
 257          $contextids = provider::get_contexts_for_userid($this->users[2]->id)->get_contextids();
 258          $this->assertEqualsCanonicalizing([
 259              $this->contexts[1]->id,
 260              $this->contexts[2]->id,
 261              $this->contexts[3]->id,
 262          ], $contextids);
 263  
 264          // Get contexts for the third user.
 265          $contextids = provider::get_contexts_for_userid($this->users[3]->id)->get_contextids();
 266          $this->assertEqualsCanonicalizing([
 267              $this->contexts[1]->id,
 268              $this->contexts[2]->id,
 269              $this->contexts[3]->id,
 270          ], $contextids);
 271      }
 272  
 273      /**
 274       * Test getting the users within a context.
 275       */
 276      public function test_get_users_in_context() {
 277          global $DB;
 278          $component = 'mod_wiki';
 279  
 280          // Add a comment from user 4 in context 3.
 281          $this->setUser($this->users[4]);
 282          $this->add_comment($this->pages[3][1], 'Look at me, getting involved!');
 283  
 284          // Ensure userlist for context 1 contains all users.
 285          $userlist = new \core_privacy\local\request\userlist($this->contexts[1], $component);
 286          provider::get_users_in_context($userlist);
 287  
 288          $this->assertCount(4, $userlist);
 289  
 290          $expected = [$this->users[1]->id, $this->users[2]->id, $this->users[3]->id, $this->users[4]->id];
 291          $actual = $userlist->get_userids();
 292          sort($expected);
 293          sort($actual);
 294          $this->assertEquals($expected, $actual);
 295  
 296          // Ensure userlist for context 2 contains users 1-3 only.
 297          $userlist = new \core_privacy\local\request\userlist($this->contexts[2], $component);
 298          provider::get_users_in_context($userlist);
 299  
 300          $this->assertCount(3, $userlist);
 301  
 302          $expected = [$this->users[1]->id, $this->users[2]->id, $this->users[3]->id];
 303          $actual = $userlist->get_userids();
 304          sort($expected);
 305          sort($actual);
 306          $this->assertEquals($expected, $actual);
 307  
 308          // Ensure userlist for context 3 contains users 2, 3 and 4 only.
 309          $userlist = new \core_privacy\local\request\userlist($this->contexts[3], $component);
 310          provider::get_users_in_context($userlist);
 311  
 312          $this->assertCount(3, $userlist);
 313  
 314          $expected = [$this->users[2]->id, $this->users[3]->id, $this->users[4]->id];
 315          $actual = $userlist->get_userids();
 316          sort($expected);
 317          sort($actual);
 318          $this->assertEquals($expected, $actual);
 319  
 320          // Ensure userlist for context 4 is empty.
 321          $userlist = new \core_privacy\local\request\userlist($this->contexts[4], $component);
 322          provider::get_users_in_context($userlist);
 323  
 324          $this->assertEmpty($userlist);
 325      }
 326  
 327      /**
 328       * Export data for user 1
 329       */
 330      public function test_export_user_data1() {
 331  
 332          // Export all contexts for the first user.
 333          $contextids = array_values(array_map(function($c) {
 334              return $c->id;
 335          }, $this->contexts));
 336          $appctx = new approved_contextlist($this->users[1], 'mod_wiki', $contextids);
 337          provider::export_user_data($appctx);
 338  
 339          // First wiki has two pages ever touched by this user.
 340          $data = writer::with_context($this->contexts[1])->get_related_data([$this->subwikis[1]]);
 341          $this->assertEquals([
 342                  $this->pagepaths[1][1],
 343                  $this->pagepaths[1][2]
 344              ], array_keys($data));
 345          // First page was initially created by this user and all its information is returned to this user.
 346          $data11 = $data[$this->pagepaths[1][1]];
 347          $this->assertEquals($this->pages[1][1]->cachedcontent, $data11['page']['cachedcontent']);
 348          $this->assertNotEmpty($data11['page']['timecreated']);
 349          // Wiki creates two revisions when page is created, first one with empty content.
 350          $this->assertEquals(2, count($data11['revisions']));
 351          $this->assertFalse(array_key_exists('locks', $data11));
 352          // Only one file is returned that was in the revision made by this user.
 353  
 354          // The second page was last modified by a different user, so userid in the wiki_pages table is different,
 355          // additional page information is not exported.
 356          $data12 = $data[$this->pagepaths[1][2]];
 357          $this->assertFalse(isset($data12['page']['timecreated']));
 358          // There are two revisions for creating the page and two additional revisions made by this user.
 359          $this->assertEquals(4, count($data12['revisions']));
 360          $lastrevision = array_pop($data12['revisions']);
 361          $this->assertEquals('update2', $lastrevision['content']);
 362  
 363          // There is one file that was used in this user's contents - "Dog face.jpg" and one file in page cachedcontents.
 364          $files = writer::with_context($this->contexts[1])->get_files([$this->subwikis[1]]);
 365          $this->assertEqualsCanonicalizing(['Dog jump.jpg', 'Hamster.jpg'], array_keys($files));
 366  
 367          // Second (individual) wiki for the first user, two pages are returned for this user's subwiki.
 368          $data = writer::with_context($this->contexts[2])->get_related_data([$this->subwikis[21]]);
 369          $this->assertEquals([
 370              $this->pagepaths[21][1],
 371              $this->pagepaths[21][2]
 372          ], array_keys($data));
 373          $files = writer::with_context($this->contexts[2])->get_files([$this->subwikis[21]]);
 374          $this->assertEquals(['mycat.jpg'], array_keys($files));
 375  
 376          // Second (individual) wiki for the first user, nothing is returned for the second user's subwiki.
 377          $this->assertFalse(writer::with_context($this->contexts[2])->has_any_data([$this->subwikis[22]]));
 378  
 379          // Third wiki for the first user, there were no contributions by the first user.
 380          $this->assertFalse(writer::with_context($this->contexts[3])->has_any_data([$this->subwikis[3]]));
 381      }
 382  
 383      /**
 384       * Test export data for user 2
 385       */
 386      public function test_export_user_data2() {
 387  
 388          // Export all contexts for the second user.
 389          $contextids = array_values(array_map(function($c) {
 390              return $c->id;
 391          }, $this->contexts));
 392          $appctx = new approved_contextlist($this->users[2], 'mod_wiki', $contextids);
 393          provider::export_user_data($appctx);
 394  
 395          // First wiki - this user only modified the second page.
 396          $data = writer::with_context($this->contexts[1])->get_related_data([$this->subwikis[1]]);
 397          $this->assertEquals([
 398              $this->pagepaths[1][2]
 399          ], array_keys($data));
 400  
 401          // This user was the last one to modify this page, so the page info is returned.
 402          $data12 = $data[$this->pagepaths[1][2]];
 403          $this->assertEquals('update3 <img src="files/Hamster.jpg" alt="Hamster.jpg" />', trim($data12['page']['cachedcontent']));
 404          // He made one revision.
 405          $this->assertEquals(1, count($data12['revisions']));
 406          $lastrevision = reset($data12['revisions']);
 407          $this->assertEquals('update3 <img src="files/Hamster.jpg">', trim($lastrevision['content']));
 408  
 409          // Only one file was used in the first wiki by this user - Hamster.jpg.
 410          $files = writer::with_context($this->contexts[1])->get_files([$this->subwikis[1]]);
 411          $this->assertEquals(['Hamster.jpg'], array_keys($files));
 412  
 413          // Export second (individual) wiki, nothing is returned for the other user's subwiki.
 414          $this->assertFalse(writer::with_context($this->contexts[2])->has_any_data([$this->subwikis[21]]));
 415  
 416          // Export second (individual) wiki, two pages are returned for this user's subwiki.
 417          $data = writer::with_context($this->contexts[2])->get_related_data([$this->subwikis[22]]);
 418          $this->assertEquals([
 419              $this->pagepaths[22][1],
 420              $this->pagepaths[22][2]
 421          ], array_keys($data));
 422          $files = writer::with_context($this->contexts[2])->get_files([$this->subwikis[22]]);
 423          $this->assertEmpty($files);
 424  
 425          // Second user made contributions to the third wiki.
 426          $data = writer::with_context($this->contexts[3])->get_related_data([$this->subwikis[3]]);
 427          $this->assertEquals([
 428              $this->pagepaths[3][1]
 429          ], array_keys($data));
 430          $files = writer::with_context($this->contexts[3])->get_files([$this->subwikis[3]]);
 431          $this->assertEmpty($files);
 432      }
 433  
 434      /**
 435       * Test export data for user 3 (locks, empty individual wiki)
 436       */
 437      public function test_export_user_data3() {
 438  
 439          // Export all contexts for the third user.
 440          $contextids = array_values(array_map(function($c) {
 441              return $c->id;
 442          }, $this->contexts));
 443          $appctx = new approved_contextlist($this->users[3], 'mod_wiki', $contextids);
 444          provider::export_user_data($appctx);
 445  
 446          // For the third page of the first wiki there are 2 revisions and 1 lock.
 447          $data = writer::with_context($this->contexts[1])->get_related_data([$this->subwikis[1]]);
 448          $this->assertEquals([
 449              $this->pagepaths[1][3]
 450          ], array_keys($data));
 451  
 452          $data13 = $data[$this->pagepaths[1][3]];
 453          $this->assertNotEmpty($data13['page']['timecreated']);
 454          $this->assertEquals(2, count($data13['revisions']));
 455          $this->assertEquals(1, count($data13['locks']));
 456          $files = writer::with_context($this->contexts[1])->get_files([$this->subwikis[1]]);
 457          $this->assertEmpty($files);
 458  
 459          // Empty individual wiki.
 460          $this->assertTrue(writer::with_context($this->contexts[2])->has_any_data());
 461          $data = writer::with_context($this->contexts[2])->get_data([$this->subwikis[23]]);
 462          $this->assertEquals((object)[
 463              'groupid' => 0,
 464              'userid' => $this->users[3]->id
 465          ], $data);
 466          $files = writer::with_context($this->contexts[2])->get_files([$this->subwikis[23]]);
 467          $this->assertEmpty($files);
 468  
 469          // For the third wiki there is no page information, no revisions and one lock.
 470          $data = writer::with_context($this->contexts[3])->get_related_data([$this->subwikis[3]]);
 471          $this->assertEquals([
 472              $this->pagepaths[3][1]
 473          ], array_keys($data));
 474  
 475          $data31 = $data[$this->pagepaths[3][1]];
 476          $this->assertTrue(empty($data31['page']['timecreated']));
 477          $this->assertTrue(empty($data31['revisions']));
 478          $this->assertEquals(1, count($data31['locks']));
 479  
 480          $files = writer::with_context($this->contexts[3])->get_files([$this->subwikis[3]]);
 481          $this->assertEmpty($files);
 482  
 483          // No data for the forth wiki.
 484          $this->assertFalse(writer::with_context($this->contexts[4])->has_any_data());
 485      }
 486  
 487      /**
 488       * Creates a comment object
 489       *
 490       * @param  stdClass $page
 491       * @param  string   $text
 492       * @return comment The comment object.
 493       */
 494      protected function add_comment($page, $text) {
 495          global $DB, $CFG, $USER;
 496          require_once($CFG->dirroot . '/comment/lib.php');
 497          $record = $DB->get_record_sql('SELECT cm.id, cm.course FROM {course_modules} cm
 498              JOIN {modules} m ON m.name = ? AND m.id = cm.module
 499              JOIN {wiki} w ON cm.instance = w.id
 500              JOIN {wiki_subwikis} s ON s.wikiid = w.id
 501              WHERE s.id=?', ['wiki', $page->subwikiid]);
 502          $context = \context_module::instance($record->id);
 503          $args = new \stdClass;
 504          $args->context = $context;
 505          $args->courseid = $record->course;
 506          $args->area = 'wiki_page';
 507          $args->itemid = $page->id;
 508          $args->component = 'mod_wiki';
 509          $comment = new \comment($args);
 510          $comment->set_post_permission(true);
 511          $comment->add($text);
 512          return $comment;
 513      }
 514  
 515      /**
 516       * Test export data when there are comments.
 517       */
 518      public function test_export_user_data_with_comments() {
 519          global $DB;
 520          // Comment on each page in the first wiki as the first user.
 521          $this->setUser($this->users[1]);
 522          $this->add_comment($this->pages[1][1], 'Hello111');
 523          $this->add_comment($this->pages[1][2], 'Hello112');
 524          $this->add_comment($this->pages[1][3], 'Hello113');
 525  
 526          // Comment on second and third page as the third user.
 527          $this->setUser($this->users[3]);
 528          $this->add_comment($this->pages[1][2], 'Hello312');
 529          $this->add_comment($this->pages[1][3], 'Hello313');
 530  
 531          // Export all contexts for the third user.
 532          $contextids = array_values(array_map(function($c) {
 533              return $c->id;
 534          }, $this->contexts));
 535          $appctx = new approved_contextlist($this->users[3], 'mod_wiki', $contextids);
 536          provider::export_user_data($appctx);
 537  
 538          $data = writer::with_context($this->contexts[1])->get_related_data([$this->subwikis[1]]);
 539          // Now user has two pages (comparing to previous test where he had one).
 540          $this->assertEquals([
 541              $this->pagepaths[1][2],
 542              $this->pagepaths[1][3]
 543          ], array_keys($data));
 544  
 545          // Page 1-2 was exported and it has one comment that this user made (comment from another user was not exported).
 546          $data12 = $data[$this->pagepaths[1][2]];
 547          $this->assertTrue(empty($data12['page']['timecreated']));
 548          $this->assertTrue(empty($data12['revisions']));
 549          $this->assertTrue(empty($data12['locks']));
 550          $this->assertEquals(1, count($data12['page']['comments']));
 551  
 552          // Page 1-3 was exported same way as in the previous test and it has two comments.
 553          $data13 = $data[$this->pagepaths[1][3]];
 554          $this->assertNotEmpty($data13['page']['timecreated']);
 555          $this->assertEquals(2, count($data13['revisions']));
 556          $this->assertEquals(1, count($data13['locks']));
 557          $this->assertEquals(2, count($data13['page']['comments']));
 558      }
 559  
 560      /**
 561       * Test for delete_data_for_all_users_in_context().
 562       */
 563      public function test_delete_data_for_all_users_in_context() {
 564          provider::delete_data_for_all_users_in_context($this->contexts[1]);
 565  
 566          $appctx = new approved_contextlist($this->users[1], 'mod_wiki',
 567              [$this->contexts[1]->id, $this->contexts[2]->id]);
 568          provider::export_user_data($appctx);
 569          $this->assertFalse(writer::with_context($this->contexts[1])->has_any_data());
 570          $this->assertTrue(writer::with_context($this->contexts[2])->has_any_data());
 571  
 572          writer::reset();
 573          $appctx = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[1]->id]);
 574          provider::export_user_data($appctx);
 575          $this->assertFalse(writer::with_context($this->contexts[1])->has_any_data());
 576  
 577          writer::reset();
 578          $appctx = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[1]->id]);
 579          provider::export_user_data($appctx);
 580          $this->assertFalse(writer::with_context($this->contexts[1])->has_any_data());
 581      }
 582  
 583      /**
 584       * Test for delete_data_for_user().
 585       */
 586      public function test_delete_data_for_user() {
 587          $appctx = new approved_contextlist($this->users[1], 'mod_wiki',
 588              [$this->contexts[1]->id, $this->contexts[1]->id]);
 589          provider::delete_data_for_user($appctx);
 590  
 591          provider::export_user_data($appctx);
 592          $this->assertTrue(writer::with_context($this->contexts[1])->has_any_data());
 593          $this->assertFalse(writer::with_context($this->contexts[2])->has_any_data());
 594      }
 595  
 596      /**
 597       * Test for delete_data_for_users().
 598       */
 599      public function test_delete_data_for_users() {
 600          $component = 'mod_wiki';
 601  
 602          // Ensure data exists within context 2 - individual wikis.
 603          // Since each user owns their own subwiki in this context, they can be deleted.
 604          $u1ctx2 = new approved_contextlist($this->users[1], 'mod_wiki', [$this->contexts[2]->id]);
 605          provider::export_user_data($u1ctx2);
 606          $u2ctx2 = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[2]->id]);
 607          provider::export_user_data($u2ctx2);
 608          $u3ctx2 = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[2]->id]);
 609          provider::export_user_data($u3ctx2);
 610  
 611          $this->assertTrue(writer::with_context($this->contexts[2])->has_any_data());
 612          writer::reset();
 613  
 614          // Delete user 1 and 2 data, user 3's wiki still remains.
 615          $approveduserids = [$this->users[1]->id, $this->users[2]->id];
 616          $approvedlist = new approved_userlist($this->contexts[2], $component, $approveduserids);
 617          provider::delete_data_for_users($approvedlist);
 618  
 619          $u1ctx2 = new approved_contextlist($this->users[1], 'mod_wiki', [$this->contexts[2]->id]);
 620          provider::export_user_data($u1ctx2);
 621          $u2ctx2 = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[2]->id]);
 622          provider::export_user_data($u2ctx2);
 623          $u3ctx2 = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[2]->id]);
 624          provider::export_user_data($u3ctx2);
 625  
 626          $this->assertTrue(writer::with_context($this->contexts[2])->has_any_data());
 627          writer::reset();
 628  
 629          // Delete user 3's wiki. All 3 subwikis now deleted, so ensure no data is found in this context.
 630          $approveduserids = [$this->users[3]->id];
 631          $approvedlist = new approved_userlist($this->contexts[2], $component, $approveduserids);
 632          provider::delete_data_for_users($approvedlist);
 633  
 634          $u1ctx2 = new approved_contextlist($this->users[1], 'mod_wiki', [$this->contexts[2]->id]);
 635          provider::export_user_data($u1ctx2);
 636          $u2ctx2 = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[2]->id]);
 637          provider::export_user_data($u2ctx2);
 638          $u3ctx2 = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[2]->id]);
 639          provider::export_user_data($u3ctx2);
 640  
 641          $this->assertFalse(writer::with_context($this->contexts[2])->has_any_data());
 642          writer::reset();
 643  
 644          // Ensure Context 1 still contains data.
 645          $u1ctx1 = new approved_contextlist($this->users[1], 'mod_wiki', [$this->contexts[1]->id]);
 646          provider::export_user_data($u1ctx1);
 647          $u2ctx1 = new approved_contextlist($this->users[2], 'mod_wiki', [$this->contexts[1]->id]);
 648          provider::export_user_data($u2ctx1);
 649          $u3ctx1 = new approved_contextlist($this->users[3], 'mod_wiki', [$this->contexts[1]->id]);
 650          provider::export_user_data($u3ctx1);
 651  
 652          $this->assertTrue(writer::with_context($this->contexts[1])->has_any_data());
 653      }
 654  }