MDL-67789 xapi: Add support to save content state
[moodle.git] / lib / xapi / tests / privacy / provider_test.php
blobc83d698e95f1e9ef65442b1308763e0f5eaf84df
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.
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 namespace core_xapi\privacy;
19 use core_privacy\tests\provider_testcase;
20 use core_privacy\local\request\transform;
21 use core_xapi\privacy\provider;
22 use core_xapi\local\statement\item_activity;
23 use core_xapi\test_helper;
25 /**
26 * Privacy tests for core_xapi.
28 * @package core_xapi
29 * @category test
30 * @copyright 2023 Sara Arjona (sara@moodle.com)
31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32 * @covers \core_xapi\privacy\provider
34 class provider_test extends provider_testcase {
36 /**
37 * Setup to ensure that fixtures are loaded.
39 public static function setUpBeforeClass(): void {
40 global $CFG;
41 require_once($CFG->dirroot.'/lib/xapi/tests/helper.php');
44 /**
45 * Helper to set up some sample data.
47 * @return array Array with the users that have been created.
49 protected function set_up_data(): array {
50 $user1 = self::getDataGenerator()->create_user();
51 $user2 = self::getDataGenerator()->create_user();
52 $user3 = self::getDataGenerator()->create_user();
54 // Add a few xAPI state records to database.
55 $context = \context_system::instance();
56 $cid = $context->id;
57 $this->setUser($user1);
58 test_helper::create_state(['activity' => item_activity::create_from_id($context->id)], true);
59 test_helper::create_state(['activity' => item_activity::create_from_id('2')], true);
60 test_helper::create_state(['activity' => item_activity::create_from_id('3'), 'component' => 'mod_h5pactivity'], true);
61 $this->setUser($user2);
62 test_helper::create_state(['activity' => item_activity::create_from_id($context->id)], true);
63 test_helper::create_state(['activity' => item_activity::create_from_id('2')], true);
64 test_helper::create_state(['activity' => item_activity::create_from_id('4')], true);
65 test_helper::create_state(['activity' => item_activity::create_from_id('5')], true);
66 $this->setUser($user3);
67 test_helper::create_state(['activity' => item_activity::create_from_id($cid), 'component' => 'mod_h5pactivity'], true);
69 return [$user1, $user2, $user3];
72 /**
73 * Test confirming that contexts of xapi items can be added to the contextlist.
75 public function test_add_contexts_for_userid(): void {
76 $this->resetAfterTest();
78 // Scenario.
79 list($user1, $user2) = $this->set_up_data();
81 // Ask the xapi privacy api to export contexts for xapi of the type we just created, for user1.
82 $contextlist = new \core_privacy\local\request\contextlist();
83 provider::add_contexts_for_userid($contextlist, $user1->id, 'fake_component');
84 $this->assertCount(2, $contextlist->get_contextids());
86 $contextlist = new \core_privacy\local\request\contextlist();
87 provider::add_contexts_for_userid($contextlist, $user1->id, 'mod_h5pactivity');
88 $this->assertCount(1, $contextlist->get_contextids());
90 // Ask the xapi privacy api to export contexts for xapi of the type we just created, for user2.
91 $contextlist = new \core_privacy\local\request\contextlist();
92 provider::add_contexts_for_userid($contextlist, $user2->id, 'fake_component');
93 $this->assertCount(4, $contextlist->get_contextids());
95 $contextlist = new \core_privacy\local\request\contextlist();
96 provider::add_contexts_for_userid($contextlist, $user2->id, 'mod_h5pactivity');
97 $this->assertCount(0, $contextlist->get_contextids());
101 * Test confirming that user ID's of xapi states can be added to the userlist.
103 public function test_add_userids_for_context() {
104 global $DB;
106 $this->resetAfterTest();
108 // Scenario.
109 list($user1, $user2, $user3) = $this->set_up_data();
110 $this->assertEquals(3, $DB->count_records('xapi_states', ['userid' => $user1->id]));
111 $this->assertEquals(4, $DB->count_records('xapi_states', ['userid' => $user2->id]));
112 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user3->id]));
113 $systemcontext = \context_system::instance();
115 // Ask the xapi privacy api to export userids for xapi states of the type we just created, in the system context.
116 $userlist = new \core_privacy\local\request\userlist($systemcontext, 'fake_component');
117 provider::add_userids_for_context($userlist, 'fake_component');
118 // Only user1 and user2 should be returned, because user3 has a different component for the system context.
119 $this->assertCount(2, $userlist->get_userids());
120 $expected = [
121 $user1->id,
122 $user2->id,
124 $this->assertEqualsCanonicalizing($expected, $userlist->get_userids());
126 // Ask the xapi privacy api to export userids for xapi states of the type we just created for a different component.
127 $userlist = new \core_privacy\local\request\userlist($systemcontext, 'mod_h5pactivity');
128 provider::add_userids_for_context($userlist, 'mod_h5pactivity');
129 // Only user3 should be returned, because the others have a different component for the system context.
130 $this->assertCount(1, $userlist->get_userids());
131 $expected = [$user3->id];
132 $this->assertEqualsCanonicalizing($expected, $userlist->get_userids());
134 // Ask the xapi privacy api to export userids xapi states for an empty component.
135 $userlist = new \core_privacy\local\request\userlist($systemcontext, 'empty_component');
136 provider::add_userids_for_context($userlist, 'empty_component');
137 $this->assertCount(0, $userlist->get_userids());
141 * Test fetching the xapi state data for a specified user in a specified component and itemid.
143 public function test_get_xapi_states_for_user() {
144 global $DB;
146 $this->resetAfterTest();
148 // Scenario.
149 list($user1, $user2, $user3) = $this->set_up_data();
150 $this->assertEquals(3, $DB->count_records('xapi_states', ['userid' => $user1->id]));
151 $this->assertEquals(4, $DB->count_records('xapi_states', ['userid' => $user2->id]));
152 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user3->id]));
153 $systemcontext = \context_system::instance();
155 // Get the states info for user1 in the system context.
156 $result = provider::get_xapi_states_for_user($user1->id, 'fake_component', $systemcontext->id);
157 $info = (object) reset($result);
158 // Ensure the correct data has been returned.
159 $this->assertNotEmpty($info->statedata);
160 $this->assertNotEmpty(transform::datetime($info->timecreated));
161 $this->assertNotEmpty(transform::datetime($info->timemodified));
163 // Get the states info for user2 in the system context.
164 $result = provider::get_xapi_states_for_user($user2->id, 'fake_component', $systemcontext->id);
165 $info = (object) reset($result);
166 // Ensure the correct data has been returned.
167 $this->assertNotEmpty($info->statedata);
168 $this->assertNotEmpty(transform::datetime($info->timecreated));
169 $this->assertNotEmpty(transform::datetime($info->timemodified));
171 // Get the states info for user3 in the system context (it should be empty).
172 $info = provider::get_xapi_states_for_user($user3->id, 'fake_component', $systemcontext->id);
173 // Ensure the correct data has been returned.
174 $this->assertEmpty($info);
178 * Test deletion of user xapi states based on an approved_contextlist and component area.
180 public function test_delete_states_for_user(): void {
181 global $DB;
183 $this->resetAfterTest();
185 // Scenario.
186 list($user1, $user2, $user3) = $this->set_up_data();
187 $this->assertEquals(3, $DB->count_records('xapi_states', ['userid' => $user1->id]));
188 $this->assertEquals(4, $DB->count_records('xapi_states', ['userid' => $user2->id]));
189 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user3->id]));
191 // Now, delete the xapistates for user1 only.
192 $user1context = \context_user::instance($user1->id);
193 $approvedcontextlist = new \core_privacy\local\request\approved_contextlist($user1, 'fake_component', [$user1context->id]);
194 provider::delete_states_for_user($approvedcontextlist, 'fake_component');
196 // Verify that we have no xapi states for user1 for the fake_component but that the rest of records are intact.
197 $this->assertEquals(0, $DB->count_records('xapi_states', ['userid' => $user1->id, 'component' => 'fake_component']));
198 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user1->id, 'component' => 'mod_h5pactivity']));
199 $this->assertEquals(4, $DB->count_records('xapi_states', ['userid' => $user2->id]));
200 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user3->id]));
204 * Test deletion of all user xapi states.
206 public function test_delete_states_for_all_users(): void {
207 global $DB;
209 $this->resetAfterTest();
211 // Scenario.
212 list($user1, $user2, $user3) = $this->set_up_data();
213 $this->assertEquals(3, $DB->count_records('xapi_states', ['userid' => $user1->id]));
214 $this->assertEquals(4, $DB->count_records('xapi_states', ['userid' => $user2->id]));
215 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user3->id]));
217 // Now, delete all course module xapi states in the 'fake_component' context only.
218 provider::delete_states_for_all_users(\context_system::instance(), 'fake_component');
220 // Verify that only content with the context_system for the fake_component have been removed.
221 $this->assertEquals(2, $DB->count_records('xapi_states', ['userid' => $user1->id]));
222 $this->assertEquals(3, $DB->count_records('xapi_states', ['userid' => $user2->id]));
223 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user3->id]));
227 * Test deletion of user xapi states based on an approved_userlist and component area.
229 public function test_delete_states_for_userlist() {
230 global $DB;
232 $this->resetAfterTest();
234 // Scenario.
235 list($user1, $user2, $user3) = $this->set_up_data();
236 $this->assertEquals(3, $DB->count_records('xapi_states', ['userid' => $user1->id]));
237 $this->assertEquals(4, $DB->count_records('xapi_states', ['userid' => $user2->id]));
238 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user3->id]));
239 $systemcontext = \context_system::instance();
241 // Ask the xapi privacy api to export userids for states of the type we just created, in the system context.
242 $userlist1 = new \core_privacy\local\request\userlist($systemcontext, 'fake_component');
243 provider::add_userids_for_context($userlist1);
244 // Verify we have two userids in the list for system context.
245 $this->assertCount(2, $userlist1->get_userids());
247 // Now, delete the states for user1 only in the system context.
248 $approveduserlist = new \core_privacy\local\request\approved_userlist($systemcontext, 'fake_component', [$user1->id]);
249 provider::delete_states_for_userlist($approveduserlist);
250 // Ensure user1's data was deleted and user2 is still returned for system context.
251 $userlist1 = new \core_privacy\local\request\userlist($systemcontext, 'fake_component');
252 provider::add_userids_for_context($userlist1);
253 $this->assertCount(1, $userlist1->get_userids());
254 // Verify that user2 is still in the list for system context.
255 $expected = [$user2->id];
256 $this->assertEquals($expected, $userlist1->get_userids());
257 // Verify that the data of user1 in other contexts was not deleted.
258 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user3->id]));
259 $this->assertEquals(1, $DB->count_records('xapi_states', ['userid' => $user1->id]));
260 $this->assertEquals(2, $DB->count_records('xapi_states', ['itemid' => $systemcontext->id]));
262 // Verify that no data is removed if the component is empty.
263 $userlist3 = new \core_privacy\local\request\userlist($systemcontext, 'empty_component');
264 provider::add_userids_for_context($userlist3);
265 $this->assertCount(0, $userlist3->get_userids());
266 $this->assertEquals(2, $DB->count_records('xapi_states', ['itemid' => $systemcontext->id]));