MDL-68483 contentbank: improve search API
[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 defined('MOODLE_INTERNAL') || die();
30 use stdClass;
31 use context_system;
32 use context_coursecat;
33 use context_course;
34 use core_contentbank\privacy\provider;
35 use core_privacy\local\request\approved_contextlist;
36 use core_privacy\local\request\writer;
37 use core_privacy\tests\provider_testcase;
38 use core_privacy\local\request\userlist;
39 use core_privacy\local\request\approved_userlist;
41 /**
42  * Unit tests for contentbank\classes\privacy\provider.php
43  *
44  * @copyright  2020 Carlos Escobedo <carlos@moodle.com>
45  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
46  */
47 class core_contentbank_privacy_testcase extends provider_testcase {
49     /**
50      * Setup to ensure that fixtures are loaded.
51      */
52     public static function setupBeforeClass(): void {
53         global $CFG;
54         require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
55     }
57     /**
58      * Test for provider::get_contexts_for_userid().
59      */
60     public function test_get_contexts_for_userid() {
62         $this->resetAfterTest();
63         // Setup scenario.
64         $scenario = $this->setup_scenario();
66         // Testing againts Manager who has content in the three contexts.
67         $contextlist = provider::get_contexts_for_userid($scenario->manager->id);
68         // There are three contexts in the list.
69         $contextlistids = $contextlist->get_contextids();
70         $this->assertCount(3, $contextlistids);
71         // Check the list against the expected list of contexts.
72         $this->assertContains($scenario->systemcontext->id, $contextlistids);
73         $this->assertContains($scenario->coursecategorycontext->id,
74             $contextlistids);
75         $this->assertContains($scenario->coursecontext->id, $contextlistids);
77         // Testing againts Teacher who has content in the one context.
78         $contextlist = provider::get_contexts_for_userid($scenario->teacher->id);
79         // There are only one context in the list.
80         $contextlistids = $contextlist->get_contextids();
81         $this->assertCount(1, $contextlistids);
82         // Check the againts Course Context.
83         $this->assertContains($scenario->coursecontext->id, $contextlistids);
84         // And there is not a System and Course Category Context.
85         $this->assertNotContains($scenario->systemcontext->id, $contextlistids);
86         $this->assertNotContains($scenario->coursecategorycontext->id, $contextlistids);
87     }
89     /**
90      * Test for provider::get_users_in_context().
91      */
92     public function test_get_users_in_context() {
94         $this->resetAfterTest();
95         // Setup scenario.
96         $scenario = $this->setup_scenario();
98         // Get the userlist to Context System, only Manager will be there.
99         $userlist = new userlist($scenario->systemcontext, 'core_contentbank');
100         provider::get_users_in_context($userlist);
101         $this->assertEquals([$scenario->manager->id], $userlist->get_userids());
102         // Teacher will not be there.
103         $this->assertNotEquals([$scenario->teacher->id], $userlist->get_userids());
105         // Get the userlist to Context Course, Manager and Teacher will be there.
106         $userlist = new userlist($scenario->coursecontext, 'core_contentbank');
107         provider::get_users_in_context($userlist);
109         $expected = [$scenario->manager->id, $scenario->teacher->id];
110         sort($expected);
111         $actual = $userlist->get_userids();
112         sort($actual);
113         $this->assertEquals($expected, $actual);
114     }
116     /**
117      * Test for provider::test_export_user_data().
118      */
119     public function test_export_user_data() {
121         $this->resetAfterTest();
122         // Setup scenario.
123         $scenario = $this->setup_scenario();
125         $subcontexts = [
126             get_string('name', 'core_contentbank')
127         ];
128         // Get the data for the System Context.
129         $writer = writer::with_context($scenario->systemcontext);
130         $this->assertFalse($writer->has_any_data());
131         // Export data for Manager.
132         $this->export_context_data_for_user($scenario->manager->id,
133             $scenario->systemcontext, 'core_contentbank');
134         $data = $writer->get_data($subcontexts);
135         $this->assertCount(3, (array) $data);
136         $this->assertCount(3, $writer->get_files($subcontexts));
138         // Get the data for the Course Categoy Context.
139         $writer = writer::with_context($scenario->coursecategorycontext);
140         // Export data for Manager.
141         $this->export_context_data_for_user($scenario->manager->id,
142             $scenario->coursecategorycontext, 'core_contentbank');
143         $data = $writer->get_data($subcontexts);
144         $this->assertCount(2, (array) $data);
145         $this->assertCount(2, $writer->get_files($subcontexts));
147         // Get the data for the Course Context.
148         $writer = writer::with_context($scenario->coursecontext);
149         // Export data for Manager.
150         $this->export_context_data_for_user($scenario->manager->id,
151             $scenario->coursecontext, 'core_contentbank');
152         $data = $writer->get_data($subcontexts);
153         $this->assertCount(2, (array) $data);
154         $this->assertCount(2, $writer->get_files($subcontexts));
156         // Export data for Teacher.
157         $writer = writer::reset();
158         $writer = writer::with_context($scenario->coursecontext);
159         $this->export_context_data_for_user($scenario->teacher->id,
160             $scenario->coursecontext, 'core_contentbank');
161         $data = $writer->get_data($subcontexts);
162         $this->assertCount(3, (array) $data);
163         $this->assertCount(3, $writer->get_files($subcontexts));
164     }
166     /**
167      * Test for provider::delete_data_for_all_users_in_context().
168      */
169     public function test_delete_data_for_all_users_in_context() {
170         global $DB;
172         $this->resetAfterTest();
173         // Setup scenario.
174         $scenario = $this->setup_scenario();
176         // Before delete data, we have 4 contents.
177         // - 3 in a system context.
178         // - 2 in a course category context.
179         // - 5 in a course context (2 by manager and 3 by teacher).
181         // Delete data based on system context.
182         provider::delete_data_for_all_users_in_context($scenario->systemcontext);
183         $count = $DB->count_records('contentbank_content');
184         // 3 content should be deleted.
185         // 7 contents should be remain.
186         $this->assertEquals(7, $count);
188         // Delete data based on course category context.
189         provider::delete_data_for_all_users_in_context($scenario->coursecategorycontext);
190         $count = $DB->count_records('contentbank_content');
191         // 2 contents should be deleted.
192         // 5 content should be remain.
193         $this->assertEquals(5, $count);
195         // Delete data based on course context.
196         provider::delete_data_for_all_users_in_context($scenario->coursecontext);
197          $count = $DB->count_records('contentbank_content');
198         // 5 content should be deleted.
199         // 0 content should be remain.
200         $this->assertEquals(0, $count);
201     }
203     /**
204      * Test for provider::test_delete_data_for_users().
205      */
206     public function test_delete_data_for_users() {
207         global $DB;
209         $this->resetAfterTest();
210         // Setup scenario.
211         $scenario = $this->setup_scenario();
213         // Before delete data, we have 4 contents.
214         // - 3 in a system context.
215         // - 2 in a course category context.
216         // - 5 in a course context (2 by manager and 3 by teacher).
218         // A list of users who has created content in Course Category Context.
219         $userlist1 = new userlist($scenario->coursecategorycontext,
220             'core_contentbank');
221         provider::get_users_in_context($userlist1);
222         $this->assertCount(1, $userlist1);
223         // Only Manager should be.
224         $this->assertEquals([$scenario->manager->id], $userlist1->get_userids());
226         // A list of users who has created content in Course Context.
227         $userlist2 = new userlist($scenario->coursecontext, 'core_contentbank');
228         provider::get_users_in_context($userlist2);
229         $this->assertCount(2, $userlist2);
231         // Manager and Teacher should be.
232         $expected = [$scenario->manager->id, $scenario->teacher->id];
233         sort($expected);
234         $actual = $userlist2->get_userids();
235         sort($actual);
236         $this->assertEquals($expected, $actual);
238         // Convert $userlist1 into an approved_contextlist.
239         $approvedlist1 = new approved_userlist($scenario->coursecategorycontext, 'core_contentbank', $userlist1->get_userids());
240         // Delete data for users in course category context.
241         provider::delete_data_for_users($approvedlist1);
243         // Re-fetch users in course category context.
244         $userlist1 = new userlist($scenario->coursecategorycontext,
245             'core_contentbank');
246         provider::get_users_in_context($userlist1);
247         // The user data in course category context should be deleted.
248         $this->assertCount(0, $userlist1);
249         // Re-fetch users in course category context.
250         $userlist2 = new userlist($scenario->coursecontext, 'core_contentbank');
251         provider::get_users_in_context($userlist2);
252         // The user data in course context should be still present.
253         $this->assertCount(2, $userlist2);
255         // Convert $userlist2 into an approved_contextlist.
256         $approvedlist2 = new approved_userlist($scenario->coursecontext,
257             'core_contentbank', $userlist2->get_userids());
258         // Delete data for users in course context.
259         provider::delete_data_for_users($approvedlist2);
260         $userlist2 = new userlist($scenario->coursecontext, 'core_contentbank');
261         provider::get_users_in_context($userlist2);
262         // The user data in course context should be deleted.
263         $this->assertCount(0, $userlist2);
264     }
266     /**
267      * Test for provider::delete_data_for_user().
268      */
269     public function test_delete_data_for_user() {
270          global $DB;
272         $this->resetAfterTest();
273         // Setup scenario.
274         $scenario = $this->setup_scenario();
276         // Before delete data, we have 4 contents.
277         // - 3 in a system context.
278         // - 2 in a course category context.
279         // - 5 in a course context (2 by manager and 3 by teacher).
281         // Get all the context for Manager.
282         $contextlist = provider::get_contexts_for_userid($scenario->manager->id);
283         $approvedcontextlist = new approved_contextlist($scenario->manager,
284             'core_contentbank', $contextlist->get_contextids());
285         // Delete all the data created by the Manager in all the contexts.
286         provider::delete_data_for_user($approvedcontextlist);
288         // After deletion, only 3 content for teacher should be present.
289         $count = $DB->count_records('contentbank_content');
290         $this->assertEquals(3, $count);
292         // Confirm that the remaining content was created by the teacher.
293         $count = $DB->count_records('contentbank_content',
294             ['usercreated' => $scenario->teacher->id]);
295         $this->assertEquals(3, $count);
297         // Get all the context for Teacher.
298         $contextlist = provider::get_contexts_for_userid($scenario->teacher->id);
299         $approvedcontextlist = new approved_contextlist($scenario->teacher,
300             'core_contentbank', $contextlist->get_contextids());
301         // Delete all the data created by the Teacher in all the contexts.
302         provider::delete_data_for_user($approvedcontextlist);
304         // After deletion, no content should be present.
305         $count = $DB->count_records('contentbank_content');
306         $this->assertEquals(0, $count);
307     }
309     /**
310      * Create a complex scenario to use into the tests.
311      *
312      * @return stdClass $scenario
313      */
314     protected function setup_scenario() {
315         global $DB;
317         $systemcontext = context_system::instance();
318         $manager = $this->getDataGenerator()->create_user();
319         $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
320         $this->getDataGenerator()->role_assign($managerroleid, $manager->id);
322         $coursecategory = $this->getDataGenerator()->create_category();
323         $coursecategorycontext = context_coursecat::instance($coursecategory->id);
325         $course = $this->getDataGenerator()->create_course();
326         $coursecontext = context_course::instance($course->id);
327         $teacher = $this->getDataGenerator()->create_and_enrol($course,
328             'editingteacher');
330         // Add some content to the content bank.
331         $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
332         // Add contents by Manager in Context System.
333         $records = $generator->generate_contentbank_data('contenttype_testable',
334             1, $manager->id, $systemcontext, false, 'systemtestfile1.h5p');
335         $records = $generator->generate_contentbank_data('contenttype_testable',
336             1, $manager->id, $systemcontext, false, 'systemtestfile2.h5p');
337         $records = $generator->generate_contentbank_data('contenttype_testable',
338             1, $manager->id, $systemcontext, false, 'systemtestfile3.h5p');
339         // Add contents by Manager in Context Course Category.
340         $records = $generator->generate_contentbank_data('contenttype_testable',
341             1, $manager->id, $coursecategorycontext, false, 'coursecattestfile1.h5p');
342         $records = $generator->generate_contentbank_data('contenttype_testable',
343             1, $manager->id, $coursecategorycontext, false, 'coursecattestfile2.h5p');
344         // Add contents by Manager in Context Course.
345         $records = $generator->generate_contentbank_data('contenttype_testable',
346             1, $manager->id, $coursecontext, false, 'coursetestfile1.h5p');
347         $records = $generator->generate_contentbank_data('contenttype_testable',
348             1, $manager->id, $coursecontext, false, 'coursetestfile2.h5p');
349         // Add contents by Teacher.
350         $records = $generator->generate_contentbank_data('contenttype_testable',
351             1, $teacher->id, $coursecontext, false, 'courseteacherfile1.h5p');
352         $records = $generator->generate_contentbank_data('contenttype_testable',
353             1, $teacher->id, $coursecontext, false, 'courseteacherfile2.h5p');
354         $records = $generator->generate_contentbank_data('contenttype_testable',
355             1, $teacher->id, $coursecontext, false, 'courseteacherfile3.h5p');
357         $scenario = new stdClass();
358         $scenario->systemcontext = $systemcontext;
359         $scenario->coursecategorycontext = $coursecategorycontext;
360         $scenario->coursecontext = $coursecontext;
361         $scenario->manager = $manager;
362         $scenario->teacher = $teacher;
364         return $scenario;
365     }