Search moodle.org's
Developer Documentation

See Release Notes

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

Differences Between: [Versions 39 and 310]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * Privacy provider tests.
  19   *
  20   * @package    mod_data
  21   * @copyright  2018 Marina Glancy
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  use core_privacy\local\metadata\collection;
  26  use core_privacy\local\request\approved_userlist;
  27  use mod_data\privacy\provider;
  28  
  29  defined('MOODLE_INTERNAL') || die();
  30  
  31  /**
  32   * Privacy provider tests class.
  33   *
  34   * @package    mod_data
  35   * @copyright  2018 Marina Glancy
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class mod_data_privacy_provider_testcase extends \core_privacy\tests\provider_testcase {
  39      /** @var stdClass The student object. */
  40      protected $student;
  41      /** @var stdClass The student object. */
  42      protected $student2;
  43      /** @var stdClass The student object. */
  44      protected $student3;
  45  
  46      /** @var stdClass The data object. */
  47      protected $datamodule;
  48  
  49      /** @var stdClass The course object. */
  50      protected $course;
  51  
  52      /**
  53       * {@inheritdoc}
  54       */
  55      protected function setUp(): void {
  56          $this->resetAfterTest();
  57  
  58          global $DB;
  59          $generator = $this->getDataGenerator();
  60          $course = $generator->create_course();
  61          $params = [
  62              'course' => $course->id,
  63              'name' => 'Database module',
  64              'comments' => 1,
  65              'assessed' => 1,
  66          ];
  67  
  68          // The database activity.
  69          $datamodule = $this->get_generator()->create_instance($params);
  70  
  71          $fieldtypes = array('checkbox', 'date', 'menu', 'multimenu', 'number', 'radiobutton', 'text', 'textarea', 'url',
  72              'latlong', 'file', 'picture');
  73          // Creating test Fields with default parameter values.
  74          foreach ($fieldtypes as $count => $fieldtype) {
  75              // Creating variables dynamically.
  76              $fieldname = 'field' . $count;
  77              $record = new \stdClass();
  78              $record->name = $fieldname;
  79              $record->description = $fieldname . ' descr';
  80              $record->type = $fieldtype;
  81  
  82              ${$fieldname} = $this->get_generator()->create_field($record, $datamodule);
  83          }
  84  
  85          $cm = get_coursemodule_from_instance('data', $datamodule->id);
  86  
  87          // Create a student.
  88          $student1 = $generator->create_user();
  89          $student2 = $generator->create_user();
  90          $student3 = $generator->create_user();
  91          $studentrole = $DB->get_record('role', ['shortname' => 'student']);
  92          $generator->enrol_user($student1->id,  $course->id, $studentrole->id);
  93          $generator->enrol_user($student2->id,  $course->id, $studentrole->id);
  94          $generator->enrol_user($student3->id,  $course->id, $studentrole->id);
  95  
  96          // Add records.
  97          $this->setUser($student1);
  98          $record1id = $this->generate_data_record($datamodule);
  99          $this->generate_data_record($datamodule);
 100  
 101          $this->setUser($student2);
 102          $this->generate_data_record($datamodule);
 103          $this->generate_data_record($datamodule);
 104          $this->generate_data_record($datamodule);
 105  
 106          $this->setUser($student3);
 107          $this->generate_data_record($datamodule);
 108  
 109          $this->student = $student1;
 110          $this->student2 = $student2;
 111          $this->student3 = $student3;
 112          $this->datamodule = $datamodule;
 113          $this->course = $course;
 114      }
 115  
 116      /**
 117       * Get mod_data generator
 118       *
 119       * @return mod_data_generator
 120       */
 121      protected function get_generator() {
 122          return $this->getDataGenerator()->get_plugin_generator('mod_data');
 123      }
 124  
 125      /**
 126       * Generates one record in the database module as the current student
 127       *
 128       * @param stdClass $datamodule
 129       * @return mixed
 130       */
 131      protected function generate_data_record($datamodule) {
 132          global $DB;
 133  
 134          static $counter = 0;
 135          $counter++;
 136  
 137          $contents = array();
 138          $contents[] = array('opt1', 'opt2', 'opt3', 'opt4');
 139          $contents[] = sprintf("%02f", $counter) . '-01-2000';
 140          $contents[] = 'menu1';
 141          $contents[] = array('multimenu1', 'multimenu2', 'multimenu3', 'multimenu4');
 142          $contents[] = 5 * $counter;
 143          $contents[] = 'radioopt1';
 144          $contents[] = 'text for testing' . $counter;
 145          $contents[] = "<p>text area testing $counter<br /></p>";
 146          $contents[] = array('example.url', 'sampleurl' . $counter);
 147          $contents[] = [-31.9489873, 115.8382036]; // Latlong.
 148          $contents[] = "Filename{$counter}.pdf"; // File - filename.
 149          $contents[] = array("Cat{$counter}.jpg", 'Cat' . $counter); // Picture - filename with alt text.
 150          $count = 0;
 151          $fieldcontents = array();
 152          $fields = $DB->get_records('data_fields', array('dataid' => $datamodule->id), 'id');
 153          foreach ($fields as $fieldrecord) {
 154              $fieldcontents[$fieldrecord->id] = $contents[$count++];
 155          }
 156          $tags = ['Cats', 'mice' . $counter];
 157          return $this->get_generator()->create_entry($datamodule, $fieldcontents, 0, $tags);
 158      }
 159  
 160      /**
 161       * Test for provider::get_metadata().
 162       */
 163      public function test_get_metadata() {
 164          $collection = new collection('mod_data');
 165          $newcollection = provider::get_metadata($collection);
 166          $itemcollection = $newcollection->get_collection();
 167          $this->assertCount(7, $itemcollection);
 168  
 169          $table = reset($itemcollection);
 170          $this->assertEquals('data_records', $table->get_name());
 171  
 172          $table = next($itemcollection);
 173          $this->assertEquals('data_content', $table->get_name());
 174      }
 175  
 176      /**
 177       * Test for provider::get_contexts_for_userid().
 178       */
 179      public function test_get_contexts_for_userid() {
 180          $cm = get_coursemodule_from_instance('data', $this->datamodule->id);
 181  
 182          $contextlist = provider::get_contexts_for_userid($this->student->id);
 183          $this->assertCount(1, $contextlist);
 184          $contextforuser = $contextlist->current();
 185          $cmcontext = context_module::instance($cm->id);
 186          $this->assertEquals($cmcontext->id, $contextforuser->id);
 187      }
 188  
 189      /**
 190       * Test for provider::get_users_in_context().
 191       */
 192      public function test_get_users_in_context() {
 193          $component = 'mod_data';
 194          $cm = get_coursemodule_from_instance('data', $this->datamodule->id);
 195          $cmcontext = context_module::instance($cm->id);
 196  
 197          $userlist = new \core_privacy\local\request\userlist($cmcontext, $component);
 198          provider::get_users_in_context($userlist);
 199  
 200          $this->assertCount(3, $userlist);
 201  
 202          $expected = [$this->student->id, $this->student2->id, $this->student3->id];
 203          $actual = $userlist->get_userids();
 204          sort($expected);
 205          sort($actual);
 206  
 207          $this->assertEquals($expected, $actual);
 208      }
 209  
 210      /**
 211       * Get test privacy writer
 212       *
 213       * @param context $context
 214       * @return \core_privacy\tests\request\content_writer
 215       */
 216      protected function get_writer($context) {
 217          return \core_privacy\local\request\writer::with_context($context);
 218      }
 219  
 220      /**
 221       * Test for provider::export_user_data().
 222       */
 223      public function test_export_for_context() {
 224          global $DB;
 225          $cm = get_coursemodule_from_instance('data', $this->datamodule->id);
 226          $cmcontext = context_module::instance($cm->id);
 227          $records = $DB->get_records_select('data_records', 'userid = :userid ORDER BY id', ['userid' => $this->student->id]);
 228          $record = reset($records);
 229          $contents = $DB->get_records('data_content', ['recordid' => $record->id]);
 230  
 231          // Export all of the data for the context.
 232          $this->export_context_data_for_user($this->student->id, $cmcontext, 'mod_data');
 233          $writer = $this->get_writer($cmcontext);
 234          $data = $writer->get_data([$record->id]);
 235          $this->assertNotEmpty($data);
 236          foreach ($contents as $content) {
 237              $data = $writer->get_data([$record->id, $content->id]);
 238              $this->assertNotEmpty($data);
 239              $hasfile = in_array($data->field['type'], ['file', 'picture']);
 240              $this->assertEquals($hasfile, !empty($writer->get_files([$record->id, $content->id])));
 241          }
 242          $tags = $writer->get_related_data([$record->id], 'tags');
 243          $this->assertNotEmpty($tags);
 244      }
 245  
 246      /**
 247       * Test for provider::delete_data_for_all_users_in_context().
 248       */
 249      public function test_delete_data_for_all_users_in_context() {
 250          $cm = get_coursemodule_from_instance('data', $this->datamodule->id);
 251          $cmcontext = context_module::instance($cm->id);
 252  
 253          provider::delete_data_for_all_users_in_context($cmcontext);
 254  
 255          $appctxt = new \core_privacy\local\request\approved_contextlist($this->student, 'mod_data', [$cmcontext->id]);
 256          provider::export_user_data($appctxt);
 257          $this->assertFalse($this->get_writer($cmcontext)->has_any_data());
 258      }
 259  
 260      /**
 261       * Test for provider::delete_data_for_user().
 262       */
 263      public function test_delete_data_for_user() {
 264          $cm = get_coursemodule_from_instance('data', $this->datamodule->id);
 265          $cmcontext = context_module::instance($cm->id);
 266  
 267          $appctxt = new \core_privacy\local\request\approved_contextlist($this->student, 'mod_data', [$cmcontext->id]);
 268          provider::delete_data_for_user($appctxt);
 269  
 270          provider::export_user_data($appctxt);
 271          $this->assertFalse($this->get_writer($cmcontext)->has_any_data());
 272      }
 273  
 274      /**
 275       * Test for provider::delete_data_for_users().
 276       */
 277      public function test_delete_data_for_users() {
 278          $cm = get_coursemodule_from_instance('data', $this->datamodule->id);
 279          $cmcontext = context_module::instance($cm->id);
 280          $userstodelete = [$this->student->id, $this->student2->id];
 281  
 282          // Ensure student, student 2 and student 3 have data before being deleted.
 283          $appctxt = new \core_privacy\local\request\approved_contextlist($this->student, 'mod_data', [$cmcontext->id]);
 284          provider::export_user_data($appctxt);
 285          $this->assertTrue($this->get_writer($cmcontext)->has_any_data());
 286  
 287          $appctxt = new \core_privacy\local\request\approved_contextlist($this->student2, 'mod_data', [$cmcontext->id]);
 288          provider::export_user_data($appctxt);
 289          $this->assertTrue($this->get_writer($cmcontext)->has_any_data());
 290  
 291          // Delete data for student 1 and 2.
 292          $approvedlist = new approved_userlist($cmcontext, 'mod_data', $userstodelete);
 293          provider::delete_data_for_users($approvedlist);
 294  
 295          // Reset the writer so it doesn't contain the data from before deletion.
 296          \core_privacy\local\request\writer::reset();
 297  
 298          // Ensure data is now deleted for student and student 2.
 299          $appctxt = new \core_privacy\local\request\approved_contextlist($this->student, 'mod_data', [$cmcontext->id]);
 300          provider::export_user_data($appctxt);
 301  
 302          $this->assertFalse($this->get_writer($cmcontext)->has_any_data());
 303  
 304          $appctxt = new \core_privacy\local\request\approved_contextlist($this->student2, 'mod_data', [$cmcontext->id]);
 305          provider::export_user_data($appctxt);
 306  
 307          $this->assertFalse($this->get_writer($cmcontext)->has_any_data());
 308  
 309          // Ensure data still intact for student 3.
 310          $appctxt = new \core_privacy\local\request\approved_contextlist($this->student3, 'mod_data', [$cmcontext->id]);
 311          provider::export_user_data($appctxt);
 312  
 313          $this->assertTrue($this->get_writer($cmcontext)->has_any_data());
 314      }
 315  }