Merge branch 'MDL-70075-39-2' of git://github.com/andrewnicols/moodle into MOODLE_39_...
[moodle.git] / grade / tests / privacy_test.php
blobd9c2d485450b3937180b5e39c5d46c28ab388a47
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 /**
18 * Data provider tests.
20 * @package core_grades
21 * @category test
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();
28 global $CFG;
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');
38 /**
39 * Data provider testcase class.
41 * @package core_grades
42 * @category test
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() {
50 global $PAGE;
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);
77 // Create some stuff.
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);
87 // Nothing as of now.
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]);
94 $go0->insert();
95 $go1 = new grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u11->id]);
96 $go1->insert();
98 // Create scales.
99 $s1 = new grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']);
100 $s1->insert();
101 $s2 = new grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']);
102 $s2->insert();
104 // User 2 creates history.
105 $this->setUser($u2);
106 $go0->shortname .= ' edited';
107 $go0->update();
108 $gc1a->fullname .= ' edited';
109 $gc1a->update();
111 // User 3 creates history.
112 $this->setUser($u3);
113 $go1->shortname .= ' edited';
114 $go1->update();
115 $gc2a->fullname .= ' a';
116 $gc2a->update();
118 // User 4 updates an outcome in course (creates history).
119 $this->setUser($u4);
120 $go2->shortname .= ' edited';
121 $go2->update();
123 // User 5 updates an item.
124 $this->setUser($u5);
125 $gi1a->itemname .= ' edited';
126 $gi1a->update();
128 // User 6 creates history.
129 $this->setUser($u6);
130 $gi2a->delete();
132 // User 9 creates history.
133 $this->setUser($u9);
134 $s1->name .= ' edited';
135 $s1->update();
137 // Assert contexts.
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);
173 $s2->delete();
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..
219 $this->setUser($u4);
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.
223 $this->setUser($u5);
224 $gi2b->update_final_grade($u2->id, 1, 'test', '', FORMAT_PLAIN, $u6->id);
225 $gi2b->delete();
227 // Assert contexts.
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]);
287 $go0->insert();
288 $go1 = new grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u11->id]);
289 $go1->insert();
291 // Create scales.
292 $s1 = new grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']);
293 $s1->insert();
294 $s2 = new grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']);
295 $s2->insert();
297 // User 2 creates history.
298 $this->setUser($u2);
299 $go0->shortname .= ' edited';
300 $go0->update();
301 $gc1a->fullname .= ' edited';
302 $gc1a->update();
304 // User 3 creates history.
305 $this->setUser($u3);
306 $go1->shortname .= ' edited';
307 $go1->update();
308 $gc2a->fullname .= ' a';
309 $gc2a->update();
311 // User 4 updates an outcome in course (creates history).
312 $this->setUser($u4);
313 $go2->shortname .= ' edited';
314 $go2->update();
316 // User 5 updates an item.
317 $this->setUser($u5);
318 $gi1a->itemname .= ' edited';
319 $gi1a->update();
321 // User 6 creates history.
322 $this->setUser($u6);
323 $gi2a->delete();
325 // User 9 creates history.
326 $this->setUser($u9);
327 $s1->name .= ' edited';
328 $s1->update();
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..
382 $this->setUser($u4);
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.
386 $this->setUser($u5);
387 $gi2b->update_final_grade($u2->id, 1, 'test', '', FORMAT_PLAIN, $u6->id);
388 $gi2b->delete();
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() {
406 global $DB;
408 $fs = new file_storage();
410 $dg = $this->getDataGenerator();
412 $c1 = $dg->create_course();
413 $c2 = $dg->create_course();
414 $u1 = $dg->create_user();
415 $u2 = $dg->create_user();
416 $u1ctx = context_user::instance($u1->id);
417 $c1ctx = context_course::instance($c1->id);
418 $c2ctx = context_course::instance($c2->id);
420 $a1 = $dg->create_module('assign', ['course' => $c1->id]);
421 $a2 = $dg->create_module('assign', ['course' => $c1->id]);
422 $a3 = $dg->create_module('assign', ['course' => $c2->id]);
423 $a4 = $dg->create_module('assign', ['course' => $c2->id]);
425 $a1context = context_module::instance($a1->cmid);
426 $a2context = context_module::instance($a2->cmid);
427 $a3context = context_module::instance($a3->cmid);
428 $a4context = context_module::instance($a4->cmid);
430 // Create some stuff.
431 $gi1a = new grade_item($dg->create_grade_item(
433 'courseid' => $c1->id,
434 'itemtype' => 'mod',
435 'itemmodule' => 'assign',
436 'iteminstance' => $a1->id
438 ), false);
439 $gi1b = new grade_item($dg->create_grade_item(
441 'courseid' => $c1->id,
442 'itemtype' => 'mod',
443 'itemmodule' => 'assign',
444 'iteminstance' => $a2->id
446 ), false);
447 $gi2a = new grade_item($dg->create_grade_item(
449 'courseid' => $c2->id,
450 'itemtype' => 'mod',
451 'itemmodule' => 'assign',
452 'iteminstance' => $a3->id
454 ), false);
455 $gi2b = new grade_item($dg->create_grade_item(
457 'courseid' => $c2->id,
458 'itemtype' => 'mod',
459 'itemmodule' => 'assign',
460 'iteminstance' => $a4->id
462 ), false);
464 $this->add_feedback_file_to_copy();
466 $grades['feedback'] = 'Nice feedback!';
467 $grades['feedbackformat'] = FORMAT_MOODLE;
468 $grades['feedbackfiles'] = [
469 'contextid' => 1,
470 'component' => 'test',
471 'filearea' => 'testarea',
472 'itemid' => 1
475 $grades['userid'] = $u1->id;
476 grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance,
477 $gi1a->itemnumber, $grades);
479 $grades['userid'] = $u2->id;
480 grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance,
481 $gi1a->itemnumber, $grades);
483 $grades['userid'] = $u1->id;
484 grade_update('mod/assign', $gi1b->courseid, $gi1b->itemtype, $gi1b->itemmodule, $gi1b->iteminstance,
485 $gi1b->itemnumber, $grades);
487 $grades['userid'] = $u1->id;
488 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,
489 $gi2a->itemnumber, $grades);
491 $grades['userid'] = $u2->id;
492 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,
493 $gi2a->itemnumber, $grades);
495 $grades['userid'] = $u1->id;
496 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,
497 $gi2b->itemnumber, $grades);
499 $grades['userid'] = $u2->id;
500 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,
501 $gi2b->itemnumber, $grades);
502 $gi2b->delete();
504 // Feedback file area.
505 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
506 $this->assertEquals(4, count($files));
508 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
509 $this->assertEquals(2, count($files));
511 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
512 $this->assertEquals(4, count($files));
514 // Grade item 2 was deleted, so the associated files were as well.
515 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
516 $this->assertEquals(0, count($files));
518 // History file area.
519 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
520 $this->assertEquals(4, count($files));
522 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
523 $this->assertEquals(2, count($files));
525 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
526 $this->assertEquals(4, count($files));
528 // Grade item 2 was deleted, so the associated files were as well.
529 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
530 $this->assertEquals(0, count($files));
532 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
533 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
534 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
535 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
536 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
537 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
538 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
540 provider::delete_data_for_all_users_in_context($c1ctx);
541 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
542 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
543 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
544 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
545 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
546 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
547 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
549 // Feedback file area.
550 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
551 $this->assertEquals(0, count($files));
553 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
554 $this->assertEquals(0, count($files));
556 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
557 $this->assertEquals(4, count($files));
559 // Grade item 2 was deleted, so the associated files were as well.
560 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
561 $this->assertEquals(0, count($files));
563 // History file area.
564 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
565 $this->assertEquals(0, count($files));
567 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
568 $this->assertEquals(0, count($files));
570 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
571 $this->assertEquals(4, count($files));
573 // Grade item 2 was deleted, so the associated files were as well.
574 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
575 $this->assertEquals(0, count($files));
577 provider::delete_data_for_all_users_in_context($u1ctx);
578 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
579 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
580 $this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
581 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
583 // Feedback file area.
584 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
585 $this->assertEquals(0, count($files));
587 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
588 $this->assertEquals(0, count($files));
590 // The user context is only reported when there are orphan historical grades, so we only delete those files.
591 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
592 $this->assertEquals(4, count($files));
594 // Grade item 2 was deleted, so the associated files were as well.
595 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
596 $this->assertEquals(0, count($files));
598 // History file area.
599 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
600 $this->assertEquals(0, count($files));
602 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
603 $this->assertEquals(0, count($files));
605 // User 2 still has historical files.
606 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
607 $this->assertEquals(2, count($files));
609 // Grade item 2 was deleted, so the associated files were as well.
610 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
611 $this->assertEquals(0, count($files));
613 provider::delete_data_for_all_users_in_context($c2ctx);
614 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
615 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
616 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
618 // Feedback file area.
619 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
620 $this->assertEquals(0, count($files));
622 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
623 $this->assertEquals(0, count($files));
625 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
626 $this->assertEquals(0, count($files));
628 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
629 $this->assertEquals(0, count($files));
631 // History file area.
632 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
633 $this->assertEquals(0, count($files));
635 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
636 $this->assertEquals(0, count($files));
638 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
639 $this->assertEquals(0, count($files));
641 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
642 $this->assertEquals(0, count($files));
645 public function test_delete_data_for_user() {
646 global $DB;
648 $fs = new file_storage();
650 $dg = $this->getDataGenerator();
652 $c1 = $dg->create_course();
653 $c2 = $dg->create_course();
654 $u1 = $dg->create_user();
655 $u2 = $dg->create_user();
656 $u1ctx = context_user::instance($u1->id);
657 $u2ctx = context_user::instance($u2->id);
658 $c1ctx = context_course::instance($c1->id);
659 $c2ctx = context_course::instance($c2->id);
661 $a1 = $dg->create_module('assign', ['course' => $c1->id]);
662 $a2 = $dg->create_module('assign', ['course' => $c1->id]);
663 $a3 = $dg->create_module('assign', ['course' => $c2->id]);
664 $a4 = $dg->create_module('assign', ['course' => $c2->id]);
666 $a1context = context_module::instance($a1->cmid);
667 $a2context = context_module::instance($a2->cmid);
668 $a3context = context_module::instance($a3->cmid);
669 $a4context = context_module::instance($a4->cmid);
671 // Create some stuff.
672 $gi1a = new grade_item($dg->create_grade_item(
674 'courseid' => $c1->id,
675 'itemtype' => 'mod',
676 'itemmodule' => 'assign',
677 'iteminstance' => $a1->id
679 ), false);
680 $gi1b = new grade_item($dg->create_grade_item(
682 'courseid' => $c1->id,
683 'itemtype' => 'mod',
684 'itemmodule' => 'assign',
685 'iteminstance' => $a2->id
687 ), false);
688 $gi2a = new grade_item($dg->create_grade_item(
690 'courseid' => $c2->id,
691 'itemtype' => 'mod',
692 'itemmodule' => 'assign',
693 'iteminstance' => $a3->id
695 ), false);
696 $gi2b = new grade_item($dg->create_grade_item(
698 'courseid' => $c2->id,
699 'itemtype' => 'mod',
700 'itemmodule' => 'assign',
701 'iteminstance' => $a4->id
703 ), false);
705 $this->add_feedback_file_to_copy();
707 $grades['feedback'] = 'Nice feedback!';
708 $grades['feedbackfiles'] = [
709 'contextid' => 1,
710 'component' => 'test',
711 'filearea' => 'testarea',
712 'itemid' => 1
715 $grades['userid'] = $u1->id;
716 grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance,
717 $gi1a->itemnumber, $grades);
719 $grades['userid'] = $u2->id;
720 grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance,
721 $gi1a->itemnumber, $grades);
723 $grades['userid'] = $u1->id;
724 grade_update('mod/assign', $gi1b->courseid, $gi1b->itemtype, $gi1b->itemmodule, $gi1b->iteminstance,
725 $gi1b->itemnumber, $grades);
727 $grades['userid'] = $u1->id;
728 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,
729 $gi2a->itemnumber, $grades);
731 $grades['userid'] = $u2->id;
732 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,
733 $gi2a->itemnumber, $grades);
735 $grades['userid'] = $u1->id;
736 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,
737 $gi2b->itemnumber, $grades);
739 $grades['userid'] = $u2->id;
740 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,
741 $gi2b->itemnumber, $grades);
743 $gi2b->delete();
745 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
746 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
747 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
748 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
749 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
750 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
751 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
753 // Feedback file area.
754 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
755 $this->assertEquals(4, count($files));
757 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
758 $this->assertEquals(2, count($files));
760 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
761 $this->assertEquals(4, count($files));
763 // Grade item 2 was deleted, so the associated files were as well.
764 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
765 $this->assertEquals(0, count($files));
767 // History file area.
768 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
769 $this->assertEquals(4, count($files));
771 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
772 $this->assertEquals(2, count($files));
774 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
775 $this->assertEquals(4, count($files));
777 // Grade item 2 was deleted, so the associated files were as well.
778 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
779 $this->assertEquals(0, count($files));
781 provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$c1ctx->id]));
782 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
783 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
784 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
785 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
786 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
787 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
788 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
790 // Feedback file area.
791 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
792 $this->assertEquals(2, count($files));
794 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
795 $this->assertEquals(0, count($files));
797 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
798 $this->assertEquals(4, count($files));
800 // Grade item 2 was deleted, so the associated files were as well.
801 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
802 $this->assertEquals(0, count($files));
804 // History file area.
805 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
806 $this->assertEquals(2, count($files));
808 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
809 $this->assertEquals(0, count($files));
811 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
812 $this->assertEquals(4, count($files));
814 // Grade item 2 was deleted, so the associated files were as well.
815 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
816 $this->assertEquals(0, count($files));
818 provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$u1ctx->id]));
819 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
820 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
821 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
822 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
823 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
824 $this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
825 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
827 // Feedback file area.
828 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
829 $this->assertEquals(2, count($files));
831 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
832 $this->assertEquals(0, count($files));
834 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
835 $this->assertEquals(4, count($files));
837 // Grade item 2 was deleted, so the associated files were as well.
838 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
839 $this->assertEquals(0, count($files));
841 // History file area.
842 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
843 $this->assertEquals(2, count($files));
845 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
846 $this->assertEquals(0, count($files));
848 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
849 $this->assertEquals(2, count($files));
851 // Grade item 2 was deleted, so the associated files were as well.
852 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
853 $this->assertEquals(0, count($files));
855 provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$u2ctx->id, $c2ctx->id]));
856 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
857 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
858 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
859 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
860 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
861 $this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
862 $this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
864 // Feedback file area.
865 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
866 $this->assertEquals(2, count($files));
868 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
869 $this->assertEquals(0, count($files));
871 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
872 $this->assertEquals(2, count($files));
874 // Grade item 2 was deleted, so the associated files were as well.
875 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);
876 $this->assertEquals(0, count($files));
878 // History file area.
879 $files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
880 $this->assertEquals(2, count($files));
882 $files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
883 $this->assertEquals(0, count($files));
885 $files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
886 $this->assertEquals(2, count($files));
888 // Grade item 2 was deleted, so the associated files were as well.
889 $files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);
890 $this->assertEquals(0, count($files));
894 * Test deleting multiple users for a context works.
896 public function test_delete_data_for_users() {
897 global $DB;
898 $dg = $this->getDataGenerator();
900 $c1 = $dg->create_course();
901 $c2 = $dg->create_course();
902 $u1 = $dg->create_user();
903 $u2 = $dg->create_user();
904 $u3 = $dg->create_user();
905 $u4 = $dg->create_user();
906 $u1ctx = context_user::instance($u1->id);
907 $u2ctx = context_user::instance($u2->id);
908 $c1ctx = context_course::instance($c1->id);
909 $c2ctx = context_course::instance($c2->id);
911 // Create some stuff.
912 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
913 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
914 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
915 $gi2b = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
917 $gi1a->update_final_grade($u1->id, 1, 'test');
918 $gi1a->update_final_grade($u2->id, 1, 'test');
919 $gi1a->update_final_grade($u3->id, 1, 'test');
920 $gi1b->update_final_grade($u1->id, 1, 'test');
921 $gi1b->update_final_grade($u4->id, 1, 'test');
922 $gi2a->update_final_grade($u1->id, 1, 'test');
923 $gi2a->update_final_grade($u2->id, 1, 'test');
924 $gi2a->update_final_grade($u4->id, 1, 'test');
925 $gi2b->update_final_grade($u1->id, 1, 'test');
926 $gi2b->update_final_grade($u2->id, 1, 'test');
927 $gi2b->update_final_grade($u3->id, 1, 'test');
928 $gi2b->delete();
930 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
931 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
932 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id]));
933 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
934 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id]));
935 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
936 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
937 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id]));
938 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2b->id]));
939 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2b->id]));
940 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi2b->id]));
942 $userlist = new \core_privacy\local\request\approved_userlist($c1ctx, 'core_grades', [$u1->id, $u2->id]);
943 provider::delete_data_for_users($userlist);
945 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
946 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
947 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id]));
948 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
949 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id]));
950 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
951 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
952 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id]));
954 $userlist = new \core_privacy\local\request\approved_userlist($c2ctx, 'core_grades', [$u2->id, $u4->id]);
955 provider::delete_data_for_users($userlist);
957 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));
958 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));
959 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id]));
960 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));
961 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id]));
962 $this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));
963 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));
964 $this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id]));
967 public function test_export_data_for_user_about_grades_and_history() {
968 $dg = $this->getDataGenerator();
970 $c1 = $dg->create_course();
971 $c2 = $dg->create_course();
973 // Users being graded.
974 $ug1 = $dg->create_user();
975 $ug2 = $dg->create_user();
976 $ug3 = $dg->create_user();
977 // Users performing actions.
978 $ua1 = $dg->create_user();
979 $ua2 = $dg->create_user();
980 $ua3 = $dg->create_user();
982 $ug1ctx = context_user::instance($ug1->id);
983 $ug2ctx = context_user::instance($ug2->id);
984 $c1ctx = context_course::instance($c1->id);
985 $c2ctx = context_course::instance($c2->id);
987 $rootpath = [get_string('grades', 'core_grades')];
988 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);
990 // Create the course minimal stuff.
991 grade_category::fetch_course_category($c1->id);
992 $ci1 = grade_item::fetch_course_item($c1->id);
993 grade_category::fetch_course_category($c2->id);
994 $ci2 = grade_item::fetch_course_item($c2->id);
996 $this->add_feedback_file_to_copy();
998 $grades['feedbackfiles'] = [
999 'contextid' => 1,
1000 'component' => 'test',
1001 'filearea' => 'testarea',
1002 'itemid' => 1
1005 $a1 = $dg->create_module('assign', ['course' => $c1->id]);
1007 // Create data that will sit in the user context because we will delete the grate item.
1008 $gi1 = new grade_item($dg->create_grade_item(
1010 'courseid' => $c1->id,
1011 'itemtype' => 'mod',
1012 'itemmodule' => 'assign',
1013 'iteminstance' => $a1->id,
1014 'aggregationcoef2' => 1
1016 ), false);
1018 $grades['feedback'] = 'Well done!';
1019 $grades['feedbackformat'] = FORMAT_PLAIN;
1020 $grades['userid'] = $ug1->id;
1021 $grades['usermodified'] = $ua2->id;
1022 $grades['rawgrade'] = 100;
1023 grade_update('mod/assign', $gi1->courseid, $gi1->itemtype, $gi1->itemmodule, $gi1->iteminstance,
1024 $gi1->itemnumber, $grades);
1026 $grades['feedback'] = 'Hi';
1027 $grades['userid'] = $ug1->id;
1028 $grades['usermodified'] = $ua2->id;
1029 $grades['rawgrade'] = 1;
1030 grade_update('mod/assign', $gi1->courseid, $gi1->itemtype, $gi1->itemmodule, $gi1->iteminstance,
1031 $gi1->itemnumber, $grades);
1033 $grades['feedback'] = 'Hello';
1034 $grades['userid'] = $ug3->id;
1035 $grades['usermodified'] = $ua2->id;
1036 $grades['rawgrade'] = 12;
1037 grade_update('mod/assign', $gi1->courseid, $gi1->itemtype, $gi1->itemmodule, $gi1->iteminstance,
1038 $gi1->itemnumber, $grades);
1040 // Create another set for another user.
1041 $a2 = $dg->create_module('assign', ['course' => $c2->id]);
1042 $a3 = $dg->create_module('assign', ['course' => $c2->id]);
1043 $gi2a = new grade_item($dg->create_grade_item(
1045 'courseid' => $c2->id,
1046 'itemtype' => 'mod',
1047 'itemmodule' => 'assign',
1048 'iteminstance' => $a2->id
1050 ), false);
1051 $gi2b = new grade_item($dg->create_grade_item(
1053 'courseid' => $c2->id,
1054 'itemtype' => 'mod',
1055 'itemmodule' => 'assign',
1056 'iteminstance' => $a3->id
1058 ), false);
1060 $grades['feedback'] = '';
1061 $grades['userid'] = $ug1->id;
1062 $grades['usermodified'] = $ua2->id;
1063 $grades['rawgrade'] = 15;
1064 grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,
1065 $gi2a->itemnumber, $grades);
1067 $grades['feedback'] = 'Well played!';
1068 $grades['userid'] = $ug1->id;
1069 $grades['usermodified'] = $ua2->id;
1070 $grades['rawgrade'] = 30;
1071 grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,
1072 $gi2b->itemnumber, $grades);
1074 // Export action user 1 everywhere.
1075 provider::export_user_data(new approved_contextlist($ua1, 'core_grades', [$ug1ctx->id, $ug2ctx->id,
1076 $c1ctx->id, $c2ctx->id]));
1077 $this->assert_context_has_no_data($ug1ctx);
1078 $this->assert_context_has_no_data($ug2ctx);
1079 $this->assert_context_has_no_data($c1ctx);
1080 $this->assert_context_has_no_data($c2ctx);
1082 // Export action user 2 in course 1.
1083 writer::reset();
1084 provider::export_user_data(new approved_contextlist($ua2, 'core_grades', [$c1ctx->id]));
1085 $this->assert_context_has_no_data($ug1ctx);
1086 $this->assert_context_has_no_data($ug2ctx);
1087 $this->assert_context_has_no_data($c2ctx);
1088 $data = writer::with_context($c1ctx)->get_data($rootpath);
1089 $this->assertEmpty($data);
1091 // Here we are testing the export of grades that we've changed.
1092 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades');
1093 $this->assertCount(2, $data->grades);
1094 $this->assertEquals($gi1->get_name(), $data->grades[0]['item']);
1095 $this->assertEquals(1, $data->grades[0]['grade']);
1096 $this->assertEquals('Hi', $data->grades[0]['feedback']);
1097 $this->assertEquals(transform::yesno(true), $data->grades[0]['created_or_modified_by_you']);
1098 $this->assertEquals($gi1->get_name(), $data->grades[1]['item']);
1099 $this->assertEquals(12, $data->grades[1]['grade']);
1100 $this->assertEquals('Hello', $data->grades[1]['feedback']);
1101 $this->assertEquals(transform::yesno(true), $data->grades[1]['created_or_modified_by_you']);
1103 $pathtofiles = [
1104 get_string('grades', 'core_grades'),
1105 get_string('feedbackfiles', 'core_grades')
1107 $file = writer::with_context($gi1->get_context())->get_files($pathtofiles)['feedback1.txt'];
1109 $this->assertInstanceOf('stored_file', $file);
1110 $this->assertEquals('feedback1.txt', $file->get_filename());
1112 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);
1114 // Here we are testing the export of history of grades that we've changed.
1115 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades_history');
1116 $this->assertCount(3, $data->modified_records);
1117 $grade = $data->modified_records[0];
1118 $this->assertEquals($ug1->id, $grade['userid']);
1119 $this->assertEquals($gi1->get_name(), $grade['item']);
1120 $this->assertEquals(100, $grade['grade']);
1121 $this->assertEquals('Well done!', $grade['feedback']);
1122 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
1123 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
1124 $grade = $data->modified_records[1];
1125 $this->assertEquals($ug1->id, $grade['userid']);
1126 $this->assertEquals($gi1->get_name(), $grade['item']);
1127 $this->assertEquals(1, $grade['grade']);
1128 $this->assertEquals('Hi', $grade['feedback']);
1129 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
1130 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
1131 $grade = $data->modified_records[2];
1132 $this->assertEquals($ug3->id, $grade['userid']);
1133 $this->assertEquals($gi1->get_name(), $grade['item']);
1134 $this->assertEquals(12, $grade['grade']);
1135 $this->assertEquals('Hello', $grade['feedback']);
1136 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
1137 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
1139 $pathtofiles = [
1140 get_string('grades', 'core_grades'),
1141 get_string('feedbackhistoryfiles', 'core_grades')
1143 $file = writer::with_context($gi1->get_context())->get_files($pathtofiles)['feedback1.txt'];
1145 $this->assertInstanceOf('stored_file', $file);
1146 $this->assertEquals('feedback1.txt', $file->get_filename());
1148 // Create a history record with logged user.
1149 $this->setUser($ua3);
1150 $gi1->update_final_grade($ug3->id, 50, 'test', '...', FORMAT_PLAIN, $ua2->id);
1151 writer::reset();
1152 provider::export_user_data(new approved_contextlist($ua3, 'core_grades', [$c1ctx->id]));
1153 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades_history');
1154 $this->assertCount(1, $data->modified_records);
1155 $grade = $data->modified_records[0];
1156 $this->assertEquals($ug3->id, $grade['userid']);
1157 $this->assertEquals($gi1->get_name(), $grade['item']);
1158 $this->assertEquals(50, $grade['grade']);
1159 $this->assertEquals('...', $grade['feedback']);
1160 $this->assertEquals(transform::yesno(true), $grade['logged_in_user_was_you']);
1161 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
1163 // Test that we export our own grades.
1164 writer::reset();
1165 provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$c1ctx->id]));
1166 $data = writer::with_context($c1ctx)->get_data($rootpath);
1167 $this->assert_context_has_no_data($c2ctx);
1168 $this->assertCount(3, $data->grades);
1169 $grade = $data->grades[0];
1170 $this->assertEquals($ci1->get_name(), $grade['item']);
1171 $this->assertEquals(1, $grade['grade']);
1172 $grade = $data->grades[2];
1173 $this->assertEquals($gi1->get_name(), $grade['item']);
1174 $this->assertEquals(1, $grade['grade']);
1175 $this->assertEquals('Hi', $grade['feedback']);
1177 // Test that we export our own grades in two courses.
1178 writer::reset();
1179 provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$ug1ctx->id, $c1ctx->id, $c2ctx->id]));
1180 $this->assert_context_has_no_data($ug1ctx);
1181 $data = writer::with_context($c1ctx)->get_data($rootpath);
1182 $this->assertCount(3, $data->grades);
1183 $grade = $data->grades[0];
1184 $this->assertEquals($ci1->get_name(), $grade['item']);
1185 $this->assertEquals(1, $grade['grade']);
1186 $grade = $data->grades[2];
1187 $this->assertEquals($gi1->get_name(), $grade['item']);
1188 $this->assertEquals(1, $grade['grade']);
1189 $this->assertEquals('Hi', $grade['feedback']);
1191 $data = writer::with_context($c2ctx)->get_data($rootpath);
1192 $this->assertCount(5, $data->grades);
1193 $grade = $data->grades[0];
1194 $this->assertEquals($ci2->get_name(), $grade['item']);
1195 $grade = $data->grades[3];
1196 $this->assertEquals($gi2a->get_name(), $grade['item']);
1197 $this->assertEquals(15, $grade['grade']);
1198 $this->assertEquals('', $grade['feedback']);
1199 $grade = $data->grades[4];
1200 $this->assertEquals($gi2b->get_name(), $grade['item']);
1201 $this->assertEquals(30, $grade['grade']);
1202 $this->assertEquals('Well played!', $grade['feedback']);
1204 // Delete a grade item.
1205 $this->setUser($ua3);
1206 $gi1->delete();
1208 // Now, we should find history of grades in our own context.
1209 writer::reset();
1210 provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$ug1ctx->id, $c1ctx->id, $c2ctx->id]));
1211 $data = writer::with_context($c1ctx)->get_data($rootpath);
1212 $this->assertCount(2, $data->grades);
1213 $this->assertEquals($ci1->get_name(), $data->grades[0]['item']);
1214 $data = writer::with_context($c2ctx)->get_data($rootpath);
1215 $this->assertCount(5, $data->grades);
1216 $data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history');
1217 $this->assertCount(3, $data->grades);
1218 $grade = $data->grades[0];
1219 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
1220 $this->assertEquals(100, $grade['grade']);
1221 $this->assertEquals('Well done!', $grade['feedback']);
1222 $this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']);
1223 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
1224 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
1225 $this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'), $grade['action']);
1226 $grade = $data->grades[1];
1227 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
1228 $this->assertEquals(1, $grade['grade']);
1229 $this->assertEquals('Hi', $grade['feedback']);
1230 $this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']);
1231 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
1232 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
1233 $this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'), $grade['action']);
1234 $grade = $data->grades[2];
1235 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
1236 $this->assertEquals(1, $grade['grade']);
1237 $this->assertEquals('Hi', $grade['feedback']);
1238 $this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']);
1239 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
1240 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
1241 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']);
1243 // The action user 3 should have a record of the deletion in the user's context.
1244 writer::reset();
1245 provider::export_user_data(new approved_contextlist($ua3, 'core_grades', [$ug1ctx->id]));
1246 $data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history');
1247 $this->assertCount(1, $data->grades);
1248 $grade = $data->grades[0];
1249 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
1250 $this->assertEquals(1, $grade['grade']);
1251 $this->assertEquals('Hi', $grade['feedback']);
1252 $this->assertEquals(transform::yesno(true), $grade['logged_in_user_was_you']);
1253 $this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);
1254 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']);
1256 // The action user 2 should have a record of their edits in the user's context.
1257 writer::reset();
1258 provider::export_user_data(new approved_contextlist($ua2, 'core_grades', [$ug1ctx->id]));
1259 $data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history');
1260 $this->assertCount(3, $data->grades);
1261 $grade = $data->grades[0];
1262 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
1263 $this->assertEquals(100, $grade['grade']);
1264 $this->assertEquals('Well done!', $grade['feedback']);
1265 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
1266 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
1267 $this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'), $grade['action']);
1268 $grade = $data->grades[1];
1269 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
1270 $this->assertEquals(1, $grade['grade']);
1271 $this->assertEquals('Hi', $grade['feedback']);
1272 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
1273 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
1274 $this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'), $grade['action']);
1275 $grade = $data->grades[2];
1276 $this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);
1277 $this->assertEquals(1, $grade['grade']);
1278 $this->assertEquals('Hi', $grade['feedback']);
1279 $this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);
1280 $this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);
1281 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']);
1284 public function test_export_data_for_user_with_scale() {
1285 global $DB;
1286 $dg = $this->getDataGenerator();
1287 $c1 = $dg->create_course();
1288 $scale = $dg->create_scale(['scale' => 'Awesome,OK,Reasonable,Bad']);
1289 $u1 = $dg->create_user();
1290 $u2 = $dg->create_user();
1292 $u1ctx = context_user::instance($u1->id);
1293 $c1ctx = context_course::instance($c1->id);
1295 $rootpath = [get_string('grades', 'core_grades')];
1297 // Create another set for another user.
1298 $gi1 = new grade_item($dg->create_grade_item(['courseid' => $c1->id, 'scaleid' => $scale->id]), false);
1299 $gi1->update_final_grade($u1->id, 1, 'test', '', FORMAT_PLAIN, $u2->id);
1300 $gi2 = new grade_item($dg->create_grade_item(['courseid' => $c1->id, 'scaleid' => $scale->id]), false);
1301 $gi2->update_final_grade($u1->id, 3, 'test', '', FORMAT_PLAIN, $u2->id);
1303 // Export user's data.
1304 writer::reset();
1305 provider::export_user_data(new approved_contextlist($u1, 'core_grades', [$c1ctx->id]));
1306 $data = writer::with_context($c1ctx)->get_data($rootpath);
1307 $this->assertCount(3, $data->grades);
1308 $this->assertEquals(grade_item::fetch_course_item($c1->id)->get_name(), $data->grades[0]['item']);
1309 $this->assertEquals($gi1->get_name(), $data->grades[1]['item']);
1310 $this->assertEquals(1, $data->grades[1]['grade']);
1311 $this->assertEquals('Awesome', $data->grades[1]['grade_formatted']);
1312 $this->assertEquals($gi2->get_name(), $data->grades[2]['item']);
1313 $this->assertEquals(3, $data->grades[2]['grade']);
1314 $this->assertEquals('Reasonable', $data->grades[2]['grade_formatted']);
1317 public function test_export_data_for_user_about_gradebook_edits() {
1318 global $DB;
1319 $dg = $this->getDataGenerator();
1320 $c1 = $dg->create_course();
1321 $c2 = $dg->create_course();
1322 $u1 = $dg->create_user();
1323 $u2 = $dg->create_user();
1324 $u3 = $dg->create_user();
1325 $u4 = $dg->create_user();
1326 $u5 = $dg->create_user();
1327 $u6 = $dg->create_user();
1328 $u7 = $dg->create_user();
1329 $u8 = $dg->create_user();
1330 $u9 = $dg->create_user();
1331 $u10 = $dg->create_user();
1333 $sysctx = context_system::instance();
1334 $u1ctx = context_user::instance($u1->id);
1335 $u2ctx = context_user::instance($u2->id);
1336 $u3ctx = context_user::instance($u3->id);
1337 $u4ctx = context_user::instance($u4->id);
1338 $u5ctx = context_user::instance($u5->id);
1339 $u6ctx = context_user::instance($u6->id);
1340 $c1ctx = context_course::instance($c1->id);
1341 $c2ctx = context_course::instance($c2->id);
1343 $rootpath = [get_string('grades', 'core_grades')];
1344 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);
1345 $allcontexts = [$sysctx->id, $c1ctx->id, $c2ctx->id, $u1ctx->id, $u2ctx->id, $u3ctx->id, $u4ctx->id,
1346 $u5ctx->id, $u6ctx->id];
1347 $updateactionstr = get_string('privacy:request:historyactionupdate', 'core_grades');
1349 // Create some stuff.
1350 $gi1a = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
1351 $gi1b = new grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);
1352 $gi2a = new grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);
1353 $gc1a = new grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);
1354 $gc1b = new grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);
1355 $gc2a = new grade_category($dg->create_grade_category(['courseid' => $c2->id]), false);
1356 $go2 = new grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2',
1357 'fullname' => 'go2']), false);
1359 $go0 = new grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]);
1360 $go0->insert();
1361 $go1 = new grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u1->id]);
1362 $go1->insert();
1364 // Create scales.
1365 $s1 = new grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']);
1366 $s1->insert();
1367 $s2 = new grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']);
1368 $s2->insert();
1369 $s3 = new grade_scale(['name' => 's3', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c2->id, 'description' => '']);
1370 $s3->insert();
1372 // User 2 creates history.
1373 $this->setUser($u2);
1374 $go0->shortname .= ' edited';
1375 $go0->update();
1376 $gc1a->fullname .= ' edited';
1377 $gc1a->update();
1379 // User 3 creates history.
1380 $this->setUser($u3);
1381 $go1->shortname .= ' edited';
1382 $go1->update();
1383 $gc2a->fullname .= ' a';
1384 $gc2a->update();
1386 // User 4 updates an outcome in course (creates history).
1387 $this->setUser($u4);
1388 $go2->shortname .= ' edited';
1389 $go2->update();
1391 // User 5 updates an item.
1392 $this->setUser($u5);
1393 $gi1a->itemname .= ' edited';
1394 $gi1a->update();
1396 // User 6 creates history.
1397 $this->setUser($u6);
1398 $gi2a->delete();
1400 // User 9 creates history.
1401 $this->setUser($u9);
1402 $s1->name .= ' edited';
1403 $s1->update();
1405 // User 10 creates history.
1406 $this->setUser($u10);
1407 $s3->delete();
1409 $this->setAdminUser();
1411 // Export data for u1.
1412 writer::reset();
1413 provider::export_user_data(new approved_contextlist($u1, 'core_grades', $allcontexts));
1414 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes');
1415 $this->assertCount(1, $data->outcomes);
1416 $this->assertEquals($go0->shortname, $data->outcomes[0]['shortname']);
1417 $this->assertEquals($go0->fullname, $data->outcomes[0]['fullname']);
1418 $this->assertEquals(transform::yesno(true), $data->outcomes[0]['created_or_modified_by_you']);
1419 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes');
1420 $this->assertCount(1, $data->outcomes);
1421 $this->assertEquals($go1->shortname, $data->outcomes[0]['shortname']);
1422 $this->assertEquals($go1->fullname, $data->outcomes[0]['fullname']);
1423 $this->assertEquals(transform::yesno(true), $data->outcomes[0]['created_or_modified_by_you']);
1424 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes_history');
1425 $this->assertEmpty($data);
1426 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes_history');
1427 $this->assertEmpty($data);
1429 // Export data for u2.
1430 writer::reset();
1431 provider::export_user_data(new approved_contextlist($u2, 'core_grades', $allcontexts));
1432 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes');
1433 $this->assertEmpty($data);
1434 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes');
1435 $this->assertEmpty($data);
1436 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes_history');
1437 $this->assertCount(1, $data->modified_records);
1438 $this->assertEquals($go0->shortname, $data->modified_records[0]['shortname']);
1439 $this->assertEquals($go0->fullname, $data->modified_records[0]['fullname']);
1440 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1441 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1443 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'categories_history');
1444 $this->assertCount(1, $data->modified_records);
1445 $this->assertEquals($gc1a->fullname, $data->modified_records[0]['name']);
1446 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1447 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1449 // Export data for u3.
1450 writer::reset();
1451 provider::export_user_data(new approved_contextlist($u3, 'core_grades', $allcontexts));
1452 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes_history');
1453 $this->assertCount(1, $data->modified_records);
1454 $this->assertEquals($go1->shortname, $data->modified_records[0]['shortname']);
1455 $this->assertEquals($go1->fullname, $data->modified_records[0]['fullname']);
1456 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1457 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1459 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'categories_history');
1460 $this->assertCount(1, $data->modified_records);
1461 $this->assertEquals($gc2a->fullname, $data->modified_records[0]['name']);
1462 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1463 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1465 // Export data for u4.
1466 writer::reset();
1467 provider::export_user_data(new approved_contextlist($u4, 'core_grades', $allcontexts));
1468 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'outcomes_history');
1469 $this->assertCount(1, $data->modified_records);
1470 $this->assertEquals($go2->shortname, $data->modified_records[0]['shortname']);
1471 $this->assertEquals($go2->fullname, $data->modified_records[0]['fullname']);
1472 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1473 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1475 // Export data for u5.
1476 writer::reset();
1477 provider::export_user_data(new approved_contextlist($u5, 'core_grades', $allcontexts));
1478 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'items_history');
1479 $this->assertCount(1, $data->modified_records);
1480 $this->assertEquals($gi1a->itemname, $data->modified_records[0]['name']);
1481 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1482 $this->assertEquals($updateactionstr, $data->modified_records[0]['action']);
1484 // Export data for u6.
1485 writer::reset();
1486 provider::export_user_data(new approved_contextlist($u6, 'core_grades', $allcontexts));
1487 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'items_history');
1488 $this->assertEmpty($data);
1489 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'items_history');
1490 $this->assertCount(1, $data->modified_records);
1491 $this->assertEquals($gi2a->itemname, $data->modified_records[0]['name']);
1492 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);
1493 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'),
1494 $data->modified_records[0]['action']);
1496 // Export data for u7.
1497 writer::reset();
1498 provider::export_user_data(new approved_contextlist($u7, 'core_grades', $allcontexts));
1499 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');
1500 $this->assertEmpty($data);
1501 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');
1502 $this->assertCount(1, $data->scales);
1503 $this->assertEquals($s1->name, $data->scales[0]['name']);
1504 $this->assertEquals(transform::yesno(true), $data->scales[0]['created_or_modified_by_you']);
1506 // Export data for u8.
1507 writer::reset();
1508 provider::export_user_data(new approved_contextlist($u8, 'core_grades', $allcontexts));
1509 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');
1510 $this->assertEmpty($data);
1511 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');
1512 $this->assertCount(1, $data->scales);
1513 $this->assertEquals($s2->name, $data->scales[0]['name']);
1514 $this->assertEquals(transform::yesno(true), $data->scales[0]['created_or_modified_by_you']);
1515 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales_history');
1516 $this->assertCount(2, $data->modified_records);
1517 $this->assertEquals($s3->name, $data->modified_records[0]['name']);
1518 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_change_was_you']);
1519 $this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_action_was_you']);
1520 $this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'),
1521 $data->modified_records[0]['action']);
1522 $this->assertEquals($s3->name, $data->modified_records[1]['name']);
1523 $this->assertEquals(transform::yesno(true), $data->modified_records[1]['author_of_change_was_you']);
1524 $this->assertEquals(transform::yesno(false), $data->modified_records[1]['author_of_action_was_you']);
1525 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'),
1526 $data->modified_records[1]['action']);
1528 // Export data for u9.
1529 writer::reset();
1530 provider::export_user_data(new approved_contextlist($u9, 'core_grades', $allcontexts));
1531 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');
1532 $this->assertEmpty($data);
1533 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');
1534 $this->assertEmpty($data);
1535 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales_history');
1536 $this->assertCount(1, $data->modified_records);
1537 $this->assertEquals($s1->name, $data->modified_records[0]['name']);
1538 $this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_change_was_you']);
1539 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_action_was_you']);
1540 $this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'),
1541 $data->modified_records[0]['action']);
1543 // Export data for u10.
1544 writer::reset();
1545 provider::export_user_data(new approved_contextlist($u10, 'core_grades', $allcontexts));
1546 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');
1547 $this->assertEmpty($data);
1548 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales');
1549 $this->assertEmpty($data);
1550 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');
1551 $this->assertEmpty($data);
1552 $data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales_history');
1553 $this->assertEmpty($data);
1554 $data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales_history');
1555 $this->assertEmpty($data);
1556 $data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales_history');
1557 $this->assertCount(1, $data->modified_records);
1558 $this->assertEquals($s3->name, $data->modified_records[0]['name']);
1559 $this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_change_was_you']);
1560 $this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_action_was_you']);
1561 $this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'),
1562 $data->modified_records[0]['action']);
1566 * Assert there is no grade data in the context.
1568 * @param context $context The context.
1569 * @return void
1571 protected function assert_context_has_no_data(context $context) {
1572 $rootpath = [get_string('grades', 'core_grades')];
1573 $relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);
1575 $data = writer::with_context($context)->get_data($rootpath);
1576 $this->assertEmpty($data);
1578 $data = writer::with_context($context)->get_related_data($rootpath, 'history');
1579 $this->assertEmpty($data);
1581 $files = ['categories_history', 'items_history', 'outcomes', 'outcomes_history', 'grades', 'grades_history', 'history'];
1582 foreach ($files as $file) {
1583 $data = writer::with_context($context)->get_related_data($relatedtomepath, $file);
1584 $this->assertEmpty($data);
1589 * Creates a feedback file to copy to the gradebook area.
1591 private function add_feedback_file_to_copy() {
1592 $dummy = array(
1593 'contextid' => 1,
1594 'component' => 'test',
1595 'filearea' => 'testarea',
1596 'itemid' => 1,
1597 'filepath' => '/',
1598 'filename' => 'feedback1.txt'
1601 $fs = get_file_storage();
1602 $fs->create_file_from_string($dummy, '');