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.
   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   * Block recentlyaccesseditems privacy provider tests.
  19   *
  20   * @package    block_recentlyaccesseditems
  21   * @copyright  2018 Michael Hawkins <michaelh@moodle.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   * @since      Moodle 3.6
  24   */
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  use \block_recentlyaccesseditems\privacy\provider;
  28  use \core_privacy\local\request\approved_contextlist;
  29  use \core_privacy\local\request\approved_userlist;
  30  
  31  /**
  32   * Block Recently accessed items privacy provider tests.
  33   *
  34   * @package    block_recentlyaccesseditems
  35   * @copyright  2018 Michael Hawkins <michaelh@moodle.com>
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   * @since      Moodle 3.6
  38   */
  39  class block_recentlyaccesseditems_privacy_testcase extends \core_privacy\tests\provider_testcase {
  40  
  41      /**
  42       * Test getting the context for the user ID related to this plugin.
  43       */
  44      public function test_get_contexts_for_userid() {
  45          $this->resetAfterTest();
  46          $generator = $this->getDataGenerator();
  47  
  48          $student = $generator->create_user();
  49          $studentcontext = context_user::instance($student->id);
  50          $teacher = $generator->create_user();
  51          $teachercontext = context_user::instance($teacher->id);
  52  
  53          // Enrol users in course and add course items.
  54          $course = $generator->create_course();
  55          $generator->enrol_user($student->id, $course->id, 'student');
  56          $generator->enrol_user($teacher->id, $course->id, 'teacher');
  57          $forum = $generator->create_module('forum', ['course' => $course]);
  58          $chat = $generator->create_module('chat', ['course' => $course]);
  59  
  60          // Check nothing is found before block is populated.
  61          $contextlist1 = provider::get_contexts_for_userid($student->id);
  62          $this->assertCount(0, $contextlist1);
  63          $contextlist2 = provider::get_contexts_for_userid($teacher->id);
  64          $this->assertCount(0, $contextlist2);
  65  
  66          // Generate some recent activity for both users.
  67          $this->setUser($student);
  68          $event = \mod_forum\event\course_module_viewed::create(['context' => context_module::instance($forum->cmid),
  69                      'objectid' => $forum->id]);
  70          $event->trigger();
  71  
  72          $this->setUser($teacher);
  73          $event = \mod_chat\event\course_module_viewed::create(['context' => context_module::instance($chat->cmid),
  74                      'objectid' => $chat->id]);
  75          $event->trigger();
  76  
  77          // Ensure provider only fetches the users's own context.
  78          $contextlist1 = provider::get_contexts_for_userid($student->id);
  79          $this->assertCount(1, $contextlist1);
  80          $this->assertEquals($studentcontext, $contextlist1->current());
  81  
  82          $contextlist2 = provider::get_contexts_for_userid($teacher->id);
  83          $this->assertCount(1, $contextlist2);
  84          $this->assertEquals($teachercontext, $contextlist2->current());
  85      }
  86  
  87      /**
  88       * Test getting users in the context ID related to this plugin.
  89       */
  90      public function test_get_users_in_context() {
  91          $this->resetAfterTest();
  92          $generator = $this->getDataGenerator();
  93          $component = 'block_recentlyaccesseditems';
  94  
  95          $student = $generator->create_user();
  96          $studentcontext = context_user::instance($student->id);
  97          $teacher = $generator->create_user();
  98          $teachercontext = context_user::instance($teacher->id);
  99  
 100          // Enrol users in course and add course items.
 101          $course = $generator->create_course();
 102          $generator->enrol_user($student->id, $course->id, 'student');
 103          $generator->enrol_user($teacher->id, $course->id, 'teacher');
 104          $forum = $generator->create_module('forum', ['course' => $course]);
 105          $chat = $generator->create_module('chat', ['course' => $course]);
 106  
 107          // Check nothing is found before block is populated.
 108          $userlist1 = new \core_privacy\local\request\userlist($studentcontext, $component);
 109          provider::get_users_in_context($userlist1);
 110          $this->assertCount(0, $userlist1);
 111          $userlist2 = new \core_privacy\local\request\userlist($teachercontext, $component);
 112          provider::get_users_in_context($userlist2);
 113          $this->assertCount(0, $userlist2);
 114  
 115          // Generate some recent activity for both users.
 116          $this->setUser($student);
 117          $event = \mod_forum\event\course_module_viewed::create(['context' => context_module::instance($forum->cmid),
 118                      'objectid' => $forum->id]);
 119          $event->trigger();
 120          $event = \mod_chat\event\course_module_viewed::create(['context' => context_module::instance($chat->cmid),
 121                      'objectid' => $chat->id]);
 122          $event->trigger();
 123  
 124          $this->setUser($teacher);
 125          $event = \mod_forum\event\course_module_viewed::create(['context' => context_module::instance($forum->cmid),
 126                      'objectid' => $forum->id]);
 127          $event->trigger();
 128          $event = \mod_chat\event\course_module_viewed::create(['context' => context_module::instance($chat->cmid),
 129                      'objectid' => $chat->id]);
 130          $event->trigger();
 131  
 132          // Ensure provider only fetches the user whose user context is checked.
 133          $userlist1 = new \core_privacy\local\request\userlist($studentcontext, $component);
 134          provider::get_users_in_context($userlist1);
 135          $this->assertCount(1, $userlist1);
 136          $this->assertEquals($student, $userlist1->current());
 137  
 138          $userlist2 = new \core_privacy\local\request\userlist($teachercontext, $component);
 139          provider::get_users_in_context($userlist2);
 140          $this->assertCount(1, $userlist2);
 141          $this->assertEquals($teacher, $userlist2->current());
 142      }
 143  
 144      /**
 145       * Test fetching information about user data stored.
 146       */
 147      public function test_get_metadata() {
 148          $collection = new \core_privacy\local\metadata\collection('block_recentlyaccesseditems');
 149          $newcollection = provider::get_metadata($collection);
 150          $itemcollection = $newcollection->get_collection();
 151          $this->assertCount(1, $itemcollection);
 152  
 153          $table = reset($itemcollection);
 154          $this->assertEquals('block_recentlyaccesseditems', $table->get_name());
 155  
 156          $privacyfields = $table->get_privacy_fields();
 157          $this->assertCount(4, $privacyfields);
 158          $this->assertArrayHasKey('userid', $privacyfields);
 159          $this->assertArrayHasKey('courseid', $privacyfields);
 160          $this->assertArrayHasKey('cmid', $privacyfields);
 161          $this->assertArrayHasKey('timeaccess', $privacyfields);
 162  
 163          $this->assertEquals('privacy:metadata:block_recentlyaccesseditemstablesummary', $table->get_summary());
 164      }
 165  
 166      /**
 167       * Test exporting data for an approved contextlist.
 168       */
 169      public function test_export_user_data() {
 170          global $DB;
 171  
 172          $this->resetAfterTest();
 173          $generator = $this->getDataGenerator();
 174          $component = 'block_recentlyaccesseditems';
 175  
 176          $student = $generator->create_user();
 177          $studentcontext = context_user::instance($student->id);
 178  
 179          // Enrol user in course and add course items.
 180          $course = $generator->create_course();
 181          $generator->enrol_user($student->id, $course->id, 'student');
 182          $forum = $generator->create_module('forum', ['course' => $course]);
 183          $chat = $generator->create_module('chat', ['course' => $course]);
 184  
 185          // Generate some recent activity.
 186          $this->setUser($student);
 187          $event = \mod_forum\event\course_module_viewed::create(['context' => context_module::instance($forum->cmid),
 188                  'objectid' => $forum->id]);
 189          $event->trigger();
 190          $event = \mod_chat\event\course_module_viewed::create(['context' => context_module::instance($chat->cmid),
 191                  'objectid' => $chat->id]);
 192          $event->trigger();
 193  
 194          // Confirm data is present.
 195          $params = [
 196              'courseid' => $course->id,
 197              'userid' => $student->id,
 198          ];
 199  
 200          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 201          $this->assertEquals(2, $result);
 202  
 203          // Export data for student.
 204          $approvedlist = new approved_contextlist($student, $component, [$studentcontext->id]);
 205          provider::export_user_data($approvedlist);
 206  
 207          // Confirm student's data is exported.
 208          $writer = \core_privacy\local\request\writer::with_context($studentcontext);
 209          $this->assertTrue($writer->has_any_data());
 210  
 211          delete_course($course, false);
 212          $sc = context_user::instance($student->id);
 213          $approvedlist = new approved_contextlist($student, $component, [$sc->id]);
 214          provider::export_user_data($approvedlist);
 215          $writer = \core_privacy\local\request\writer::with_context($sc);
 216          $this->assertTrue($writer->has_any_data());
 217      }
 218  
 219      /**
 220       * Test exporting data for an approved contextlist with a deleted course
 221       */
 222      public function test_export_user_data_with_deleted_course() {
 223          global $DB;
 224  
 225          $this->resetAfterTest();
 226          $generator = $this->getDataGenerator();
 227          $component = 'block_recentlyaccesseditems';
 228  
 229          $student = $generator->create_user();
 230          $studentcontext = context_user::instance($student->id);
 231  
 232          // Enrol user in course and add course items.
 233          $course = $generator->create_course();
 234          $generator->enrol_user($student->id, $course->id, 'student');
 235          $forum = $generator->create_module('forum', ['course' => $course]);
 236          $chat = $generator->create_module('chat', ['course' => $course]);
 237  
 238          // Generate some recent activity.
 239          $this->setUser($student);
 240          $event = \mod_forum\event\course_module_viewed::create(['context' => context_module::instance($forum->cmid),
 241                  'objectid' => $forum->id]);
 242          $event->trigger();
 243          $event = \mod_chat\event\course_module_viewed::create(['context' => context_module::instance($chat->cmid),
 244                  'objectid' => $chat->id]);
 245          $event->trigger();
 246  
 247          // Confirm data is present.
 248          $params = [
 249              'courseid' => $course->id,
 250              'userid' => $student->id,
 251          ];
 252  
 253          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 254          $this->assertEquals(2, $result);
 255          delete_course($course, false);
 256  
 257          // Export data for student.
 258          $approvedlist = new approved_contextlist($student, $component, [$studentcontext->id]);
 259          provider::export_user_data($approvedlist);
 260  
 261          // Confirm student's data is exported.
 262          $writer = \core_privacy\local\request\writer::with_context($studentcontext);
 263          $this->assertFalse($writer->has_any_data());
 264      }
 265  
 266      /**
 267       * Test deleting data for all users within an approved contextlist.
 268       */
 269      public function test_delete_data_for_all_users_in_context() {
 270          global $DB;
 271  
 272          $this->resetAfterTest();
 273          $generator = $this->getDataGenerator();
 274  
 275          $student = $generator->create_user();
 276          $studentcontext = context_user::instance($student->id);
 277          $teacher = $generator->create_user();
 278  
 279          // Enrol users in course and add course items.
 280          $course = $generator->create_course();
 281          $generator->enrol_user($student->id, $course->id, 'student');
 282          $generator->enrol_user($teacher->id, $course->id, 'teacher');
 283          $forum = $generator->create_module('forum', ['course' => $course]);
 284          $chat = $generator->create_module('chat', ['course' => $course]);
 285  
 286          // Generate some recent activity for both users.
 287          $users = [$student, $teacher];
 288          foreach ($users as $user) {
 289              $this->setUser($user);
 290              $event = \mod_forum\event\course_module_viewed::create(['context' => context_module::instance($forum->cmid),
 291                          'objectid' => $forum->id]);
 292              $event->trigger();
 293              $event = \mod_chat\event\course_module_viewed::create(['context' => context_module::instance($chat->cmid),
 294                          'objectid' => $chat->id]);
 295              $event->trigger();
 296          }
 297  
 298          // Confirm data is present for both users.
 299          $params = [
 300              'courseid' => $course->id,
 301              'userid' => $student->id,
 302          ];
 303  
 304          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 305          $this->assertEquals(2, $result);
 306          $params['userid'] = $teacher->id;
 307          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 308          $this->assertEquals(2, $result);
 309  
 310          // Attempt system context deletion (should have no effect).
 311          $systemcontext = context_system::instance();
 312          provider::delete_data_for_all_users_in_context($systemcontext);
 313  
 314          $params = ['courseid' => $course->id];
 315          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 316          $this->assertEquals(4, $result);
 317  
 318          // Delete all data in student context.
 319          provider::delete_data_for_all_users_in_context($studentcontext);
 320  
 321          // Confirm only student data is deleted.
 322          $params = [
 323              'courseid' => $course->id,
 324              'userid' => $student->id,
 325          ];
 326          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 327          $this->assertEquals(0, $result);
 328  
 329          $params['userid'] = $teacher->id;
 330          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 331          $this->assertEquals(2, $result);
 332      }
 333  
 334      /**
 335       * Test deleting data within an approved contextlist for a user.
 336       */
 337      public function test_delete_data_for_user() {
 338          global $DB;
 339  
 340          $this->resetAfterTest();
 341          $generator = $this->getDataGenerator();
 342          $component = 'block_recentlyaccesseditems';
 343  
 344          $student = $generator->create_user();
 345          $studentcontext = context_user::instance($student->id);
 346          $teacher = $generator->create_user();
 347          $teachercontext = context_user::instance($teacher->id);
 348  
 349          // Enrol users in course and add course items.
 350          $course = $generator->create_course();
 351          $generator->enrol_user($student->id, $course->id, 'student');
 352          $generator->enrol_user($teacher->id, $course->id, 'teacher');
 353          $forum = $generator->create_module('forum', ['course' => $course]);
 354          $chat = $generator->create_module('chat', ['course' => $course]);
 355  
 356          // Generate some recent activity for both users.
 357          $users = [$student, $teacher];
 358          foreach ($users as $user) {
 359              $this->setUser($user);
 360              $event = \mod_forum\event\course_module_viewed::create(['context' => context_module::instance($forum->cmid),
 361                          'objectid' => $forum->id]);
 362              $event->trigger();
 363              $event = \mod_chat\event\course_module_viewed::create(['context' => context_module::instance($chat->cmid),
 364                          'objectid' => $chat->id]);
 365              $event->trigger();
 366          }
 367  
 368          // Confirm data is present for both users.
 369          $params = [
 370              'courseid' => $course->id,
 371              'userid' => $student->id,
 372          ];
 373  
 374          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 375          $this->assertEquals(2, $result);
 376          $params['userid'] = $teacher->id;
 377          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 378          $this->assertEquals(2, $result);
 379  
 380          // Attempt system context deletion (should have no effect).
 381          $systemcontext = context_system::instance();
 382          $approvedlist = new approved_contextlist($teacher, $component, [$systemcontext->id]);
 383          provider::delete_data_for_user($approvedlist);
 384  
 385          $params = ['courseid' => $course->id];
 386          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 387          $this->assertEquals(4, $result);
 388  
 389          // Attempt to delete teacher data in student user context (should have no effect).
 390          $approvedlist = new approved_contextlist($teacher, $component, [$studentcontext->id]);
 391          provider::delete_data_for_user($approvedlist);
 392  
 393          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 394          $this->assertEquals(4, $result);
 395  
 396          // Delete teacher data in their own user context.
 397          $approvedlist = new approved_contextlist($teacher, $component, [$teachercontext->id]);
 398          provider::delete_data_for_user($approvedlist);
 399  
 400          // Confirm only teacher data is deleted.
 401          $params = [
 402              'courseid' => $course->id,
 403              'userid' => $student->id,
 404          ];
 405  
 406          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 407          $this->assertEquals(2, $result);
 408  
 409          $params['userid'] = $teacher->id;
 410          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 411          $this->assertEquals(0, $result);
 412      }
 413  
 414      /**
 415       * Test deleting data within a context for an approved userlist.
 416       */
 417      public function test_delete_data_for_users() {
 418          global $DB;
 419  
 420          $this->resetAfterTest();
 421          $generator = $this->getDataGenerator();
 422          $component = 'block_recentlyaccesseditems';
 423  
 424          $student = $generator->create_user();
 425          $studentcontext = context_user::instance($student->id);
 426          $teacher = $generator->create_user();
 427          $teachercontext = context_user::instance($teacher->id);
 428  
 429          // Enrol users in course and add course items.
 430          $course = $generator->create_course();
 431          $generator->enrol_user($student->id, $course->id, 'student');
 432          $generator->enrol_user($teacher->id, $course->id, 'teacher');
 433          $forum = $generator->create_module('forum', ['course' => $course]);
 434          $chat = $generator->create_module('chat', ['course' => $course]);
 435  
 436          // Generate some recent activity for all users.
 437          $users = [$student, $teacher];
 438          foreach ($users as $user) {
 439              $this->setUser($user);
 440              $event = \mod_forum\event\course_module_viewed::create(['context' => context_module::instance($forum->cmid),
 441                          'objectid' => $forum->id]);
 442              $event->trigger();
 443              $event = \mod_chat\event\course_module_viewed::create(['context' => context_module::instance($chat->cmid),
 444                          'objectid' => $chat->id]);
 445              $event->trigger();
 446          }
 447  
 448          // Confirm data is present for all 3 users.
 449          $params = [
 450              'courseid' => $course->id,
 451              'userid' => $student->id,
 452          ];
 453  
 454          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 455          $this->assertEquals(2, $result);
 456          $params['userid'] = $teacher->id;
 457          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 458          $this->assertEquals(2, $result);
 459  
 460          // Attempt system context deletion (should have no effect).
 461          $systemcontext = context_system::instance();
 462          $approvedlist = new approved_userlist($systemcontext, $component, [$student->id, $teacher->id]);
 463          provider::delete_data_for_users($approvedlist);
 464  
 465          $params = ['courseid' => $course->id];
 466          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 467          $this->assertEquals(4, $result);
 468  
 469          // Attempt to delete data in another user's context (should have no effect).
 470          $approvedlist = new approved_userlist($studentcontext, $component, [$teacher->id]);
 471          provider::delete_data_for_users($approvedlist);
 472  
 473          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 474          $this->assertEquals(4, $result);
 475  
 476          // Delete users' data in teacher's context.
 477          $approvedlist = new approved_userlist($teachercontext, $component, [$student->id, $teacher->id]);
 478          provider::delete_data_for_users($approvedlist);
 479  
 480          // Confirm only teacher data is deleted.
 481          $params = [
 482              'courseid' => $course->id,
 483              'userid' => $student->id,
 484          ];
 485  
 486          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 487          $this->assertEquals(2, $result);
 488          $params['userid'] = $teacher->id;
 489          $result = $DB->count_records('block_recentlyaccesseditems', $params);
 490          $this->assertEquals(0, $result);
 491      }
 492  }