2 // This file is part of Moodle - http://moodle.org/
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.
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/>.
18 * Data provider tests.
20 * @package core_grades
22 * @copyright 2018 Frédéric Massart
23 * @author Frédéric Massart <fred@branchup.tech>
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') || die();
30 use core_privacy\tests\provider_testcase;
31 use core_privacy\local\request\approved_contextlist;
32 use core_privacy\local\request\transform;
33 use core_privacy\local\request\writer;
34 use core_grades\privacy\provider;
36 require_once($CFG->libdir . '/gradelib.php');
39 * Data provider testcase class.
41 * @package core_grades
43 * @copyright 2018 Frédéric Massart
44 * @author Frédéric Massart <fred@branchup.tech>
45 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
47 class core_grades_privacy_testcase extends provider_testcase {
49 public function setUp() {
51 $this->resetAfterTest();
52 $PAGE->get_renderer('core');
55 public function test_get_contexts_for_userid_gradebook_edits() {
56 $dg = $this->getDataGenerator();
58 $c1 = $dg->create_course();
59 $c2 = $dg->create_course();
61 $u1 = $dg->create_user();
62 $u2 = $dg->create_user();
63 $u3 = $dg->create_user();
64 $u4 = $dg->create_user();
65 $u5 = $dg->create_user();
66 $u6 = $dg->create_user();
67 $u7 = $dg->create_user();
68 $u8 = $dg->create_user();
69 $u9 = $dg->create_user();
70 $u10 = $dg->create_user();
71 $u11 = $dg->create_user();
73 $sysctx = context_system::instance();
74 $c1ctx = context_course::instance($c1->id);
75 $c2ctx = context_course::instance($c2->id);
78 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
79 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
80 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
81 $gc1a = new grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);
82 $gc1b = new grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);
83 $gc2a = new grade_category($dg->create_grade_category(['courseid' => $c2->id]), false);
84 $go2 = new grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2',
85 'fullname' => 'go2']), false);
88 foreach ([$u1, $u2, $u3, $u4, $u5, $u6, $u7, $u8, $u9, $u10, $u11] as $u) {
89 $contexts = array_flip(provider::get_contexts_for_userid($u->id)->get_contextids());
90 $this->assertEmpty($contexts);
93 $go0 = new grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]);
95 $go1 = new grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u11->id]);
99 $s1 = new grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']);
101 $s2 = new grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']);
104 // User 2 creates history.
106 $go0->shortname .= ' edited';
108 $gc1a->fullname .= ' edited';
111 // User 3 creates history.
113 $go1->shortname .= ' edited';
115 $gc2a->fullname .= ' a';
118 // User 4 updates an outcome in course (creates history).
120 $go2->shortname .= ' edited';
123 // User 5 updates an item.
125 $gi1a->itemname .= ' edited';
128 // User 6 creates history.
132 // User 9 creates history.
134 $s1->name .= ' edited';
138 $contexts = array_flip(provider::get_contexts_for_userid($u1->id)->get_contextids());
139 $this->assertCount(1, $contexts);
140 $this->assertArrayHasKey($sysctx->id, $contexts);
141 $contexts = array_flip(provider::get_contexts_for_userid($u11->id)->get_contextids());
142 $this->assertCount(1, $contexts);
143 $this->assertArrayHasKey($c1ctx->id, $contexts);
144 $contexts = array_flip(provider::get_contexts_for_userid($u2->id)->get_contextids());
145 $this->assertCount(2, $contexts);
146 $this->assertArrayHasKey($sysctx->id, $contexts);
147 $this->assertArrayHasKey($c1ctx->id, $contexts);
148 $contexts = array_flip(provider::get_contexts_for_userid($u3->id)->get_contextids());
149 $this->assertCount(2, $contexts);
150 $this->assertArrayHasKey($c1ctx->id, $contexts);
151 $this->assertArrayHasKey($c2ctx->id, $contexts);
152 $contexts = array_flip(provider::get_contexts_for_userid($u4->id)->get_contextids());
153 $this->assertCount(1, $contexts);
154 $this->assertArrayHasKey($c2ctx->id, $contexts);
155 $contexts = array_flip(provider::get_contexts_for_userid($u5->id)->get_contextids());
156 $this->assertCount(1, $contexts);
157 $this->assertArrayHasKey($c1ctx->id, $contexts);
158 $contexts = array_flip(provider::get_contexts_for_userid($u6->id)->get_contextids());
159 $this->assertCount(1, $contexts);
160 $this->assertArrayHasKey($c2ctx->id, $contexts);
161 $contexts = array_flip(provider::get_contexts_for_userid($u7->id)->get_contextids());
162 $this->assertCount(1, $contexts);
163 $this->assertArrayHasKey($sysctx->id, $contexts);
164 $contexts = array_flip(provider::get_contexts_for_userid($u8->id)->get_contextids());
165 $this->assertCount(1, $contexts);
166 $this->assertArrayHasKey($c1ctx->id, $contexts);
167 $contexts = array_flip(provider::get_contexts_for_userid($u9->id)->get_contextids());
168 $this->assertCount(1, $contexts);
169 $this->assertArrayHasKey($sysctx->id, $contexts);
171 // User 10 creates history.
172 $this->setUser($u10);
175 $contexts = array_flip(provider::get_contexts_for_userid($u10->id)->get_contextids());
176 $this->assertCount(1, $contexts);
177 $this->assertArrayHasKey($c1ctx->id, $contexts);
180 public function test_get_contexts_for_userid_grades_and_history() {
181 $dg = $this->getDataGenerator();
183 $c1 = $dg->create_course();
184 $c2 = $dg->create_course();
186 $u1 = $dg->create_user();
187 $u2 = $dg->create_user();
188 $u3 = $dg->create_user();
189 $u4 = $dg->create_user();
190 $u5 = $dg->create_user();
191 $u6 = $dg->create_user();
193 $sysctx = context_system::instance();
194 $c1ctx = context_course::instance($c1->id);
195 $c2ctx = context_course::instance($c2->id);
197 // Create some stuff.
198 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
199 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
200 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
201 $gi2b = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
203 // Nothing as of now.
204 foreach ([$u1, $u2, $u3, $u4, $u5, $u6] as $u) {
205 $contexts = array_flip(provider::get_contexts_for_userid($u->id)->get_contextids());
206 $this->assertEmpty($contexts);
209 // User 1 is graded in course 1.
210 $gi1a->update_final_grade($u1->id, 1, 'test');
212 // User 2 is graded in course 2.
213 $gi2a->update_final_grade($u2->id, 10, 'test');
215 // User 3 is set as modifier.
216 $gi1a->update_final_grade($u1->id, 1, 'test', '', FORMAT_MOODLE, $u3->id);
218 // User 4 is set as modifier, and creates history..
220 $gi1a->update_final_grade($u2->id, 1, 'test');
222 // User 5 creates history, user 6 is the known modifier, and we delete the item.
224 $gi2b->update_final_grade($u2->id, 1, 'test', '', FORMAT_PLAIN, $u6->id);
228 $contexts = array_flip(provider::get_contexts_for_userid($u1->id)->get_contextids());
229 $this->assertCount(1, $contexts);
230 $this->assertArrayHasKey($c1ctx->id, $contexts);
231 $contexts = array_flip(provider::get_contexts_for_userid($u2->id)->get_contextids());
232 $this->assertCount(3, $contexts);
233 $this->assertArrayHasKey($c1ctx->id, $contexts);
234 $this->assertArrayHasKey($c2ctx->id, $contexts);
235 $this->assertArrayHasKey(context_user::instance($u2->id)->id, $contexts);
236 $contexts = array_flip(provider::get_contexts_for_userid($u3->id)->get_contextids());
237 $this->assertCount(1, $contexts);
238 $this->assertArrayHasKey($c1ctx->id, $contexts);
239 $contexts = array_flip(provider::get_contexts_for_userid($u4->id)->get_contextids());
240 $this->assertCount(1, $contexts);
241 $this->assertArrayHasKey($c1ctx->id, $contexts);
242 $contexts = array_flip(provider::get_contexts_for_userid($u5->id)->get_contextids());
243 $this->assertCount(2, $contexts);
244 $this->assertArrayHasKey($c2ctx->id, $contexts);
245 $this->assertArrayHasKey(context_user::instance($u2->id)->id, $contexts);
246 $contexts = array_flip(provider::get_contexts_for_userid($u6->id)->get_contextids());
247 $this->assertCount(1, $contexts);
248 $this->assertArrayHasKey(context_user::instance($u2->id)->id, $contexts);
252 * Test that the appropriate user IDs are returned for a given context.
254 public function test_get_users_in_context_gradebook_edits() {
255 $dg = $this->getDataGenerator();
257 $c1 = $dg->create_course();
258 $c2 = $dg->create_course();
260 $u1 = $dg->create_user();
261 $u2 = $dg->create_user();
262 $u3 = $dg->create_user();
263 $u4 = $dg->create_user();
264 $u5 = $dg->create_user();
265 $u6 = $dg->create_user();
266 $u7 = $dg->create_user();
267 $u8 = $dg->create_user();
268 $u9 = $dg->create_user();
269 $u10 = $dg->create_user();
270 $u11 = $dg->create_user();
272 $sysctx = context_system::instance();
273 $c1ctx = context_course::instance($c1->id);
274 $c2ctx = context_course::instance($c2->id);
276 // Create some stuff.
277 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
278 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
279 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
280 $gc1a = new grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);
281 $gc1b = new grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);
282 $gc2a = new grade_category($dg->create_grade_category(['courseid' => $c2->id]), false);
283 $go2 = new grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2',
284 'fullname' => 'go2']), false);
286 $go0 = new grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]);
288 $go1 = new grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u11->id]);
292 $s1 = new grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']);
294 $s2 = new grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']);
297 // User 2 creates history.
299 $go0->shortname .= ' edited';
301 $gc1a->fullname .= ' edited';
304 // User 3 creates history.
306 $go1->shortname .= ' edited';
308 $gc2a->fullname .= ' a';
311 // User 4 updates an outcome in course (creates history).
313 $go2->shortname .= ' edited';
316 // User 5 updates an item.
318 $gi1a->itemname .= ' edited';
321 // User 6 creates history.
325 // User 9 creates history.
327 $s1->name .= ' edited';
330 $userlist = new \core_privacy\local\request\userlist($sysctx, 'core_grades');
331 provider::get_users_in_context($userlist);
332 $systemcontextuserids = [$u1->id, $u2->id, $u7->id, $u9->id];
333 $this->assertEquals($systemcontextuserids, $userlist->get_userids());
335 $userlist = new \core_privacy\local\request\userlist($c1ctx, 'core_grades');
336 provider::get_users_in_context($userlist);
337 $course1userids = [$u11->id, $u3->id, $u8->id, $u5->id, $u2->id];
338 $this->assertEquals($course1userids, $userlist->get_userids());
340 $userlist = new \core_privacy\local\request\userlist($c2ctx, 'core_grades');
341 provider::get_users_in_context($userlist);
342 $course2userids = [$u4->id, $u6->id, $u3->id];
343 $this->assertEquals($course2userids, $userlist->get_userids());
347 * Test that the appropriate user IDs are returned for a given context.
349 public function test_get_users_in_context_grades_and_history() {
350 $dg = $this->getDataGenerator();
352 $c1 = $dg->create_course();
353 $c2 = $dg->create_course();
355 $u1 = $dg->create_user();
356 $u2 = $dg->create_user();
357 $u3 = $dg->create_user();
358 $u4 = $dg->create_user();
359 $u5 = $dg->create_user();
360 $u6 = $dg->create_user();
362 $c1ctx = context_course::instance($c1->id);
363 $c2ctx = context_course::instance($c2->id);
364 $u2ctx = context_user::instance($u2->id);
366 // Create some stuff.
367 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
368 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
369 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
370 $gi2b = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
372 // User 1 is graded in course 1.
373 $gi1a->update_final_grade($u1->id, 1, 'test');
375 // User 2 is graded in course 2.
376 $gi2a->update_final_grade($u2->id, 10, 'test');
378 // User 3 is set as modifier.
379 $gi1a->update_final_grade($u1->id, 1, 'test', '', FORMAT_MOODLE, $u3->id);
381 // User 4 is set as modifier, and creates history..
383 $gi1a->update_final_grade($u2->id, 1, 'test');
385 // User 5 creates history, user 6 is the known modifier, and we delete the item.
387 $gi2b->update_final_grade($u2->id, 1, 'test', '', FORMAT_PLAIN, $u6->id);
390 $userlist = new \core_privacy\local\request\userlist($c1ctx, 'core_grades');
391 provider::get_users_in_context($userlist);
392 $course1userids = [$u1->id, $u2->id, $u3->id, $u4->id];
393 $this->assertEquals($course1userids, $userlist->get_userids(), '', 0.0, 10, true);
395 $userlist = new \core_privacy\local\request\userlist($c2ctx, 'core_grades');
396 provider::get_users_in_context($userlist);
397 $course2userids = [$u5->id, $u2->id];
398 $this->assertEquals($course2userids, $userlist->get_userids(), '', 0.0, 10, true);
400 $userlist = new \core_privacy\local\request\userlist($u2ctx, 'core_grades');
401 provider::get_users_in_context($userlist);
402 $this->assertEquals([$u2->id], $userlist->get_userids());
405 public function test_delete_data_for_all_users_in_context() {
407 $dg = $this->getDataGenerator();
409 $c1 = $dg->create_course();
410 $c2 = $dg->create_course();
411 $u1 = $dg->create_user();
412 $u2 = $dg->create_user();
413 $u1ctx = context_user::instance($u1->id);
414 $c1ctx = context_course::instance($c1->id);
415 $c2ctx = context_course::instance($c2->id);
417 // Create some stuff.
418 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
419 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
420 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
421 $gi2b = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
423 $gi1a->update_final_grade($u1->id, 1, 'test');
424 $gi1a->update_final_grade($u2->id, 1, 'test');
425 $gi1b->update_final_grade($u1->id, 1, 'test');
426 $gi2a->update_final_grade($u1->id, 1, 'test');
427 $gi2a->update_final_grade($u2->id, 1, 'test');
428 $gi2b->update_final_grade($u1->id, 1, 'test');
429 $gi2b->update_final_grade($u2->id, 1, 'test');
432 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
433 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
434 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
435 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
436 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
437 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
438 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
440 provider::delete_data_for_all_users_in_context($c1ctx);
441 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
442 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
443 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
444 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
445 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
446 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
447 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
449 provider::delete_data_for_all_users_in_context($u1ctx);
450 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
451 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
452 $this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
453 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
455 provider::delete_data_for_all_users_in_context($c2ctx);
456 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
457 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
458 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
461 public function test_delete_data_for_user() {
463 $dg = $this->getDataGenerator();
465 $c1 = $dg->create_course();
466 $c2 = $dg->create_course();
467 $u1 = $dg->create_user();
468 $u2 = $dg->create_user();
469 $u1ctx = context_user::instance($u1->id);
470 $u2ctx = context_user::instance($u2->id);
471 $c1ctx = context_course::instance($c1->id);
472 $c2ctx = context_course::instance($c2->id);
474 // Create some stuff.
475 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
476 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
477 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
478 $gi2b = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
480 $gi1a->update_final_grade($u1->id, 1, 'test');
481 $gi1a->update_final_grade($u2->id, 1, 'test');
482 $gi1b->update_final_grade($u1->id, 1, 'test');
483 $gi2a->update_final_grade($u1->id, 1, 'test');
484 $gi2a->update_final_grade($u2->id, 1, 'test');
485 $gi2b->update_final_grade($u1->id, 1, 'test');
486 $gi2b->update_final_grade($u2->id, 1, 'test');
489 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
490 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
491 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
492 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
493 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
494 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
495 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
497 provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$c1ctx->id]));
498 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
499 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
500 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
501 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
502 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
503 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
504 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
506 provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$u1ctx->id]));
507 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
508 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
509 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
510 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
511 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
512 $this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
513 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
515 provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$u2ctx->id, $c2ctx->id]));
516 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
517 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
518 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
519 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
520 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
521 $this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
522 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
526 * Test deleting multiple users for a context works.
528 public function test_delete_data_for_users() {
530 $dg = $this->getDataGenerator();
532 $c1 = $dg->create_course();
533 $c2 = $dg->create_course();
534 $u1 = $dg->create_user();
535 $u2 = $dg->create_user();
536 $u3 = $dg->create_user();
537 $u4 = $dg->create_user();
538 $u1ctx = context_user::instance($u1->id);
539 $u2ctx = context_user::instance($u2->id);
540 $c1ctx = context_course::instance($c1->id);
541 $c2ctx = context_course::instance($c2->id);
543 // Create some stuff.
544 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
545 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
546 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
547 $gi2b = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
549 $gi1a->update_final_grade($u1->id, 1, 'test');
550 $gi1a->update_final_grade($u2->id, 1, 'test');
551 $gi1a->update_final_grade($u3->id, 1, 'test');
552 $gi1b->update_final_grade($u1->id, 1, 'test');
553 $gi1b->update_final_grade($u4->id, 1, 'test');
554 $gi2a->update_final_grade($u1->id, 1, 'test');
555 $gi2a->update_final_grade($u2->id, 1, 'test');
556 $gi2a->update_final_grade($u4->id, 1, 'test');
557 $gi2b->update_final_grade($u1->id, 1, 'test');
558 $gi2b->update_final_grade($u2->id, 1, 'test');
559 $gi2b->update_final_grade($u3->id, 1, 'test');
562 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
563 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
564 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id]));
565 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
566 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id]));
567 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
568 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
569 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id]));
570 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
571 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
572 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi2b->id]));
574 $userlist = new \core_privacy\local\request\approved_userlist($c1ctx, 'core_grades', [$u1->id, $u2->id]);
575 provider::delete_data_for_users($userlist);
577 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
578 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
579 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id]));
580 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
581 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id]));
582 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
583 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
584 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id]));
586 $userlist = new \core_privacy\local\request\approved_userlist($c2ctx, 'core_grades', [$u2->id, $u4->id]);
587 provider::delete_data_for_users($userlist);
589 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
590 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
591 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id]));
592 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
593 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id]));
594 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
595 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
596 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id]));
599 public function test_export_data_for_user_about_grades_and_history() {
601 $dg = $this->getDataGenerator();
603 $c1 = $dg->create_course();
604 $c2 = $dg->create_course();
606 // Users being graded.
607 $ug1 = $dg->create_user();
608 $ug2 = $dg->create_user();
609 $ug3 = $dg->create_user();
610 // Users performing actions.
611 $ua1 = $dg->create_user();
612 $ua2 = $dg->create_user();
613 $ua3 = $dg->create_user();
615 $ug1ctx = context_user::instance($ug1->id);
616 $ug2ctx = context_user::instance($ug2->id);
617 $c1ctx = context_course::instance($c1->id);
618 $c2ctx = context_course::instance($c2->id);
620 $rootpath = [get_string('grades', 'core_grades')];
621 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);
623 // Create the course minimal stuff.
624 grade_category::fetch_course_category($c1->id);
625 $ci1 = grade_item::fetch_course_item($c1->id);
626 grade_category::fetch_course_category($c2->id);
627 $ci2 = grade_item::fetch_course_item($c2->id);
629 // Create data that will sit in the user context because we will delete the grate item.
630 $gi1 = new grade_item($dg->create_grade_item(['courseid' => $c1->id, 'aggregationcoef2' => 1]), false);
631 $gi1->update_final_grade($ug1->id, 100, 'test', 'Well done!', FORMAT_PLAIN, $ua2->id);
632 $gi1->update_final_grade($ug1->id, 1, 'test', 'Hi', FORMAT_PLAIN, $ua2->id);
633 $gi1->update_final_grade($ug3->id, 12, 'test', 'Hello', FORMAT_PLAIN, $ua2->id);
635 // Create another set for another user.
636 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
637 $gi2a->update_final_grade($ug1->id, 15, 'test', '', FORMAT_PLAIN, $ua2->id);
638 $gi2b = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
639 $gi2b->update_final_grade($ug1->id, 30, 'test', 'Well played!', FORMAT_PLAIN, $ua2->id);
641 // Export action user 1 everywhere.
642 provider::export_user_data(new approved_contextlist($ua1, 'core_grades', [$ug1ctx->id, $ug2ctx->id,
643 $c1ctx->id, $c2ctx->id]));
644 $this->assert_context_has_no_data($ug1ctx);
645 $this->assert_context_has_no_data($ug2ctx);
646 $this->assert_context_has_no_data($c1ctx);
647 $this->assert_context_has_no_data($c2ctx);
649 // Export action user 2 in course 1.
651 provider::export_user_data(new approved_contextlist($ua2, 'core_grades', [$c1ctx->id]));
652 $this->assert_context_has_no_data($ug1ctx);
653 $this->assert_context_has_no_data($ug2ctx);
654 $this->assert_context_has_no_data($c2ctx);
655 $data = writer::with_context($c1ctx)->get_data($rootpath);
656 $this->assertEmpty($data);
658 // Here we are testing the export of grades that we've changed.
659 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades');
660 $this->assertCount(2, $data->grades);
661 $this->assertEquals($gi1->get_name(), $data->grades[0]['item']);
662 $this->assertEquals(1, $data->grades[0]['grade']);
663 $this->assertEquals('Hi', $data->grades[0]['feedback']);
664 $this->assertEquals(transform::yesno(true), $data->grades[0]['created_or_modified_by_you']);
665 $this->assertEquals($gi1->get_name(), $data->grades[1]['item']);
666 $this->assertEquals(12, $data->grades[1]['grade']);
667 $this->assertEquals('Hello', $data->grades[1]['feedback']);
668 $this->assertEquals(transform::yesno(true), $data->grades[1]['created_or_modified_by_you']);
670 // Here we are testing the export of history of grades that we've changed.
671 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades_history');
672 $this->assertCount(3, $data->modified_records);
673 $grade = $data->modified_records[0];
674 $this->assertEquals($ug1->id, $grade['userid']);
675 $this->assertEquals($gi1->get_name(), $grade['item']);
676 $this->assertEquals(100, $grade['grade']);
677 $this->assertEquals('Well done!', $grade['feedback']);
678 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
679 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
680 $grade = $data->modified_records[1];
681 $this->assertEquals($ug1->id, $grade['userid']);
682 $this->assertEquals($gi1->get_name(), $grade['item']);
683 $this->assertEquals(1, $grade['grade']);
684 $this->assertEquals('Hi', $grade['feedback']);
685 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
686 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
687 $grade = $data->modified_records[2];
688 $this->assertEquals($ug3->id, $grade['userid']);
689 $this->assertEquals($gi1->get_name(), $grade['item']);
690 $this->assertEquals(12, $grade['grade']);
691 $this->assertEquals('Hello', $grade['feedback']);
692 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
693 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
695 // Create a history record with logged user.
696 $this->setUser($ua3);
697 $gi1->update_final_grade($ug3->id, 50, 'test', '...', FORMAT_PLAIN, $ua2->id);
699 provider::export_user_data(new approved_contextlist($ua3, 'core_grades', [$c1ctx->id]));
700 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades_history');
701 $this->assertCount(1, $data->modified_records);
702 $grade = $data->modified_records[0];
703 $this->assertEquals($ug3->id, $grade['userid']);
704 $this->assertEquals($gi1->get_name(), $grade['item']);
705 $this->assertEquals(50, $grade['grade']);
706 $this->assertEquals('...', $grade['feedback']);
707 $this->assertEquals(transform::yesno(true), $grade['logged_in_user_was_you']);
708 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
710 // Test that we export our own grades.
712 provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$c1ctx->id]));
713 $data = writer::with_context($c1ctx)->get_data($rootpath);
714 $this->assert_context_has_no_data($c2ctx);
715 $this->assertCount(2, $data->grades);
716 $grade = $data->grades[0];
717 $this->assertEquals($ci1->get_name(), $grade['item']);
718 $this->assertEquals(1, $grade['grade']);
719 $grade = $data->grades[1];
720 $this->assertEquals($gi1->get_name(), $grade['item']);
721 $this->assertEquals(1, $grade['grade']);
722 $this->assertEquals('Hi', $grade['feedback']);
724 // Test that we export our own grades in two courses.
726 provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$ug1ctx->id, $c1ctx->id, $c2ctx->id]));
727 $this->assert_context_has_no_data($ug1ctx);
728 $data = writer::with_context($c1ctx)->get_data($rootpath);
729 $this->assertCount(2, $data->grades);
730 $grade = $data->grades[0];
731 $this->assertEquals($ci1->get_name(), $grade['item']);
732 $this->assertEquals(1, $grade['grade']);
733 $grade = $data->grades[1];
734 $this->assertEquals($gi1->get_name(), $grade['item']);
735 $this->assertEquals(1, $grade['grade']);
736 $this->assertEquals('Hi', $grade['feedback']);
738 $data = writer::with_context($c2ctx)->get_data($rootpath);
739 $this->assertCount(3, $data->grades);
740 $grade = $data->grades[0];
741 $this->assertEquals($ci2->get_name(), $grade['item']);
742 $grade = $data->grades[1];
743 $this->assertEquals($gi2a->get_name(), $grade['item']);
744 $this->assertEquals(15, $grade['grade']);
745 $this->assertEquals('', $grade['feedback']);
746 $grade = $data->grades[2];
747 $this->assertEquals($gi2b->get_name(), $grade['item']);
748 $this->assertEquals(30, $grade['grade']);
749 $this->assertEquals('Well played!', $grade['feedback']);
751 // Delete a grade item.
752 $this->setUser($ua3);
755 // Now, we should find history of grades in our own context.
757 provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$ug1ctx->id, $c1ctx->id, $c2ctx->id]));
758 $data = writer::with_context($c1ctx)->get_data($rootpath);
759 $this->assertCount(1, $data->grades);
760 $this->assertEquals($ci1->get_name(), $data->grades[0]['item']);
761 $data = writer::with_context($c2ctx)->get_data($rootpath);
762 $this->assertCount(3, $data->grades);
763 $data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history');
764 $this->assertCount(3, $data->grades);
765 $grade = $data->grades[0];
766 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
767 $this->assertEquals(100, $grade['grade']);
768 $this->assertEquals('Well done!', $grade['feedback']);
769 $this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']);
770 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
771 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
772 $this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'), $grade['action']);
773 $grade = $data->grades[1];
774 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
775 $this->assertEquals(1, $grade['grade']);
776 $this->assertEquals('Hi', $grade['feedback']);
777 $this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']);
778 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
779 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
780 $this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'), $grade['action']);
781 $grade = $data->grades[2];
782 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
783 $this->assertEquals(1, $grade['grade']);
784 $this->assertEquals('Hi', $grade['feedback']);
785 $this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']);
786 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
787 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
788 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']);
790 // The action user 3 should have a record of the deletion in the user's context.
792 provider::export_user_data(new approved_contextlist($ua3, 'core_grades', [$ug1ctx->id]));
793 $data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history');
794 $this->assertCount(1, $data->grades);
795 $grade = $data->grades[0];
796 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
797 $this->assertEquals(1, $grade['grade']);
798 $this->assertEquals('Hi', $grade['feedback']);
799 $this->assertEquals(transform::yesno(true), $grade['logged_in_user_was_you']);
800 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
801 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']);
803 // The action user 2 should have a record of their edits in the user's context.
805 provider::export_user_data(new approved_contextlist($ua2, 'core_grades', [$ug1ctx->id]));
806 $data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history');
807 $this->assertCount(3, $data->grades);
808 $grade = $data->grades[0];
809 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
810 $this->assertEquals(100, $grade['grade']);
811 $this->assertEquals('Well done!', $grade['feedback']);
812 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
813 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
814 $this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'), $grade['action']);
815 $grade = $data->grades[1];
816 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
817 $this->assertEquals(1, $grade['grade']);
818 $this->assertEquals('Hi', $grade['feedback']);
819 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
820 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
821 $this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'), $grade['action']);
822 $grade = $data->grades[2];
823 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
824 $this->assertEquals(1, $grade['grade']);
825 $this->assertEquals('Hi', $grade['feedback']);
826 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
827 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
828 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']);
831 public function test_export_data_for_user_with_scale() {
833 $dg = $this->getDataGenerator();
834 $c1 = $dg->create_course();
835 $scale = $dg->create_scale(['scale' => 'Awesome,OK,Reasonable,Bad']);
836 $u1 = $dg->create_user();
837 $u2 = $dg->create_user();
839 $u1ctx = context_user::instance($u1->id);
840 $c1ctx = context_course::instance($c1->id);
842 $rootpath = [get_string('grades', 'core_grades')];
844 // Create another set for another user.
845 $gi1 = new grade_item($dg->create_grade_item(['courseid' => $c1->id, 'scaleid' => $scale->id]), false);
846 $gi1->update_final_grade($u1->id, 1, 'test', '', FORMAT_PLAIN, $u2->id);
847 $gi2 = new grade_item($dg->create_grade_item(['courseid' => $c1->id, 'scaleid' => $scale->id]), false);
848 $gi2->update_final_grade($u1->id, 3, 'test', '', FORMAT_PLAIN, $u2->id);
850 // Export user's data.
852 provider::export_user_data(new approved_contextlist($u1, 'core_grades', [$c1ctx->id]));
853 $data = writer::with_context($c1ctx)->get_data($rootpath);
854 $this->assertCount(3, $data->grades);
855 $this->assertEquals(grade_item::fetch_course_item($c1->id)->get_name(), $data->grades[0]['item']);
856 $this->assertEquals($gi1->get_name(), $data->grades[1]['item']);
857 $this->assertEquals(1, $data->grades[1]['grade']);
858 $this->assertEquals('Awesome', $data->grades[1]['grade_formatted']);
859 $this->assertEquals($gi2->get_name(), $data->grades[2]['item']);
860 $this->assertEquals(3, $data->grades[2]['grade']);
861 $this->assertEquals('Reasonable', $data->grades[2]['grade_formatted']);
864 public function test_export_data_for_user_about_gradebook_edits() {
866 $dg = $this->getDataGenerator();
867 $c1 = $dg->create_course();
868 $c2 = $dg->create_course();
869 $u1 = $dg->create_user();
870 $u2 = $dg->create_user();
871 $u3 = $dg->create_user();
872 $u4 = $dg->create_user();
873 $u5 = $dg->create_user();
874 $u6 = $dg->create_user();
875 $u7 = $dg->create_user();
876 $u8 = $dg->create_user();
877 $u9 = $dg->create_user();
878 $u10 = $dg->create_user();
880 $sysctx = context_system::instance();
881 $u1ctx = context_user::instance($u1->id);
882 $u2ctx = context_user::instance($u2->id);
883 $u3ctx = context_user::instance($u3->id);
884 $u4ctx = context_user::instance($u4->id);
885 $u5ctx = context_user::instance($u5->id);
886 $u6ctx = context_user::instance($u6->id);
887 $c1ctx = context_course::instance($c1->id);
888 $c2ctx = context_course::instance($c2->id);
890 $rootpath = [get_string('grades', 'core_grades')];
891 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);
892 $allcontexts = [$sysctx->id, $c1ctx->id, $c2ctx->id, $u1ctx->id, $u2ctx->id, $u3ctx->id, $u4ctx->id,
893 $u5ctx->id, $u6ctx->id];
894 $updateactionstr = get_string('privacy:request:historyactionupdate', 'core_grades');
896 // Create some stuff.
897 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
898 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
899 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
900 $gc1a = new grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);
901 $gc1b = new grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);
902 $gc2a = new grade_category($dg->create_grade_category(['courseid' => $c2->id]), false);
903 $go2 = new grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2',
904 'fullname' => 'go2']), false);
906 $go0 = new grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]);
908 $go1 = new grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u1->id]);
912 $s1 = new grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']);
914 $s2 = new grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']);
916 $s3 = new grade_scale(['name' => 's3', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c2->id, 'description' => '']);
919 // User 2 creates history.
921 $go0->shortname .= ' edited';
923 $gc1a->fullname .= ' edited';
926 // User 3 creates history.
928 $go1->shortname .= ' edited';
930 $gc2a->fullname .= ' a';
933 // User 4 updates an outcome in course (creates history).
935 $go2->shortname .= ' edited';
938 // User 5 updates an item.
940 $gi1a->itemname .= ' edited';
943 // User 6 creates history.
947 // User 9 creates history.
949 $s1->name .= ' edited';
952 // User 10 creates history.
953 $this->setUser($u10);
956 $this->setAdminUser();
958 // Export data for u1.
960 provider::export_user_data(new approved_contextlist($u1, 'core_grades', $allcontexts));
961 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes');
962 $this->assertCount(1, $data->outcomes);
963 $this->assertEquals($go0->shortname, $data->outcomes[0]['shortname']);
964 $this->assertEquals($go0->fullname, $data->outcomes[0]['fullname']);
965 $this->assertEquals(transform::yesno(true), $data->outcomes[0]['created_or_modified_by_you']);
966 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes');
967 $this->assertCount(1, $data->outcomes);
968 $this->assertEquals($go1->shortname, $data->outcomes[0]['shortname']);
969 $this->assertEquals($go1->fullname, $data->outcomes[0]['fullname']);
970 $this->assertEquals(transform::yesno(true), $data->outcomes[0]['created_or_modified_by_you']);
971 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes_history');
972 $this->assertEmpty($data);
973 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes_history');
974 $this->assertEmpty($data);
976 // Export data for u2.
978 provider::export_user_data(new approved_contextlist($u2, 'core_grades', $allcontexts));
979 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes');
980 $this->assertEmpty($data);
981 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes');
982 $this->assertEmpty($data);
983 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes_history');
984 $this->assertCount(1, $data->modified_records);
985 $this->assertEquals($go0->shortname, $data->modified_records[0]['shortname']);
986 $this->assertEquals($go0->fullname, $data->modified_records[0]['fullname']);
987 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
988 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
990 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'categories_history');
991 $this->assertCount(1, $data->modified_records);
992 $this->assertEquals($gc1a->fullname, $data->modified_records[0]['name']);
993 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
994 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
996 // Export data for u3.
998 provider::export_user_data(new approved_contextlist($u3, 'core_grades', $allcontexts));
999 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes_history');
1000 $this->assertCount(1, $data->modified_records);
1001 $this->assertEquals($go1->shortname, $data->modified_records[0]['shortname']);
1002 $this->assertEquals($go1->fullname, $data->modified_records[0]['fullname']);
1003 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1004 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1006 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'categories_history');
1007 $this->assertCount(1, $data->modified_records);
1008 $this->assertEquals($gc2a->fullname, $data->modified_records[0]['name']);
1009 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1010 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1012 // Export data for u4.
1014 provider::export_user_data(new approved_contextlist($u4, 'core_grades', $allcontexts));
1015 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'outcomes_history');
1016 $this->assertCount(1, $data->modified_records);
1017 $this->assertEquals($go2->shortname, $data->modified_records[0]['shortname']);
1018 $this->assertEquals($go2->fullname, $data->modified_records[0]['fullname']);
1019 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1020 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1022 // Export data for u5.
1024 provider::export_user_data(new approved_contextlist($u5, 'core_grades', $allcontexts));
1025 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'items_history');
1026 $this->assertCount(1, $data->modified_records);
1027 $this->assertEquals($gi1a->itemname, $data->modified_records[0]['name']);
1028 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1029 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1031 // Export data for u6.
1033 provider::export_user_data(new approved_contextlist($u6, 'core_grades', $allcontexts));
1034 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'items_history');
1035 $this->assertEmpty($data);
1036 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'items_history');
1037 $this->assertCount(1, $data->modified_records);
1038 $this->assertEquals($gi2a->itemname, $data->modified_records[0]['name']);
1039 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1040 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'),
1041 $data->modified_records[0]['action']);
1043 // Export data for u7.
1045 provider::export_user_data(new approved_contextlist($u7, 'core_grades', $allcontexts));
1046 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');
1047 $this->assertEmpty($data);
1048 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');
1049 $this->assertCount(1, $data->scales);
1050 $this->assertEquals($s1->name, $data->scales[0]['name']);
1051 $this->assertEquals(transform::yesno(true), $data->scales[0]['created_or_modified_by_you']);
1053 // Export data for u8.
1055 provider::export_user_data(new approved_contextlist($u8, 'core_grades', $allcontexts));
1056 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');
1057 $this->assertEmpty($data);
1058 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');
1059 $this->assertCount(1, $data->scales);
1060 $this->assertEquals($s2->name, $data->scales[0]['name']);
1061 $this->assertEquals(transform::yesno(true), $data->scales[0]['created_or_modified_by_you']);
1062 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales_history');
1063 $this->assertCount(2, $data->modified_records);
1064 $this->assertEquals($s3->name, $data->modified_records[0]['name']);
1065 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_change_was_you']);
1066 $this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_action_was_you']);
1067 $this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'),
1068 $data->modified_records[0]['action']);
1069 $this->assertEquals($s3->name, $data->modified_records[1]['name']);
1070 $this->assertEquals(transform::yesno(true), $data->modified_records[1]['author_of_change_was_you']);
1071 $this->assertEquals(transform::yesno(false), $data->modified_records[1]['author_of_action_was_you']);
1072 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'),
1073 $data->modified_records[1]['action']);
1075 // Export data for u9.
1077 provider::export_user_data(new approved_contextlist($u9, 'core_grades', $allcontexts));
1078 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');
1079 $this->assertEmpty($data);
1080 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');
1081 $this->assertEmpty($data);
1082 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales_history');
1083 $this->assertCount(1, $data->modified_records);
1084 $this->assertEquals($s1->name, $data->modified_records[0]['name']);
1085 $this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_change_was_you']);
1086 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_action_was_you']);
1087 $this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'),
1088 $data->modified_records[0]['action']);
1090 // Export data for u10.
1092 provider::export_user_data(new approved_contextlist($u10, 'core_grades', $allcontexts));
1093 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');
1094 $this->assertEmpty($data);
1095 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales');
1096 $this->assertEmpty($data);
1097 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');
1098 $this->assertEmpty($data);
1099 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales_history');
1100 $this->assertEmpty($data);
1101 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales_history');
1102 $this->assertEmpty($data);
1103 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales_history');
1104 $this->assertCount(1, $data->modified_records);
1105 $this->assertEquals($s3->name, $data->modified_records[0]['name']);
1106 $this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_change_was_you']);
1107 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_action_was_you']);
1108 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'),
1109 $data->modified_records[0]['action']);
1113 * Assert there is no grade data in the context.
1115 * @param context $context The context.
1118 protected function assert_context_has_no_data(context $context) {
1119 $rootpath = [get_string('grades', 'core_grades')];
1120 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);
1122 $data = writer::with_context($context)->get_data($rootpath);
1123 $this->assertEmpty($data);
1125 $data = writer::with_context($context)->get_related_data($rootpath, 'history');
1126 $this->assertEmpty($data);
1128 $files = ['categories_history', 'items_history', 'outcomes', 'outcomes_history', 'grades', 'grades_history', 'history'];
1129 foreach ($files as $file) {
1130 $data = writer::with_context($context)->get_related_data($relatedtomepath, $file);
1131 $this->assertEmpty($data);