MDL-63497 mod_data: Add support for removal of context users
[moodle.git] / mod / data / tests / privacy_provider_test.php
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/>.
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  */
25 use core_privacy\local\metadata\collection;
26 use core_privacy\local\request\approved_userlist;
27 use mod_data\privacy\provider;
29 defined('MOODLE_INTERNAL') || die();
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;
46     /** @var stdClass The data object. */
47     protected $datamodule;
49     /** @var stdClass The course object. */
50     protected $course;
52     /**
53      * {@inheritdoc}
54      */
55     protected function setUp() {
56         $this->resetAfterTest();
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         ];
68         // The database activity.
69         $datamodule = $this->get_generator()->create_instance($params);
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;
82             ${$fieldname} = $this->get_generator()->create_field($record, $datamodule);
83         }
85         $cm = get_coursemodule_from_instance('data', $datamodule->id);
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);
96         // Add records.
97         $this->setUser($student1);
98         $record1id = $this->generate_data_record($datamodule);
99         $this->generate_data_record($datamodule);
101         $this->setUser($student2);
102         $this->generate_data_record($datamodule);
103         $this->generate_data_record($datamodule);
104         $this->generate_data_record($datamodule);
106         $this->setUser($student3);
107         $this->generate_data_record($datamodule);
109         $this->student = $student1;
110         $this->student2 = $student2;
111         $this->student3 = $student3;
112         $this->datamodule = $datamodule;
113         $this->course = $course;
114     }
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     }
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;
134         static $counter = 0;
135         $counter++;
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     }
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);
169         $table = reset($itemcollection);
170         $this->assertEquals('data_records', $table->get_name());
172         $table = next($itemcollection);
173         $this->assertEquals('data_content', $table->get_name());
174     }
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);
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     }
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);
197         $userlist = new \core_privacy\local\request\userlist($cmcontext, $component);
198         provider::get_users_in_context($userlist);
200         $this->assertCount(3, $userlist);
202         $expected = [$this->student->id, $this->student2->id, $this->student3->id];
203         $actual = $userlist->get_userids();
204         sort($expected);
205         sort($actual);
207         $this->assertEquals($expected, $actual);
208     }
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     }
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]);
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     }
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);
253         provider::delete_data_for_all_users_in_context($cmcontext);
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     }
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);
267         $appctxt = new \core_privacy\local\request\approved_contextlist($this->student, 'mod_data', [$cmcontext->id]);
268         provider::delete_data_for_user($appctxt);
270         provider::export_user_data($appctxt);
271         $this->assertFalse($this->get_writer($cmcontext)->has_any_data());
272     }
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];
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());
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());
291         // Delete data for student 1 and 2.
292         $approvedlist = new approved_userlist($cmcontext, 'mod_data', $userstodelete);
293         provider::delete_data_for_users($approvedlist);
295         // Reset the writer so it doesn't contain the data from before deletion.
296         \core_privacy\local\request\writer::reset();
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);
302         $this->assertFalse($this->get_writer($cmcontext)->has_any_data());
304         $appctxt = new \core_privacy\local\request\approved_contextlist($this->student2, 'mod_data', [$cmcontext->id]);
305         provider::export_user_data($appctxt);
307         $this->assertFalse($this->get_writer($cmcontext)->has_any_data());
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);
313         $this->assertTrue($this->get_writer($cmcontext)->has_any_data());
314     }