MDL-63665 mod_choice: support removal of multiple users in a context
[moodle.git] / mod / choice / 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_choice
21  * @copyright  2018 Jun Pataleta
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\deletion_criteria;
27 use mod_choice\privacy\provider;
29 defined('MOODLE_INTERNAL') || die();
31 /**
32  * Privacy provider tests class.
33  *
34  * @package    mod_choice
35  * @copyright  2018 Jun Pataleta
36  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class mod_choice_privacy_provider_testcase extends \core_privacy\tests\provider_testcase {
39     /** @var stdClass The student object. */
40     protected $student;
42     /** @var stdClass The choice object. */
43     protected $choice;
45     /** @var stdClass The course object. */
46     protected $course;
48     /**
49      * {@inheritdoc}
50      */
51     protected function setUp() {
52         $this->resetAfterTest();
54         global $DB;
55         $generator = $this->getDataGenerator();
56         $course = $generator->create_course();
57         $options = ['fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza'];
58         $params = [
59             'course' => $course->id,
60             'option' => $options,
61             'name' => 'First Choice Activity',
62             'showpreview' => 0
63         ];
65         $plugingenerator = $generator->get_plugin_generator('mod_choice');
66         // The choice activity the user will answer.
67         $choice = $plugingenerator->create_instance($params);
68         // Create another choice activity.
69         $plugingenerator->create_instance($params);
70         $cm = get_coursemodule_from_instance('choice', $choice->id);
72         // Create a student which will make a choice.
73         $student = $generator->create_user();
74         $studentrole = $DB->get_record('role', ['shortname' => 'student']);
75         $generator->enrol_user($student->id,  $course->id, $studentrole->id);
77         $choicewithoptions = choice_get_choice($choice->id);
78         $optionids = array_keys($choicewithoptions->option);
80         choice_user_submit_response($optionids[2], $choice, $student->id, $course, $cm);
81         $this->student = $student;
82         $this->choice = $choice;
83         $this->course = $course;
84     }
86     /**
87      * Test for provider::get_metadata().
88      */
89     public function test_get_metadata() {
90         $collection = new collection('mod_choice');
91         $newcollection = provider::get_metadata($collection);
92         $itemcollection = $newcollection->get_collection();
93         $this->assertCount(1, $itemcollection);
95         $table = reset($itemcollection);
96         $this->assertEquals('choice_answers', $table->get_name());
98         $privacyfields = $table->get_privacy_fields();
99         $this->assertArrayHasKey('choiceid', $privacyfields);
100         $this->assertArrayHasKey('optionid', $privacyfields);
101         $this->assertArrayHasKey('userid', $privacyfields);
102         $this->assertArrayHasKey('timemodified', $privacyfields);
104         $this->assertEquals('privacy:metadata:choice_answers', $table->get_summary());
105     }
107     /**
108      * Test for provider::get_contexts_for_userid().
109      */
110     public function test_get_contexts_for_userid() {
111         $cm = get_coursemodule_from_instance('choice', $this->choice->id);
113         $contextlist = provider::get_contexts_for_userid($this->student->id);
114         $this->assertCount(1, $contextlist);
115         $contextforuser = $contextlist->current();
116         $cmcontext = context_module::instance($cm->id);
117         $this->assertEquals($cmcontext->id, $contextforuser->id);
118     }
120     /**
121      * Test for provider::export_user_data().
122      */
123     public function test_export_for_context() {
124         $cm = get_coursemodule_from_instance('choice', $this->choice->id);
125         $cmcontext = context_module::instance($cm->id);
127         // Export all of the data for the context.
128         $this->export_context_data_for_user($this->student->id, $cmcontext, 'mod_choice');
129         $writer = \core_privacy\local\request\writer::with_context($cmcontext);
130         $this->assertTrue($writer->has_any_data());
131     }
133     /**
134      * Test for provider::delete_data_for_all_users_in_context().
135      */
136     public function test_delete_data_for_all_users_in_context() {
137         global $DB;
139         $choice = $this->choice;
140         $generator = $this->getDataGenerator();
141         $cm = get_coursemodule_from_instance('choice', $this->choice->id);
143         // Create another student who will answer the choice activity.
144         $student = $generator->create_user();
145         $studentrole = $DB->get_record('role', ['shortname' => 'student']);
146         $generator->enrol_user($student->id, $this->course->id, $studentrole->id);
148         $choicewithoptions = choice_get_choice($choice->id);
149         $optionids = array_keys($choicewithoptions->option);
151         choice_user_submit_response($optionids[1], $choice, $student->id, $this->course, $cm);
153         // Before deletion, we should have 2 responses.
154         $count = $DB->count_records('choice_answers', ['choiceid' => $choice->id]);
155         $this->assertEquals(2, $count);
157         // Delete data based on context.
158         $cmcontext = context_module::instance($cm->id);
159         provider::delete_data_for_all_users_in_context($cmcontext);
161         // After deletion, the choice answers for that choice activity should have been deleted.
162         $count = $DB->count_records('choice_answers', ['choiceid' => $choice->id]);
163         $this->assertEquals(0, $count);
164     }
166     /**
167      * Test for provider::delete_data_for_user().
168      */
169     public function test_delete_data_for_user_() {
170         global $DB;
172         $choice = $this->choice;
173         $generator = $this->getDataGenerator();
174         $cm1 = get_coursemodule_from_instance('choice', $this->choice->id);
176         // Create a second choice activity.
177         $options = ['Boracay', 'Camiguin', 'Bohol', 'Cebu', 'Coron'];
178         $params = [
179             'course' => $this->course->id,
180             'option' => $options,
181             'name' => 'Which do you think is the best island in the Philippines?',
182             'showpreview' => 0
183         ];
184         $plugingenerator = $generator->get_plugin_generator('mod_choice');
185         $choice2 = $plugingenerator->create_instance($params);
186         $plugingenerator->create_instance($params);
187         $cm2 = get_coursemodule_from_instance('choice', $choice2->id);
189         // Make a selection for the first student for the 2nd choice activity.
190         $choicewithoptions = choice_get_choice($choice2->id);
191         $optionids = array_keys($choicewithoptions->option);
192         choice_user_submit_response($optionids[2], $choice2, $this->student->id, $this->course, $cm2);
194         // Create another student who will answer the first choice activity.
195         $otherstudent = $generator->create_user();
196         $studentrole = $DB->get_record('role', ['shortname' => 'student']);
197         $generator->enrol_user($otherstudent->id, $this->course->id, $studentrole->id);
199         $choicewithoptions = choice_get_choice($choice->id);
200         $optionids = array_keys($choicewithoptions->option);
202         choice_user_submit_response($optionids[1], $choice, $otherstudent->id, $this->course, $cm1);
204         // Before deletion, we should have 2 responses.
205         $count = $DB->count_records('choice_answers', ['choiceid' => $choice->id]);
206         $this->assertEquals(2, $count);
208         $context1 = context_module::instance($cm1->id);
209         $context2 = context_module::instance($cm2->id);
210         $contextlist = new \core_privacy\local\request\approved_contextlist($this->student, 'choice',
211             [context_system::instance()->id, $context1->id, $context2->id]);
212         provider::delete_data_for_user($contextlist);
214         // After deletion, the choice answers for the first student should have been deleted.
215         $count = $DB->count_records('choice_answers', ['choiceid' => $choice->id, 'userid' => $this->student->id]);
216         $this->assertEquals(0, $count);
218         // Confirm that we only have one choice answer available.
219         $choiceanswers = $DB->get_records('choice_answers');
220         $this->assertCount(1, $choiceanswers);
221         $lastresponse = reset($choiceanswers);
222         // And that it's the other student's response.
223         $this->assertEquals($otherstudent->id, $lastresponse->userid);
224     }
226     /**
227      * Test for provider::get_users_in_context().
228      */
229     public function test_get_users_in_context() {
230         $cm = get_coursemodule_from_instance('choice', $this->choice->id);
231         $cmcontext = context_module::instance($cm->id);
233         $userlist = new \core_privacy\local\request\userlist($cmcontext, 'mod_choice');
234         \mod_choice\privacy\provider::get_users_in_context($userlist);
236         $this->assertEquals(
237                 [$this->student->id],
238                 $userlist->get_userids()
239         );
240     }
242     /**
243      * Test for provider::get_users_in_context() with invalid context type.
244      */
245     public function test_get_users_in_context_invalid_context_type() {
246         $systemcontext = context_system::instance();
248         $userlist = new \core_privacy\local\request\userlist($systemcontext, 'mod_choice');
249         \mod_choice\privacy\provider::get_users_in_context($userlist);
251         $this->assertCount(0, $userlist->get_userids());
252     }
254     /**
255      * Test for provider::delete_data_for_users().
256      */
257     public function test_delete_data_for_users() {
258         global $DB;
260         $choice = $this->choice;
261         $generator = $this->getDataGenerator();
262         $cm1 = get_coursemodule_from_instance('choice', $this->choice->id);
264         // Create a second choice activity.
265         $options = ['Boracay', 'Camiguin', 'Bohol', 'Cebu', 'Coron'];
266         $params = [
267             'course' => $this->course->id,
268             'option' => $options,
269             'name' => 'Which do you think is the best island in the Philippines?',
270             'showpreview' => 0
271         ];
272         $plugingenerator = $generator->get_plugin_generator('mod_choice');
273         $choice2 = $plugingenerator->create_instance($params);
274         $plugingenerator->create_instance($params);
275         $cm2 = get_coursemodule_from_instance('choice', $choice2->id);
277         // Make a selection for the first student for the 2nd choice activity.
278         $choicewithoptions = choice_get_choice($choice2->id);
279         $optionids = array_keys($choicewithoptions->option);
280         choice_user_submit_response($optionids[2], $choice2, $this->student->id, $this->course, $cm2);
282         // Create 2 other students who will answer the first choice activity.
283         $otherstudent = $generator->create_and_enrol($this->course, 'student');
284         $anotherstudent = $generator->create_and_enrol($this->course, 'student');
286         $choicewithoptions = choice_get_choice($choice->id);
287         $optionids = array_keys($choicewithoptions->option);
289         choice_user_submit_response($optionids[1], $choice, $otherstudent->id, $this->course, $cm1);
290         choice_user_submit_response($optionids[1], $choice, $anotherstudent->id, $this->course, $cm1);
292         // Before deletion, we should have 3 responses in the first choice activity.
293         $count = $DB->count_records('choice_answers', ['choiceid' => $choice->id]);
294         $this->assertEquals(3, $count);
296         $context1 = context_module::instance($cm1->id);
297         $approveduserlist = new \core_privacy\local\request\approved_userlist($context1, 'choice',
298                 [$this->student->id, $otherstudent->id]);
299         provider::delete_data_for_users($approveduserlist);
301         // After deletion, the choice answers of the 2 students provided above should have been deleted
302         // from the first choice activity. So there should only remain 1 answer which is for $anotherstudent.
303         $choiceanswers = $DB->get_records('choice_answers', ['choiceid' => $choice->id]);
304         $this->assertCount(1, $choiceanswers);
305         $lastresponse = reset($choiceanswers);
306         $this->assertEquals($anotherstudent->id, $lastresponse->userid);
308         // Confirm that the answer that was submitted in the other choice activity is intact.
309         $choiceanswers = $DB->get_records_select('choice_answers', 'choiceid <> ?', [$choice->id]);
310         $this->assertCount(1, $choiceanswers);
311         $lastresponse = reset($choiceanswers);
312         // And that it's for the choice2 activity.
313         $this->assertEquals($choice2->id, $lastresponse->choiceid);
314     }