Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 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   * Tests for privacy functions.
  19   *
  20   * @package    report_stats
  21   * @copyright  2018 Adrian Greeve <adriangreeve.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  use \report_stats\privacy\provider;
  28  use \core_privacy\local\request\approved_userlist;
  29  
  30  /**
  31   * Class report_stats_privacy_testcase
  32   *
  33   * @package    report_stats
  34   * @copyright  2018 Adrian Greeve <adriangreeve.com>
  35   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
  36   */
  37  class report_stats_privacy_testcase extends advanced_testcase {
  38  
  39      /**
  40       * Convenience function to create stats.
  41       *
  42       * @param int $courseid Course ID for this record.
  43       * @param int $userid User ID for this record.
  44       * @param string $table Stat table to insert into.
  45       */
  46      protected function create_stats($courseid, $userid, $table) {
  47          global $DB;
  48  
  49          $data = (object) [
  50              'courseid' => $courseid,
  51              'userid' => $userid,
  52              'roleid' => 0,
  53              'timeend' => time(),
  54              'statsreads' => rand(1, 50),
  55              'statswrites' => rand(1, 50),
  56              'stattype' => 'activity'
  57          ];
  58          $DB->insert_record($table, $data);
  59      }
  60  
  61      /**
  62       * Get all of the contexts related to a user and stat tables.
  63       */
  64      public function test_get_contexts_for_userid() {
  65          $this->resetAfterTest();
  66          $user1 = $this->getDataGenerator()->create_user();
  67          $user2 = $this->getDataGenerator()->create_user();
  68          $user3 = $this->getDataGenerator()->create_user();
  69  
  70          $course1 = $this->getDataGenerator()->create_course();
  71          $course2 = $this->getDataGenerator()->create_course();
  72          $course3 = $this->getDataGenerator()->create_course();
  73  
  74          $context1 = context_course::instance($course1->id);
  75          $context2 = context_course::instance($course2->id);
  76          $context3 = context_course::instance($course3->id);
  77  
  78          $this->create_stats($course1->id, $user1->id, 'stats_user_daily');
  79          $this->create_stats($course2->id, $user1->id, 'stats_user_monthly');
  80          $this->create_stats($course1->id, $user2->id, 'stats_user_weekly');
  81  
  82          $contextlist = provider::get_contexts_for_userid($user1->id);
  83          $this->assertCount(2, $contextlist->get_contextids());
  84          foreach ($contextlist->get_contexts() as $context) {
  85              $this->assertEquals(CONTEXT_COURSE, $context->contextlevel);
  86              $this->assertNotEquals($context3, $context);
  87          }
  88          $contextlist = provider::get_contexts_for_userid($user2->id);
  89          $this->assertCount(1, $contextlist->get_contextids());
  90          $this->assertEquals($context1, $contextlist->current());
  91      }
  92  
  93      /**
  94       * Test that stat data is exported as required.
  95       */
  96      public function test_export_user_data() {
  97          $this->resetAfterTest();
  98          $user = $this->getDataGenerator()->create_user();
  99          $course1 = $this->getDataGenerator()->create_course();
 100          $course2 = $this->getDataGenerator()->create_course();
 101          $context1 = context_course::instance($course1->id);
 102          $context2 = context_course::instance($course2->id);
 103          $this->create_stats($course1->id, $user->id, 'stats_user_daily');
 104          $this->create_stats($course1->id, $user->id, 'stats_user_daily');
 105          $this->create_stats($course2->id, $user->id, 'stats_user_weekly');
 106          $this->create_stats($course2->id, $user->id, 'stats_user_monthly');
 107          $this->create_stats($course1->id, $user->id, 'stats_user_monthly');
 108  
 109          $approvedlist = new \core_privacy\local\request\approved_contextlist($user, 'report_stats', [$context1->id, $context2->id]);
 110  
 111          provider::export_user_data($approvedlist);
 112          $writer = \core_privacy\local\request\writer::with_context($context1);
 113          $dailystats = (array) $writer->get_data([get_string('privacy:dailypath', 'report_stats')]);
 114          $this->assertCount(2, $dailystats);
 115          $monthlystats = (array) $writer->get_data([get_string('privacy:monthlypath', 'report_stats')]);
 116          $this->assertCount(1, $monthlystats);
 117          $data = array_shift($monthlystats);
 118          $this->assertEquals($course1->fullname, $data['course']);
 119          $writer = \core_privacy\local\request\writer::with_context($context2);
 120          $monthlystats = (array) $writer->get_data([get_string('privacy:monthlypath', 'report_stats')]);
 121          $this->assertCount(1, $monthlystats);
 122          $data = array_shift($monthlystats);
 123          $this->assertEquals($course2->fullname, $data['course']);
 124          $weeklystats = (array) $writer->get_data([get_string('privacy:weeklypath', 'report_stats')]);
 125          $this->assertCount(1, $weeklystats);
 126          $data = array_shift($weeklystats);
 127          $this->assertEquals($course2->fullname, $data['course']);
 128      }
 129  
 130      /**
 131       * Test that stat data is deleted for a whole context.
 132       */
 133      public function test_delete_data_for_all_users_in_context() {
 134          global $DB;
 135  
 136          $this->resetAfterTest();
 137          $user1 = $this->getDataGenerator()->create_user();
 138          $user2 = $this->getDataGenerator()->create_user();
 139  
 140          $course1 = $this->getDataGenerator()->create_course();
 141          $course2 = $this->getDataGenerator()->create_course();
 142          $context1 = context_course::instance($course1->id);
 143          $context2 = context_course::instance($course2->id);
 144          $this->create_stats($course1->id, $user1->id, 'stats_user_daily');
 145          $this->create_stats($course1->id, $user1->id, 'stats_user_daily');
 146          $this->create_stats($course1->id, $user1->id, 'stats_user_monthly');
 147          $this->create_stats($course1->id, $user2->id, 'stats_user_weekly');
 148          $this->create_stats($course2->id, $user2->id, 'stats_user_daily');
 149          $this->create_stats($course2->id, $user2->id, 'stats_user_weekly');
 150          $this->create_stats($course2->id, $user2->id, 'stats_user_monthly');
 151  
 152          $dailyrecords = $DB->get_records('stats_user_daily');
 153          $this->assertCount(3, $dailyrecords);
 154          $weeklyrecords = $DB->get_records('stats_user_weekly');
 155          $this->assertCount(2, $weeklyrecords);
 156          $monthlyrecords = $DB->get_records('stats_user_monthly');
 157          $this->assertCount(2, $monthlyrecords);
 158  
 159          // Delete all user data for course 1.
 160          provider::delete_data_for_all_users_in_context($context1);
 161          $dailyrecords = $DB->get_records('stats_user_daily');
 162          $this->assertCount(1, $dailyrecords);
 163          $weeklyrecords = $DB->get_records('stats_user_weekly');
 164          $this->assertCount(1, $weeklyrecords);
 165          $monthlyrecords = $DB->get_records('stats_user_monthly');
 166          $this->assertCount(1, $monthlyrecords);
 167      }
 168  
 169      /**
 170       * Test that stats are deleted for one user.
 171       */
 172      public function test_delete_data_for_user() {
 173          global $DB;
 174  
 175          $this->resetAfterTest();
 176          $user1 = $this->getDataGenerator()->create_user();
 177          $user2 = $this->getDataGenerator()->create_user();
 178  
 179          $course1 = $this->getDataGenerator()->create_course();
 180          $course2 = $this->getDataGenerator()->create_course();
 181          $context1 = context_course::instance($course1->id);
 182          $context2 = context_course::instance($course2->id);
 183          $this->create_stats($course1->id, $user1->id, 'stats_user_daily');
 184          $this->create_stats($course1->id, $user1->id, 'stats_user_daily');
 185          $this->create_stats($course1->id, $user1->id, 'stats_user_monthly');
 186          $this->create_stats($course1->id, $user2->id, 'stats_user_weekly');
 187          $this->create_stats($course2->id, $user2->id, 'stats_user_daily');
 188          $this->create_stats($course2->id, $user2->id, 'stats_user_weekly');
 189          $this->create_stats($course2->id, $user2->id, 'stats_user_monthly');
 190  
 191          $dailyrecords = $DB->get_records('stats_user_daily');
 192          $this->assertCount(3, $dailyrecords);
 193          $weeklyrecords = $DB->get_records('stats_user_weekly');
 194          $this->assertCount(2, $weeklyrecords);
 195          $monthlyrecords = $DB->get_records('stats_user_monthly');
 196          $this->assertCount(2, $monthlyrecords);
 197  
 198          // Delete all user data for course 1.
 199          $approvedlist = new \core_privacy\local\request\approved_contextlist($user1, 'report_stats', [$context1->id]);
 200          provider::delete_data_for_user($approvedlist);
 201          $dailyrecords = $DB->get_records('stats_user_daily');
 202          $this->assertCount(1, $dailyrecords);
 203          $weeklyrecords = $DB->get_records('stats_user_weekly');
 204          $this->assertCount(2, $weeklyrecords);
 205          $monthlyrecords = $DB->get_records('stats_user_monthly');
 206          $this->assertCount(1, $monthlyrecords);
 207      }
 208  
 209      /**
 210       * Test that only users within a course context are fetched.
 211       */
 212      public function test_get_users_in_context() {
 213          $this->resetAfterTest();
 214  
 215          $component = 'report_stats';
 216  
 217          // Create user1.
 218          $user1 = $this->getDataGenerator()->create_user();
 219          // Create user2.
 220          $user2 = $this->getDataGenerator()->create_user();
 221          // Create course1.
 222          $course1 = $this->getDataGenerator()->create_course();
 223          $coursecontext1 = context_course::instance($course1->id);
 224          // Create course2.
 225          $course2 = $this->getDataGenerator()->create_course();
 226          $coursecontext2 = context_course::instance($course2->id);
 227  
 228          $userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
 229          provider::get_users_in_context($userlist1);
 230          $this->assertCount(0, $userlist1);
 231  
 232          $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
 233          provider::get_users_in_context($userlist2);
 234          $this->assertCount(0, $userlist2);
 235  
 236          $this->create_stats($course1->id, $user1->id, 'stats_user_daily');
 237          $this->create_stats($course2->id, $user1->id, 'stats_user_monthly');
 238          $this->create_stats($course1->id, $user2->id, 'stats_user_weekly');
 239  
 240          // The list of users within the course context should contain users.
 241          provider::get_users_in_context($userlist1);
 242          $this->assertCount(2, $userlist1);
 243          $this->assertTrue(in_array($user1->id, $userlist1->get_userids()));
 244          $this->assertTrue(in_array($user2->id, $userlist1->get_userids()));
 245  
 246          provider::get_users_in_context($userlist2);
 247          $this->assertCount(1, $userlist2);
 248          $this->assertTrue(in_array($user1->id, $userlist2->get_userids()));
 249  
 250          // The list of users within other contexts than course should be empty.
 251          $systemcontext = context_system::instance();
 252          $userlist3 = new \core_privacy\local\request\userlist($systemcontext, $component);
 253          provider::get_users_in_context($userlist3);
 254          $this->assertCount(0, $userlist3);
 255      }
 256  
 257      /**
 258       * Test that data for users in approved userlist is deleted.
 259       */
 260      public function test_delete_data_for_users() {
 261          $this->resetAfterTest();
 262  
 263          $component = 'report_stats';
 264  
 265          // Create user1.
 266          $user1 = $this->getDataGenerator()->create_user();
 267          // Create user2.
 268          $user2 = $this->getDataGenerator()->create_user();
 269          // Create user3.
 270          $user3 = $this->getDataGenerator()->create_user();
 271          // Create course1.
 272          $course1 = $this->getDataGenerator()->create_course();
 273          $coursecontext1 = context_course::instance($course1->id);
 274          // Create course2.
 275          $course2 = $this->getDataGenerator()->create_course();
 276          $coursecontext2 = context_course::instance($course2->id);
 277  
 278          $this->create_stats($course1->id, $user1->id, 'stats_user_daily');
 279          $this->create_stats($course2->id, $user1->id, 'stats_user_monthly');
 280          $this->create_stats($course1->id, $user2->id, 'stats_user_weekly');
 281          $this->create_stats($course1->id, $user3->id, 'stats_user_weekly');
 282  
 283          $userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
 284          provider::get_users_in_context($userlist1);
 285          $this->assertCount(3, $userlist1);
 286  
 287          $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
 288          provider::get_users_in_context($userlist2);
 289          $this->assertCount(1, $userlist2);
 290  
 291          // Convert $userlist1 into an approved_contextlist.
 292          $approvedlist1 = new approved_userlist($coursecontext1, $component, [$user1->id, $user2->id]);
 293          // Delete using delete_data_for_user.
 294          provider::delete_data_for_users($approvedlist1);
 295  
 296          // Re-fetch users in coursecontext1.
 297          $userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
 298          provider::get_users_in_context($userlist1);
 299          // The approved user data in coursecontext1 should be deleted.
 300          // The user list should still return user3.
 301          $this->assertCount(1, $userlist1);
 302          $this->assertTrue(in_array($user3->id, $userlist1->get_userids()));
 303          // Re-fetch users in coursecontext2.
 304          $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
 305          provider::get_users_in_context($userlist2);
 306          // The user data in coursecontext2 should be still present.
 307          $this->assertCount(1, $userlist2);
 308  
 309          // Convert $userlist2 into an approved_contextlist in the system context.
 310          $systemcontext = context_system::instance();
 311          $approvedlist2 = new approved_userlist($systemcontext, $component, $userlist2->get_userids());
 312          // Delete using delete_data_for_user.
 313          provider::delete_data_for_users($approvedlist2);
 314          // Re-fetch users in coursecontext2.
 315          $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
 316          provider::get_users_in_context($userlist2);
 317          // The user data in systemcontext should not be deleted.
 318          $this->assertCount(1, $userlist2);
 319      }
 320  }