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    logstore_database
  21   * @category   test
  22   * @copyright  2018 Frédéric Massart
  23   * @author     Frédéric Massart <fred@branchup.tech>
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  namespace logstore_database\privacy;
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  global $CFG;
  30  
  31  use core_privacy\tests\provider_testcase;
  32  use core_privacy\local\request\contextlist;
  33  use core_privacy\local\request\approved_contextlist;
  34  use core_privacy\local\request\transform;
  35  use core_privacy\local\request\writer;
  36  use logstore_database\privacy\provider;
  37  
  38  require_once (__DIR__ . '/../fixtures/event.php');
  39  
  40  /**
  41   * Data provider testcase class.
  42   *
  43   * This testcase is almost identical to the logstore_standard testcase, aside from the
  44   * initialisation of the relevant logstore obviously.
  45   *
  46   * @package    logstore_database
  47   * @category   test
  48   * @copyright  2018 Frédéric Massart
  49   * @author     Frédéric Massart <fred@branchup.tech>
  50   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  51   */
  52  class provider_test extends provider_testcase {
  53  
  54      public function setUp(): void {
  55          global $CFG;
  56          $this->resetAfterTest();
  57          $this->preventResetByRollback(); // Logging waits till the transaction gets committed.
  58  
  59          // Fake the settings, we will abuse the standard plugin table here...
  60          set_config('dbdriver', $CFG->dblibrary . '/' . $CFG->dbtype, 'logstore_database');
  61          set_config('dbhost', $CFG->dbhost, 'logstore_database');
  62          set_config('dbuser', $CFG->dbuser, 'logstore_database');
  63          set_config('dbpass', $CFG->dbpass, 'logstore_database');
  64          set_config('dbname', $CFG->dbname, 'logstore_database');
  65          set_config('dbtable', $CFG->prefix . 'logstore_standard_log', 'logstore_database');
  66          if (!empty($CFG->dboptions['dbpersist'])) {
  67              set_config('dbpersist', 1, 'logstore_database');
  68          } else {
  69              set_config('dbpersist', 0, 'logstore_database');
  70          }
  71          if (!empty($CFG->dboptions['dbsocket'])) {
  72              set_config('dbsocket', $CFG->dboptions['dbsocket'], 'logstore_database');
  73          } else {
  74              set_config('dbsocket', '', 'logstore_database');
  75          }
  76          if (!empty($CFG->dboptions['dbport'])) {
  77              set_config('dbport', $CFG->dboptions['dbport'], 'logstore_database');
  78          } else {
  79              set_config('dbport', '', 'logstore_database');
  80          }
  81          if (!empty($CFG->dboptions['dbschema'])) {
  82              set_config('dbschema', $CFG->dboptions['dbschema'], 'logstore_database');
  83          } else {
  84              set_config('dbschema', '', 'logstore_database');
  85          }
  86          if (!empty($CFG->dboptions['dbcollation'])) {
  87              set_config('dbcollation', $CFG->dboptions['dbcollation'], 'logstore_database');
  88          } else {
  89              set_config('dbcollation', '', 'logstore_database');
  90          }
  91          if (!empty($CFG->dboptions['dbhandlesoptions'])) {
  92              set_config('dbhandlesoptions', $CFG->dboptions['dbhandlesoptions'], 'logstore_database');
  93          } else {
  94              set_config('dbhandlesoptions', false, 'logstore_database');
  95          }
  96      }
  97  
  98      public function test_get_contexts_for_userid() {
  99          $admin = \core_user::get_user(2);
 100          $u1 = $this->getDataGenerator()->create_user();
 101          $u2 = $this->getDataGenerator()->create_user();
 102          $u3 = $this->getDataGenerator()->create_user();
 103  
 104          $c1 = $this->getDataGenerator()->create_course();
 105          $cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
 106          $c2 = $this->getDataGenerator()->create_course();
 107          $cm2 = $this->getDataGenerator()->create_module('url', ['course' => $c2]);
 108  
 109          $sysctx = \context_system::instance();
 110          $c1ctx = \context_course::instance($c1->id);
 111          $c2ctx = \context_course::instance($c2->id);
 112          $cm1ctx = \context_module::instance($cm1->cmid);
 113          $cm2ctx = \context_module::instance($cm2->cmid);
 114  
 115          $this->enable_logging();
 116          $manager = get_log_manager(true);
 117  
 118          // User 1 is the author.
 119          $this->setUser($u1);
 120          $this->assert_contextlist_equals($this->get_contextlist_for_user($u1), []);
 121          $e = \logstore_database\event\unittest_executed::create(['context' => $cm1ctx]);
 122          $e->trigger();
 123          $this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$cm1ctx]);
 124  
 125          // User 2 is the related user.
 126          $this->setUser(0);
 127          $this->assert_contextlist_equals($this->get_contextlist_for_user($u2), []);
 128          $e = \logstore_database\event\unittest_executed::create(['context' => $cm2ctx, 'relateduserid' => $u2->id]);
 129          $e->trigger();
 130          $this->assert_contextlist_equals($this->get_contextlist_for_user($u2), [$cm2ctx]);
 131  
 132          // Admin user is the real user.
 133          $this->assert_contextlist_equals($this->get_contextlist_for_user($admin), []);
 134          $this->assert_contextlist_equals($this->get_contextlist_for_user($u3), []);
 135          $this->setAdminUser();
 136          \core\session\manager::loginas($u3->id, $sysctx);
 137          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
 138          $e->trigger();
 139          $this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx]);
 140          $this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx, $c1ctx]);
 141  
 142          // By admin user masquerading u1 related to u3.
 143          $this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$cm1ctx]);
 144          $this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx, $c1ctx]);
 145          $this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx]);
 146          $this->setAdminUser();
 147          \core\session\manager::loginas($u1->id, \context_system::instance());
 148          $e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx, 'relateduserid' => $u3->id]);
 149          $e->trigger();
 150          $this->assert_contextlist_equals($this->get_contextlist_for_user($u1), [$sysctx, $cm1ctx, $c2ctx]);
 151          $this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx, $c1ctx, $c2ctx]);
 152          $this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx, $c2ctx]);
 153      }
 154  
 155      /**
 156       * Check that user IDs are returned for a given context.
 157       */
 158      public function test_add_userids_for_context() {
 159          $admin = \core_user::get_user(2);
 160          $u1 = $this->getDataGenerator()->create_user();
 161          $u2 = $this->getDataGenerator()->create_user();
 162          $u3 = $this->getDataGenerator()->create_user();
 163          $u4 = $this->getDataGenerator()->create_user();
 164  
 165          $c1 = $this->getDataGenerator()->create_course();
 166  
 167          $sysctx = \context_system::instance();
 168          $c1ctx = \context_course::instance($c1->id);
 169  
 170          $this->enable_logging();
 171          $manager = get_log_manager(true);
 172  
 173          $userlist = new \core_privacy\local\request\userlist($sysctx, 'logstore_database');
 174          $userids = $userlist->get_userids();
 175          $this->assertEmpty($userids);
 176          provider::add_userids_for_context($userlist);
 177          $userids = $userlist->get_userids();
 178          $this->assertEmpty($userids);
 179          // User one should be added (userid).
 180          $this->setUser($u1);
 181          $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]);
 182          $e->trigger();
 183          // User two (userids) and three (relateduserid) should be added.
 184          $this->setUser($u2);
 185          $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx, 'relateduserid' => $u3->id]);
 186          $e->trigger();
 187          // The admin user should be added (realuserid).
 188          $this->setAdminUser();
 189          \core\session\manager::loginas($u2->id, \context_system::instance());
 190          $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]);
 191          $e->trigger();
 192          // Set off an event in a different context. User 4 should not be returned below.
 193          $this->setUser($u4);
 194          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
 195          $e->trigger();
 196  
 197          provider::add_userids_for_context($userlist);
 198          $userids = $userlist->get_userids();
 199          $this->assertCount(4, $userids);
 200          $expectedresult = [$admin->id, $u1->id, $u2->id, $u3->id];
 201          $this->assertEmpty(array_diff($expectedresult, $userids));
 202      }
 203  
 204      public function test_delete_data_for_user() {
 205          global $DB;
 206          $u1 = $this->getDataGenerator()->create_user();
 207          $u2 = $this->getDataGenerator()->create_user();
 208          $c1 = $this->getDataGenerator()->create_course();
 209          $c2 = $this->getDataGenerator()->create_course();
 210          $sysctx = \context_system::instance();
 211          $c1ctx = \context_course::instance($c1->id);
 212          $c2ctx = \context_course::instance($c2->id);
 213  
 214          $this->enable_logging();
 215          $manager = get_log_manager(true);
 216  
 217          // User 1 is the author.
 218          $this->setUser($u1);
 219          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
 220          $e->trigger();
 221          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
 222          $e->trigger();
 223          $e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx]);
 224          $e->trigger();
 225  
 226          // User 2 is the author.
 227          $this->setUser($u2);
 228          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
 229          $e->trigger();
 230          $e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx]);
 231          $e->trigger();
 232  
 233          // Confirm data present.
 234          $this->assertTrue($DB->record_exists('logstore_standard_log', ['userid' => $u1->id, 'contextid' => $c1ctx->id]));
 235          $this->assertEquals(3, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
 236          $this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
 237  
 238          // Delete all the things!
 239          provider::delete_data_for_user(new approved_contextlist($u1, 'logstore_database', [$c1ctx->id]));
 240          $this->assertFalse($DB->record_exists('logstore_standard_log', ['userid' => $u1->id, 'contextid' => $c1ctx->id]));
 241          $this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
 242          $this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
 243      }
 244  
 245      public function test_delete_data_for_all_users_in_context() {
 246          global $DB;
 247          $u1 = $this->getDataGenerator()->create_user();
 248          $u2 = $this->getDataGenerator()->create_user();
 249          $c1 = $this->getDataGenerator()->create_course();
 250          $c2 = $this->getDataGenerator()->create_course();
 251          $sysctx = \context_system::instance();
 252          $c1ctx = \context_course::instance($c1->id);
 253          $c2ctx = \context_course::instance($c2->id);
 254  
 255          $this->enable_logging();
 256          $manager = get_log_manager(true);
 257  
 258          // User 1 is the author.
 259          $this->setUser($u1);
 260          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
 261          $e->trigger();
 262          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
 263          $e->trigger();
 264          $e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx]);
 265          $e->trigger();
 266  
 267          // User 2 is the author.
 268          $this->setUser($u2);
 269          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
 270          $e->trigger();
 271          $e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx]);
 272          $e->trigger();
 273  
 274          // Confirm data present.
 275          $this->assertTrue($DB->record_exists('logstore_standard_log', ['contextid' => $c1ctx->id]));
 276          $this->assertEquals(3, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
 277          $this->assertEquals(2, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
 278  
 279          // Delete all the things!
 280          provider::delete_data_for_all_users_in_context($c1ctx);
 281          $this->assertFalse($DB->record_exists('logstore_standard_log', ['contextid' => $c1ctx->id]));
 282          $this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u1->id]));
 283          $this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u2->id]));
 284      }
 285  
 286      /**
 287       * Check that data is removed for the listed users in a given context.
 288       */
 289      public function test_delete_data_for_userlist() {
 290          global $DB;
 291  
 292          $u1 = $this->getDataGenerator()->create_user();
 293          $u2 = $this->getDataGenerator()->create_user();
 294          $u3 = $this->getDataGenerator()->create_user();
 295          $u4 = $this->getDataGenerator()->create_user();
 296  
 297          $course = $this->getDataGenerator()->create_course();
 298          $sysctx = \context_system::instance();
 299          $c1ctx = \context_course::instance($course->id);
 300  
 301          $this->enable_logging();
 302          $manager = get_log_manager(true);
 303  
 304          $this->setUser($u1);
 305          $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]);
 306          $e->trigger();
 307          $this->setUser($u2);
 308          $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]);
 309          $e->trigger();
 310          $this->setUser($u3);
 311          $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]);
 312          $e->trigger();
 313          $this->setUser($u4);
 314          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]);
 315          $e->trigger();
 316  
 317          // Check that four records were created.
 318          $this->assertEquals(4, $DB->count_records('logstore_standard_log'));
 319  
 320          $userlist = new \core_privacy\local\request\approved_userlist($sysctx, 'logstore_database', [$u1->id, $u3->id]);
 321          provider::delete_data_for_userlist($userlist);
 322          // We should have a record for u2 and u4.
 323          $this->assertEquals(2, $DB->count_records('logstore_standard_log'));
 324  
 325          $records = $DB->get_records('logstore_standard_log', ['contextid' => $sysctx->id]);
 326          $this->assertCount(1, $records);
 327          $currentrecord = array_shift($records);
 328          $this->assertEquals($u2->id, $currentrecord->userid);
 329      }
 330  
 331      public function test_export_data_for_user() {
 332          $admin = \core_user::get_user(2);
 333          $u1 = $this->getDataGenerator()->create_user();
 334          $u2 = $this->getDataGenerator()->create_user();
 335          $u3 = $this->getDataGenerator()->create_user();
 336          $u4 = $this->getDataGenerator()->create_user();
 337          $c1 = $this->getDataGenerator()->create_course();
 338          $cm1 = $this->getDataGenerator()->create_module('url', ['course' => $c1]);
 339          $c2 = $this->getDataGenerator()->create_course();
 340          $cm2 = $this->getDataGenerator()->create_module('url', ['course' => $c2]);
 341          $sysctx = \context_system::instance();
 342          $c1ctx = \context_course::instance($c1->id);
 343          $c2ctx = \context_course::instance($c2->id);
 344          $cm1ctx = \context_module::instance($cm1->cmid);
 345          $cm2ctx = \context_module::instance($cm2->cmid);
 346  
 347          $path = [get_string('privacy:path:logs', 'tool_log'), get_string('pluginname', 'logstore_database')];
 348          $this->enable_logging();
 349          $manager = get_log_manager(true);
 350  
 351          // User 1 is the author.
 352          $this->setUser($u1);
 353          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx, 'other' => ['i' => 0]]);
 354          $e->trigger();
 355  
 356          // User 2 is related.
 357          $this->setUser(0);
 358          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx, 'relateduserid' => $u2->id,
 359              'other' => ['i' => 1]]);
 360          $e->trigger();
 361  
 362          // Admin user masquerades u3, which is related to u4.
 363          $this->setAdminUser();
 364          \core\session\manager::loginas($u3->id, $sysctx);
 365          $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx, 'relateduserid' => $u4->id,
 366              'other' => ['i' => 2]]);
 367          $e->trigger();
 368  
 369          // Confirm data present for u1.
 370          provider::export_user_data(new approved_contextlist($u1, 'logstore_database', [$c2ctx->id, $c1ctx->id]));
 371          $data = writer::with_context($c2ctx)->get_data($path);
 372          $this->assertEmpty($data);
 373          $data = writer::with_context($c1ctx)->get_data($path);
 374          $this->assertCount(1, $data->logs);
 375          $this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
 376          $this->assertSame(0, $data->logs[0]['other']['i']);
 377  
 378          // Confirm data present for u2.
 379          writer::reset();
 380          provider::export_user_data(new approved_contextlist($u2, 'logstore_database', [$c2ctx->id, $c1ctx->id]));
 381          $data = writer::with_context($c2ctx)->get_data($path);
 382          $this->assertEmpty($data);
 383          $data = writer::with_context($c1ctx)->get_data($path);
 384          $this->assertCount(1, $data->logs);
 385          $this->assertEquals(transform::yesno(false), $data->logs[0]['author_of_the_action_was_you']);
 386          $this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
 387          $this->assertSame(1, $data->logs[0]['other']['i']);
 388  
 389          // Confirm data present for u3.
 390          writer::reset();
 391          provider::export_user_data(new approved_contextlist($u3, 'logstore_database', [$c2ctx->id, $c1ctx->id]));
 392          $data = writer::with_context($c2ctx)->get_data($path);
 393          $this->assertEmpty($data);
 394          $data = writer::with_context($c1ctx)->get_data($path);
 395          $this->assertCount(1, $data->logs);
 396          $this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
 397          $this->assertEquals(transform::yesno(false), $data->logs[0]['related_user_was_you']);
 398          $this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
 399          $this->assertEquals(transform::yesno(false), $data->logs[0]['masquerading_user_was_you']);
 400          $this->assertSame(2, $data->logs[0]['other']['i']);
 401  
 402          // Confirm data present for u4.
 403          writer::reset();
 404          provider::export_user_data(new approved_contextlist($u4, 'logstore_database', [$c2ctx->id, $c1ctx->id]));
 405          $data = writer::with_context($c2ctx)->get_data($path);
 406          $this->assertEmpty($data);
 407          $data = writer::with_context($c1ctx)->get_data($path);
 408          $this->assertCount(1, $data->logs);
 409          $this->assertEquals(transform::yesno(false), $data->logs[0]['author_of_the_action_was_you']);
 410          $this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
 411          $this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
 412          $this->assertEquals(transform::yesno(false), $data->logs[0]['masquerading_user_was_you']);
 413          $this->assertSame(2, $data->logs[0]['other']['i']);
 414  
 415          // Add anonymous events.
 416          $this->setUser($u1);
 417          $e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx, 'relateduserid' => $u2->id,
 418              'anonymous' => true]);
 419          $e->trigger();
 420          $this->setAdminUser();
 421          \core\session\manager::loginas($u3->id, $sysctx);
 422          $e = \logstore_database\event\unittest_executed::create(['context' => $c2ctx, 'relateduserid' => $u4->id,
 423              'anonymous' => true]);
 424          $e->trigger();
 425  
 426          // Confirm data present for u1.
 427          provider::export_user_data(new approved_contextlist($u1, 'logstore_database', [$c2ctx->id]));
 428          $data = writer::with_context($c2ctx)->get_data($path);
 429          $this->assertCount(1, $data->logs);
 430          $this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
 431          $this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
 432  
 433          // Confirm data present for u2.
 434          writer::reset();
 435          provider::export_user_data(new approved_contextlist($u2, 'logstore_database', [$c2ctx->id]));
 436          $data = writer::with_context($c2ctx)->get_data($path);
 437          $this->assertCount(1, $data->logs);
 438          $this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
 439          $this->assertArrayNotHasKey('author_of_the_action_was_you', $data->logs[0]);
 440          $this->assertArrayNotHasKey('authorid', $data->logs[0]);
 441          $this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
 442  
 443          // Confirm data present for u3.
 444          writer::reset();
 445          provider::export_user_data(new approved_contextlist($u3, 'logstore_database', [$c2ctx->id]));
 446          $data = writer::with_context($c2ctx)->get_data($path);
 447          $this->assertCount(1, $data->logs);
 448          $this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
 449          $this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_you']);
 450          $this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
 451          $this->assertArrayNotHasKey('masquerading_user_was_you', $data->logs[0]);
 452          $this->assertArrayNotHasKey('masqueradinguserid', $data->logs[0]);
 453  
 454          // Confirm data present for u4.
 455          writer::reset();
 456          provider::export_user_data(new approved_contextlist($u4, 'logstore_database', [$c2ctx->id]));
 457          $data = writer::with_context($c2ctx)->get_data($path);
 458          $this->assertCount(1, $data->logs);
 459          $this->assertEquals(transform::yesno(true), $data->logs[0]['action_was_done_anonymously']);
 460          $this->assertArrayNotHasKey('author_of_the_action_was_you', $data->logs[0]);
 461          $this->assertArrayNotHasKey('authorid', $data->logs[0]);
 462          $this->assertEquals(transform::yesno(true), $data->logs[0]['related_user_was_you']);
 463          $this->assertEquals(transform::yesno(true), $data->logs[0]['author_of_the_action_was_masqueraded']);
 464          $this->assertArrayNotHasKey('masquerading_user_was_you', $data->logs[0]);
 465          $this->assertArrayNotHasKey('masqueradinguserid', $data->logs[0]);
 466      }
 467  
 468      /**
 469       * Assert the content of a context list.
 470       *
 471       * @param contextlist $contextlist The collection.
 472       * @param array $expected List of expected contexts or IDs.
 473       * @return void
 474       */
 475      protected function assert_contextlist_equals($contextlist, array $expected) {
 476          $expectedids = array_map(function($context) {
 477              if (is_object($context)) {
 478                  return $context->id;
 479              }
 480              return $context;
 481          }, $expected);
 482          $contextids = array_map('intval', $contextlist->get_contextids());
 483          sort($contextids);
 484          sort($expectedids);
 485          $this->assertEquals($expectedids, $contextids);
 486      }
 487  
 488      /**
 489       * Enable logging.
 490       *
 491       * @return void
 492       */
 493      protected function enable_logging() {
 494          set_config('enabled_stores', 'logstore_database', 'tool_log');
 495          set_config('buffersize', 0, 'logstore_database');
 496          set_config('logguests', 1, 'logstore_database');
 497          get_log_manager(true);
 498      }
 499  
 500      /**
 501       * Get the contextlist for a user.
 502       *
 503       * @param object $user The user.
 504       * @return contextlist
 505       */
 506      protected function get_contextlist_for_user($user) {
 507          $contextlist = new contextlist();
 508          provider::add_contexts_for_userid($contextlist, $user->id);
 509          return $contextlist;
 510      }
 511  }