Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310]

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