on-demand release 3.9dev+
[moodle.git] / contentbank / tests / privacy_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  * Base class for unit tests for core_contentbank.
19  *
20  * @package    core_contentbank
21  * @category   test
22  * @copyright  2020 Carlos Escobedo <carlos@moodle.com>
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 namespace core_contentbank;
28 use stdClass;
29 use context_system;
30 use context_coursecat;
31 use context_course;
32 use core_contentbank\privacy\provider;
33 use core_privacy\local\request\approved_contextlist;
34 use core_privacy\local\request\writer;
35 use core_privacy\tests\provider_testcase;
36 use core_privacy\local\request\userlist;
37 use core_privacy\local\request\approved_userlist;
39 /**
40  * Unit tests for contentbank\classes\privacy\provider.php
41  *
42  * @copyright  2020 Carlos Escobedo <carlos@moodle.com>
43  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44  */
45 class core_contentbank_privacy_testcase extends provider_testcase {
47     /**
48      * Setup to ensure that fixtures are loaded.
49      */
50     public static function setupBeforeClass(): void {
51         global $CFG;
52         require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
53     }
55     /**
56      * Test for provider::get_contexts_for_userid().
57      */
58     public function test_get_contexts_for_userid() {
60         $this->resetAfterTest();
61         // Setup scenario.
62         $scenario = $this->setup_scenario();
64         // Testing againts Manager who has content in the three contexts.
65         $contextlist = provider::get_contexts_for_userid($scenario->manager->id);
66         // There are three contexts in the list.
67         $contextlistids = $contextlist->get_contextids();
68         $this->assertCount(3, $contextlistids);
69         // Check the list against the expected list of contexts.
70         $this->assertContains($scenario->systemcontext->id, $contextlistids);
71         $this->assertContains($scenario->coursecategorycontext->id,
72             $contextlistids);
73         $this->assertContains($scenario->coursecontext->id, $contextlistids);
75         // Testing againts Teacher who has content in the one context.
76         $contextlist = provider::get_contexts_for_userid($scenario->teacher->id);
77         // There are only one context in the list.
78         $contextlistids = $contextlist->get_contextids();
79         $this->assertCount(1, $contextlistids);
80         // Check the againts Course Context.
81         $this->assertContains($scenario->coursecontext->id, $contextlistids);
82         // And there is not a System and Course Category Context.
83         $this->assertNotContains($scenario->systemcontext->id, $contextlistids);
84         $this->assertNotContains($scenario->coursecategorycontext->id, $contextlistids);
85     }
87     /**
88      * Test for provider::get_users_in_context().
89      */
90     public function test_get_users_in_context() {
92         $this->resetAfterTest();
93         // Setup scenario.
94         $scenario = $this->setup_scenario();
96         // Get the userlist to Context System, only Manager will be there.
97         $userlist = new userlist($scenario->systemcontext, 'core_contentbank');
98         provider::get_users_in_context($userlist);
99         $this->assertEquals([$scenario->manager->id], $userlist->get_userids());
100         // Teacher will not be there.
101         $this->assertNotEquals([$scenario->teacher->id], $userlist->get_userids());
103         // Get the userlist to Context Course, Manager and Teacher will be there.
104         $userlist = new userlist($scenario->coursecontext, 'core_contentbank');
105         provider::get_users_in_context($userlist);
107         $expected = [$scenario->manager->id, $scenario->teacher->id];
108         sort($expected);
109         $actual = $userlist->get_userids();
110         sort($actual);
111         $this->assertEquals($expected, $actual);
112     }
114     /**
115      * Test for provider::test_export_user_data().
116      */
117     public function test_export_user_data() {
119         $this->resetAfterTest();
120         // Setup scenario.
121         $scenario = $this->setup_scenario();
123         $subcontexts = [
124             get_string('name', 'core_contentbank')
125         ];
126         // Get the data for the System Context.
127         $writer = writer::with_context($scenario->systemcontext);
128         $this->assertFalse($writer->has_any_data());
129         // Export data for Manager.
130         $this->export_context_data_for_user($scenario->manager->id,
131             $scenario->systemcontext, 'core_contentbank');
132         $data = $writer->get_data($subcontexts);
133         $this->assertCount(3, (array) $data);
134         $this->assertCount(3, $writer->get_files($subcontexts));
136         // Get the data for the Course Categoy Context.
137         $writer = writer::with_context($scenario->coursecategorycontext);
138         // Export data for Manager.
139         $this->export_context_data_for_user($scenario->manager->id,
140             $scenario->coursecategorycontext, 'core_contentbank');
141         $data = $writer->get_data($subcontexts);
142         $this->assertCount(2, (array) $data);
143         $this->assertCount(2, $writer->get_files($subcontexts));
145         // Get the data for the Course Context.
146         $writer = writer::with_context($scenario->coursecontext);
147         // Export data for Manager.
148         $this->export_context_data_for_user($scenario->manager->id,
149             $scenario->coursecontext, 'core_contentbank');
150         $data = $writer->get_data($subcontexts);
151         $this->assertCount(2, (array) $data);
152         $this->assertCount(2, $writer->get_files($subcontexts));
154         // Export data for Teacher.
155         $writer = writer::reset();
156         $writer = writer::with_context($scenario->coursecontext);
157         $this->export_context_data_for_user($scenario->teacher->id,
158             $scenario->coursecontext, 'core_contentbank');
159         $data = $writer->get_data($subcontexts);
160         $this->assertCount(3, (array) $data);
161         $this->assertCount(3, $writer->get_files($subcontexts));
162     }
164     /**
165      * Test for provider::delete_data_for_all_users_in_context().
166      */
167     public function test_delete_data_for_all_users_in_context() {
168         global $DB;
170         $this->resetAfterTest();
171         // Setup scenario.
172         $scenario = $this->setup_scenario();
174         // Before delete data, we have 4 contents.
175         // - 3 in a system context.
176         // - 2 in a course category context.
177         // - 5 in a course context (2 by manager and 3 by teacher).
179         // Delete data based on system context.
180         provider::delete_data_for_all_users_in_context($scenario->systemcontext);
181         $count = $DB->count_records('contentbank_content');
182         // 3 content should be deleted.
183         // 7 contents should be remain.
184         $this->assertEquals(7, $count);
186         // Delete data based on course category context.
187         provider::delete_data_for_all_users_in_context($scenario->coursecategorycontext);
188         $count = $DB->count_records('contentbank_content');
189         // 2 contents should be deleted.
190         // 5 content should be remain.
191         $this->assertEquals(5, $count);
193         // Delete data based on course context.
194         provider::delete_data_for_all_users_in_context($scenario->coursecontext);
195          $count = $DB->count_records('contentbank_content');
196         // 5 content should be deleted.
197         // 0 content should be remain.
198         $this->assertEquals(0, $count);
199     }
201     /**
202      * Test for provider::test_delete_data_for_users().
203      */
204     public function test_delete_data_for_users() {
205         global $DB;
207         $this->resetAfterTest();
208         // Setup scenario.
209         $scenario = $this->setup_scenario();
211         // Before delete data, we have 4 contents.
212         // - 3 in a system context.
213         // - 2 in a course category context.
214         // - 5 in a course context (2 by manager and 3 by teacher).
216         // A list of users who has created content in Course Category Context.
217         $userlist1 = new userlist($scenario->coursecategorycontext,
218             'core_contentbank');
219         provider::get_users_in_context($userlist1);
220         $this->assertCount(1, $userlist1);
221         // Only Manager should be.
222         $this->assertEquals([$scenario->manager->id], $userlist1->get_userids());
224         // A list of users who has created content in Course Context.
225         $userlist2 = new userlist($scenario->coursecontext, 'core_contentbank');
226         provider::get_users_in_context($userlist2);
227         $this->assertCount(2, $userlist2);
229         // Manager and Teacher should be.
230         $expected = [$scenario->manager->id, $scenario->teacher->id];
231         sort($expected);
232         $actual = $userlist2->get_userids();
233         sort($actual);
234         $this->assertEquals($expected, $actual);
236         // Convert $userlist1 into an approved_contextlist.
237         $approvedlist1 = new approved_userlist($scenario->coursecategorycontext, 'core_contentbank', $userlist1->get_userids());
238         // Delete data for users in course category context.
239         provider::delete_data_for_users($approvedlist1);
241         // Re-fetch users in course category context.
242         $userlist1 = new userlist($scenario->coursecategorycontext,
243             'core_contentbank');
244         provider::get_users_in_context($userlist1);
245         // The user data in course category context should be deleted.
246         $this->assertCount(0, $userlist1);
247         // Re-fetch users in course category context.
248         $userlist2 = new userlist($scenario->coursecontext, 'core_contentbank');
249         provider::get_users_in_context($userlist2);
250         // The user data in course context should be still present.
251         $this->assertCount(2, $userlist2);
253         // Convert $userlist2 into an approved_contextlist.
254         $approvedlist2 = new approved_userlist($scenario->coursecontext,
255             'core_contentbank', $userlist2->get_userids());
256         // Delete data for users in course context.
257         provider::delete_data_for_users($approvedlist2);
258         $userlist2 = new userlist($scenario->coursecontext, 'core_contentbank');
259         provider::get_users_in_context($userlist2);
260         // The user data in course context should be deleted.
261         $this->assertCount(0, $userlist2);
262     }
264     /**
265      * Test for provider::delete_data_for_user().
266      */
267     public function test_delete_data_for_user() {
268          global $DB;
270         $this->resetAfterTest();
271         // Setup scenario.
272         $scenario = $this->setup_scenario();
274         // Before delete data, we have 4 contents.
275         // - 3 in a system context.
276         // - 2 in a course category context.
277         // - 5 in a course context (2 by manager and 3 by teacher).
279         // Get all the context for Manager.
280         $contextlist = provider::get_contexts_for_userid($scenario->manager->id);
281         $approvedcontextlist = new approved_contextlist($scenario->manager,
282             'core_contentbank', $contextlist->get_contextids());
283         // Delete all the data created by the Manager in all the contexts.
284         provider::delete_data_for_user($approvedcontextlist);
286         // After deletion, only 3 content for teacher should be present.
287         $count = $DB->count_records('contentbank_content');
288         $this->assertEquals(3, $count);
290         // Confirm that the remaining content was created by the teacher.
291         $count = $DB->count_records('contentbank_content',
292             ['usercreated' => $scenario->teacher->id]);
293         $this->assertEquals(3, $count);
295         // Get all the context for Teacher.
296         $contextlist = provider::get_contexts_for_userid($scenario->teacher->id);
297         $approvedcontextlist = new approved_contextlist($scenario->teacher,
298             'core_contentbank', $contextlist->get_contextids());
299         // Delete all the data created by the Teacher in all the contexts.
300         provider::delete_data_for_user($approvedcontextlist);
302         // After deletion, no content should be present.
303         $count = $DB->count_records('contentbank_content');
304         $this->assertEquals(0, $count);
305     }
307     /**
308      * Create a complex scenario to use into the tests.
309      *
310      * @return stdClass $scenario
311      */
312     protected function setup_scenario() {
313         global $DB;
315         $systemcontext = context_system::instance();
316         $manager = $this->getDataGenerator()->create_user();
317         $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
318         $this->getDataGenerator()->role_assign($managerroleid, $manager->id);
320         $coursecategory = $this->getDataGenerator()->create_category();
321         $coursecategorycontext = context_coursecat::instance($coursecategory->id);
323         $course = $this->getDataGenerator()->create_course();
324         $coursecontext = context_course::instance($course->id);
325         $teacher = $this->getDataGenerator()->create_and_enrol($course,
326             'editingteacher');
328         // Add some content to the content bank.
329         $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
330         // Add contents by Manager in Context System.
331         $records = $generator->generate_contentbank_data('contenttype_testable',
332             1, $manager->id, $systemcontext, false, 'systemtestfile1.h5p');
333         $records = $generator->generate_contentbank_data('contenttype_testable',
334             1, $manager->id, $systemcontext, false, 'systemtestfile2.h5p');
335         $records = $generator->generate_contentbank_data('contenttype_testable',
336             1, $manager->id, $systemcontext, false, 'systemtestfile3.h5p');
337         // Add contents by Manager in Context Course Category.
338         $records = $generator->generate_contentbank_data('contenttype_testable',
339             1, $manager->id, $coursecategorycontext, false, 'coursecattestfile1.h5p');
340         $records = $generator->generate_contentbank_data('contenttype_testable',
341             1, $manager->id, $coursecategorycontext, false, 'coursecattestfile2.h5p');
342         // Add contents by Manager in Context Course.
343         $records = $generator->generate_contentbank_data('contenttype_testable',
344             1, $manager->id, $coursecontext, false, 'coursetestfile1.h5p');
345         $records = $generator->generate_contentbank_data('contenttype_testable',
346             1, $manager->id, $coursecontext, false, 'coursetestfile2.h5p');
347         // Add contents by Teacher.
348         $records = $generator->generate_contentbank_data('contenttype_testable',
349             1, $teacher->id, $coursecontext, false, 'courseteacherfile1.h5p');
350         $records = $generator->generate_contentbank_data('contenttype_testable',
351             1, $teacher->id, $coursecontext, false, 'courseteacherfile2.h5p');
352         $records = $generator->generate_contentbank_data('contenttype_testable',
353             1, $teacher->id, $coursecontext, false, 'courseteacherfile3.h5p');
355         $scenario = new stdClass();
356         $scenario->systemcontext = $systemcontext;
357         $scenario->coursecategorycontext = $coursecategorycontext;
358         $scenario->coursecontext = $coursecontext;
359         $scenario->manager = $manager;
360         $scenario->teacher = $teacher;
362         return $scenario;
363     }