Search moodle.org's
Developer Documentation

See Release Notes

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