Rev 1 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** Data provider tests.** @package core_grades* @category test* @copyright 2018 Frédéric Massart* @author Frédéric Massart <fred@branchup.tech>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/namespace core_grades\privacy;defined('MOODLE_INTERNAL') || die();global $CFG;use core_privacy\tests\provider_testcase;use core_privacy\local\request\approved_contextlist;use core_privacy\local\request\transform;use core_privacy\local\request\writer;use core_grades\privacy\provider;require_once($CFG->libdir . '/gradelib.php');/*** Data provider testcase class.** @package core_grades* @category test* @copyright 2018 Frédéric Massart* @author Frédéric Massart <fred@branchup.tech>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later* @covers \core_grades\privacy\provider*/class provider_test extends provider_testcase {public function setUp(): void {global $PAGE;$this->resetAfterTest();$PAGE->get_renderer('core');}public function test_get_contexts_for_userid_gradebook_edits(): void {$dg = $this->getDataGenerator();$c1 = $dg->create_course();$c2 = $dg->create_course();$u1 = $dg->create_user();$u2 = $dg->create_user();$u3 = $dg->create_user();$u4 = $dg->create_user();$u5 = $dg->create_user();$u6 = $dg->create_user();$u7 = $dg->create_user();$u8 = $dg->create_user();$u9 = $dg->create_user();$u10 = $dg->create_user();$u11 = $dg->create_user();$sysctx = \context_system::instance();$c1ctx = \context_course::instance($c1->id);$c2ctx = \context_course::instance($c2->id);// Create some stuff.$gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);$gc1a = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);$gc1b = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);$gc2a = new \grade_category($dg->create_grade_category(['courseid' => $c2->id]), false);$go2 = new \grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2','fullname' => 'go2']), false);// Nothing as of now.foreach ([$u1, $u2, $u3, $u4, $u5, $u6, $u7, $u8, $u9, $u10, $u11] as $u) {$contexts = array_flip(provider::get_contexts_for_userid($u->id)->get_contextids());$this->assertEmpty($contexts);}$go0 = new \grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]);$go0->insert();$go1 = new \grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u11->id]);$go1->insert();// Create scales.$s1 = new \grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']);$s1->insert();$s2 = new \grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']);$s2->insert();// User 2 creates history.$this->setUser($u2);$go0->shortname .= ' edited';$go0->update();$gc1a->fullname .= ' edited';$gc1a->update();// User 3 creates history.$this->setUser($u3);$go1->shortname .= ' edited';$go1->update();$gc2a->fullname .= ' a';$gc2a->update();// User 4 updates an outcome in course (creates history).$this->setUser($u4);$go2->shortname .= ' edited';$go2->update();// User 5 updates an item.$this->setUser($u5);$gi1a->itemname .= ' edited';$gi1a->update();// User 6 creates history.$this->setUser($u6);$gi2a->delete();// User 9 creates history.$this->setUser($u9);$s1->name .= ' edited';$s1->update();// Assert contexts.$contexts = array_flip(provider::get_contexts_for_userid($u1->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($sysctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u11->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u2->id)->get_contextids());$this->assertCount(2, $contexts);$this->assertArrayHasKey($sysctx->id, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u3->id)->get_contextids());$this->assertCount(2, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);$this->assertArrayHasKey($c2ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u4->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($c2ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u5->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u6->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($c2ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u7->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($sysctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u8->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u9->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($sysctx->id, $contexts);// User 10 creates history.$this->setUser($u10);$s2->delete();$contexts = array_flip(provider::get_contexts_for_userid($u10->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);}public function test_get_contexts_for_userid_grades_and_history(): void {$dg = $this->getDataGenerator();$c1 = $dg->create_course();$c2 = $dg->create_course();$u1 = $dg->create_user();$u2 = $dg->create_user();$u3 = $dg->create_user();$u4 = $dg->create_user();$u5 = $dg->create_user();$u6 = $dg->create_user();$sysctx = \context_system::instance();$c1ctx = \context_course::instance($c1->id);$c2ctx = \context_course::instance($c2->id);// Create some stuff.$gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);$gi2b = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);// Nothing as of now.foreach ([$u1, $u2, $u3, $u4, $u5, $u6] as $u) {$contexts = array_flip(provider::get_contexts_for_userid($u->id)->get_contextids());$this->assertEmpty($contexts);}// User 1 is graded in course 1.$gi1a->update_final_grade($u1->id, 1, 'test');// User 2 is graded in course 2.$gi2a->update_final_grade($u2->id, 10, 'test');// User 3 is set as modifier.$gi1a->update_final_grade($u1->id, 1, 'test', '', FORMAT_MOODLE, $u3->id);// User 4 is set as modifier, and creates history..$this->setUser($u4);$gi1a->update_final_grade($u2->id, 1, 'test');// User 5 creates history, user 6 is the known modifier, and we delete the item.$this->setUser($u5);$gi2b->update_final_grade($u2->id, 1, 'test', '', FORMAT_PLAIN, $u6->id);$gi2b->delete();// Assert contexts.$contexts = array_flip(provider::get_contexts_for_userid($u1->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u2->id)->get_contextids());$this->assertCount(3, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);$this->assertArrayHasKey($c2ctx->id, $contexts);$this->assertArrayHasKey(\context_user::instance($u2->id)->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u3->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u4->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey($c1ctx->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u5->id)->get_contextids());$this->assertCount(2, $contexts);$this->assertArrayHasKey($c2ctx->id, $contexts);$this->assertArrayHasKey(\context_user::instance($u2->id)->id, $contexts);$contexts = array_flip(provider::get_contexts_for_userid($u6->id)->get_contextids());$this->assertCount(1, $contexts);$this->assertArrayHasKey(\context_user::instance($u2->id)->id, $contexts);}/*** Test that the appropriate user IDs are returned for a given context.*/public function test_get_users_in_context_gradebook_edits(): void {$dg = $this->getDataGenerator();$c1 = $dg->create_course();$c2 = $dg->create_course();$u1 = $dg->create_user();$u2 = $dg->create_user();$u3 = $dg->create_user();$u4 = $dg->create_user();$u5 = $dg->create_user();$u6 = $dg->create_user();$u7 = $dg->create_user();$u8 = $dg->create_user();$u9 = $dg->create_user();$u10 = $dg->create_user();$u11 = $dg->create_user();$sysctx = \context_system::instance();$c1ctx = \context_course::instance($c1->id);$c2ctx = \context_course::instance($c2->id);// Create some stuff.$gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);$gc1a = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);$gc1b = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);$gc2a = new \grade_category($dg->create_grade_category(['courseid' => $c2->id]), false);$go2 = new \grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2','fullname' => 'go2']), false);$go0 = new \grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]);$go0->insert();$go1 = new \grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u11->id]);$go1->insert();// Create scales.$s1 = new \grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']);$s1->insert();$s2 = new \grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']);$s2->insert();// User 2 creates history.$this->setUser($u2);$go0->shortname .= ' edited';$go0->update();$gc1a->fullname .= ' edited';$gc1a->update();// User 3 creates history.$this->setUser($u3);$go1->shortname .= ' edited';$go1->update();$gc2a->fullname .= ' a';$gc2a->update();// User 4 updates an outcome in course (creates history).$this->setUser($u4);$go2->shortname .= ' edited';$go2->update();// User 5 updates an item.$this->setUser($u5);$gi1a->itemname .= ' edited';$gi1a->update();// User 6 creates history.$this->setUser($u6);$gi2a->delete();// User 9 creates history.$this->setUser($u9);$s1->name .= ' edited';$s1->update();$userlist = new \core_privacy\local\request\userlist($sysctx, 'core_grades');provider::get_users_in_context($userlist);$systemcontextuserids = [$u1->id, $u2->id, $u7->id, $u9->id];$this->assertEquals($systemcontextuserids, $userlist->get_userids());$userlist = new \core_privacy\local\request\userlist($c1ctx, 'core_grades');provider::get_users_in_context($userlist);$course1userids = [$u11->id, $u3->id, $u8->id, $u5->id, $u2->id];$this->assertEquals($course1userids, $userlist->get_userids());$userlist = new \core_privacy\local\request\userlist($c2ctx, 'core_grades');provider::get_users_in_context($userlist);$course2userids = [$u4->id, $u6->id, $u3->id];$this->assertEquals($course2userids, $userlist->get_userids());}/*** Test that the appropriate user IDs are returned for a given context.*/public function test_get_users_in_context_grades_and_history(): void {$dg = $this->getDataGenerator();$c1 = $dg->create_course();$c2 = $dg->create_course();$u1 = $dg->create_user();$u2 = $dg->create_user();$u3 = $dg->create_user();$u4 = $dg->create_user();$u5 = $dg->create_user();$u6 = $dg->create_user();$c1ctx = \context_course::instance($c1->id);$c2ctx = \context_course::instance($c2->id);$u2ctx = \context_user::instance($u2->id);// Create some stuff.$gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);$gi2b = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);// User 1 is graded in course 1.$gi1a->update_final_grade($u1->id, 1, 'test');// User 2 is graded in course 2.$gi2a->update_final_grade($u2->id, 10, 'test');// User 3 is set as modifier.$gi1a->update_final_grade($u1->id, 1, 'test', '', FORMAT_MOODLE, $u3->id);// User 4 is set as modifier, and creates history..$this->setUser($u4);$gi1a->update_final_grade($u2->id, 1, 'test');// User 5 creates history, user 6 is the known modifier, and we delete the item.$this->setUser($u5);$gi2b->update_final_grade($u2->id, 1, 'test', '', FORMAT_PLAIN, $u6->id);$gi2b->delete();$userlist = new \core_privacy\local\request\userlist($c1ctx, 'core_grades');provider::get_users_in_context($userlist);$course1userids = [$u1->id, $u2->id, $u3->id, $u4->id];$this->assertEqualsCanonicalizing($course1userids, $userlist->get_userids());$userlist = new \core_privacy\local\request\userlist($c2ctx, 'core_grades');provider::get_users_in_context($userlist);$course2userids = [$u5->id, $u2->id];$this->assertEqualsCanonicalizing($course2userids, $userlist->get_userids());$userlist = new \core_privacy\local\request\userlist($u2ctx, 'core_grades');provider::get_users_in_context($userlist);$this->assertEquals([$u2->id], $userlist->get_userids());}public function test_delete_data_for_all_users_in_context(): void {global $DB;$fs = new \file_storage();$dg = $this->getDataGenerator();$c1 = $dg->create_course();$c2 = $dg->create_course();$u1 = $dg->create_user();$u2 = $dg->create_user();$u1ctx = \context_user::instance($u1->id);$c1ctx = \context_course::instance($c1->id);$c2ctx = \context_course::instance($c2->id);$a1 = $dg->create_module('assign', ['course' => $c1->id]);$a2 = $dg->create_module('assign', ['course' => $c1->id]);$a3 = $dg->create_module('assign', ['course' => $c2->id]);$a4 = $dg->create_module('assign', ['course' => $c2->id]);$a1context = \context_module::instance($a1->cmid);$a2context = \context_module::instance($a2->cmid);$a3context = \context_module::instance($a3->cmid);$a4context = \context_module::instance($a4->cmid);// Create some stuff.$gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a1->id]), false);$gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a2->id]), false);$gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a3->id]), false);$gi2b = new \grade_item($dg->create_grade_item(['courseid' => $c2->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a4->id]), false);$this->add_feedback_file_to_copy();$grades['feedback'] = 'Nice feedback!';$grades['feedbackformat'] = FORMAT_MOODLE;$grades['feedbackfiles'] = ['contextid' => 1,'component' => 'test','filearea' => 'testarea','itemid' => 1];$grades['userid'] = $u1->id;grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance,$gi1a->itemnumber, $grades);$grades['userid'] = $u2->id;grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance,$gi1a->itemnumber, $grades);$grades['userid'] = $u1->id;grade_update('mod/assign', $gi1b->courseid, $gi1b->itemtype, $gi1b->itemmodule, $gi1b->iteminstance,$gi1b->itemnumber, $grades);$grades['userid'] = $u1->id;grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,$gi2a->itemnumber, $grades);$grades['userid'] = $u2->id;grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,$gi2a->itemnumber, $grades);$grades['userid'] = $u1->id;grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,$gi2b->itemnumber, $grades);$grades['userid'] = $u2->id;grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,$gi2b->itemnumber, $grades);$gi2b->delete();// Feedback file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// History file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));provider::delete_data_for_all_users_in_context($c1ctx);$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));// Feedback file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// History file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));provider::delete_data_for_all_users_in_context($u1ctx);$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));// Feedback file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// The user context is only reported when there are orphan historical grades, so we only delete those files.$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// History file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// User 2 still has historical files.$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));provider::delete_data_for_all_users_in_context($c2ctx);$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));// Feedback file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// History file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));}public function test_delete_data_for_user(): void {global $DB;$fs = new \file_storage();$dg = $this->getDataGenerator();$c1 = $dg->create_course();$c2 = $dg->create_course();$u1 = $dg->create_user();$u2 = $dg->create_user();$u1ctx = \context_user::instance($u1->id);$u2ctx = \context_user::instance($u2->id);$c1ctx = \context_course::instance($c1->id);$c2ctx = \context_course::instance($c2->id);$a1 = $dg->create_module('assign', ['course' => $c1->id]);$a2 = $dg->create_module('assign', ['course' => $c1->id]);$a3 = $dg->create_module('assign', ['course' => $c2->id]);$a4 = $dg->create_module('assign', ['course' => $c2->id]);$a1context = \context_module::instance($a1->cmid);$a2context = \context_module::instance($a2->cmid);$a3context = \context_module::instance($a3->cmid);$a4context = \context_module::instance($a4->cmid);// Create some stuff.$gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a1->id]), false);$gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a2->id]), false);$gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a3->id]), false);$gi2b = new \grade_item($dg->create_grade_item(['courseid' => $c2->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a4->id]), false);$this->add_feedback_file_to_copy();$grades['feedback'] = 'Nice feedback!';$grades['feedbackfiles'] = ['contextid' => 1,'component' => 'test','filearea' => 'testarea','itemid' => 1];$grades['userid'] = $u1->id;grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance,$gi1a->itemnumber, $grades);$grades['userid'] = $u2->id;grade_update('mod/assign', $gi1a->courseid, $gi1a->itemtype, $gi1a->itemmodule, $gi1a->iteminstance,$gi1a->itemnumber, $grades);$grades['userid'] = $u1->id;grade_update('mod/assign', $gi1b->courseid, $gi1b->itemtype, $gi1b->itemmodule, $gi1b->iteminstance,$gi1b->itemnumber, $grades);$grades['userid'] = $u1->id;grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,$gi2a->itemnumber, $grades);$grades['userid'] = $u2->id;grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,$gi2a->itemnumber, $grades);$grades['userid'] = $u1->id;grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,$gi2b->itemnumber, $grades);$grades['userid'] = $u2->id;grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,$gi2b->itemnumber, $grades);$gi2b->delete();$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));// Feedback file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// History file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$c1ctx->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));// Feedback file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// History file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$u1ctx->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));// Feedback file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(4, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// History file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));provider::delete_data_for_user(new approved_contextlist($u1, 'core_grades', [$u2ctx->id, $c2ctx->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertFalse($DB->record_exists('grade_grades_history', ['userid' => $u1->id, 'itemid' => $gi2b->id]));$this->assertTrue($DB->record_exists('grade_grades_history', ['userid' => $u2->id, 'itemid' => $gi2b->id]));// Feedback file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));// History file area.$files = $fs->get_area_files($a1context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));$files = $fs->get_area_files($a2context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));$files = $fs->get_area_files($a3context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(2, count($files));// Grade item 2 was deleted, so the associated files were as well.$files = $fs->get_area_files($a4context->id, GRADE_FILE_COMPONENT, GRADE_HISTORY_FEEDBACK_FILEAREA);$this->assertEquals(0, count($files));}/*** Test deleting multiple users for a context works.*/public function test_delete_data_for_users(): void {global $DB;$dg = $this->getDataGenerator();$c1 = $dg->create_course();$c2 = $dg->create_course();$u1 = $dg->create_user();$u2 = $dg->create_user();$u3 = $dg->create_user();$u4 = $dg->create_user();$u1ctx = \context_user::instance($u1->id);$u2ctx = \context_user::instance($u2->id);$c1ctx = \context_course::instance($c1->id);$c2ctx = \context_course::instance($c2->id);// Create some stuff.$gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);$gi2b = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);$gi1a->update_final_grade($u1->id, 1, 'test');$gi1a->update_final_grade($u2->id, 1, 'test');$gi1a->update_final_grade($u3->id, 1, 'test');$gi1b->update_final_grade($u1->id, 1, 'test');$gi1b->update_final_grade($u4->id, 1, 'test');$gi2a->update_final_grade($u1->id, 1, 'test');$gi2a->update_final_grade($u2->id, 1, 'test');$gi2a->update_final_grade($u4->id, 1, 'test');$gi2b->update_final_grade($u1->id, 1, 'test');$gi2b->update_final_grade($u2->id, 1, 'test');$gi2b->update_final_grade($u3->id, 1, 'test');$gi2b->delete();$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2b->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2b->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi2b->id]));$userlist = new \core_privacy\local\request\approved_userlist($c1ctx, 'core_grades', [$u1->id, $u2->id]);provider::delete_data_for_users($userlist);$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id]));$userlist = new \core_privacy\local\request\approved_userlist($c2ctx, 'core_grades', [$u2->id, $u4->id]);provider::delete_data_for_users($userlist);$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi1a->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u3->id, 'itemid' => $gi1a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi1b->id]));$this->assertTrue($DB->record_exists('grade_grades', ['userid' => $u1->id, 'itemid' => $gi2a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u2->id, 'itemid' => $gi2a->id]));$this->assertFalse($DB->record_exists('grade_grades', ['userid' => $u4->id, 'itemid' => $gi2a->id]));}public function test_export_data_for_user_about_grades_and_history(): void {$dg = $this->getDataGenerator();$c1 = $dg->create_course();$c2 = $dg->create_course();// Users being graded.$ug1 = $dg->create_user();$ug2 = $dg->create_user();$ug3 = $dg->create_user();// Users performing actions.$ua1 = $dg->create_user();$ua2 = $dg->create_user();$ua3 = $dg->create_user();$ug1ctx = \context_user::instance($ug1->id);$ug2ctx = \context_user::instance($ug2->id);$c1ctx = \context_course::instance($c1->id);$c2ctx = \context_course::instance($c2->id);$rootpath = [get_string('grades', 'core_grades')];$relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);// Create the course minimal stuff.\grade_category::fetch_course_category($c1->id);$ci1 = \grade_item::fetch_course_item($c1->id);\grade_category::fetch_course_category($c2->id);$ci2 = \grade_item::fetch_course_item($c2->id);$this->add_feedback_file_to_copy();$grades['feedbackfiles'] = ['contextid' => 1,'component' => 'test','filearea' => 'testarea','itemid' => 1];$a1 = $dg->create_module('assign', ['course' => $c1->id]);// Create data that will sit in the user context because we will delete the grate item.$gi1 = new \grade_item($dg->create_grade_item(['courseid' => $c1->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a1->id,'aggregationcoef2' => 1]), false);$grades['feedback'] = 'Well done!';$grades['feedbackformat'] = FORMAT_PLAIN;$grades['userid'] = $ug1->id;$grades['usermodified'] = $ua2->id;$grades['rawgrade'] = 100;grade_update('mod/assign', $gi1->courseid, $gi1->itemtype, $gi1->itemmodule, $gi1->iteminstance,$gi1->itemnumber, $grades);$grades['feedback'] = 'Hi';$grades['userid'] = $ug1->id;$grades['usermodified'] = $ua2->id;$grades['rawgrade'] = 1;grade_update('mod/assign', $gi1->courseid, $gi1->itemtype, $gi1->itemmodule, $gi1->iteminstance,$gi1->itemnumber, $grades);$grades['feedback'] = 'Hello';$grades['userid'] = $ug3->id;$grades['usermodified'] = $ua2->id;$grades['rawgrade'] = 12;grade_update('mod/assign', $gi1->courseid, $gi1->itemtype, $gi1->itemmodule, $gi1->iteminstance,$gi1->itemnumber, $grades);// Create another set for another user.$a2 = $dg->create_module('assign', ['course' => $c2->id]);$a3 = $dg->create_module('assign', ['course' => $c2->id]);$gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a2->id]), false);$gi2b = new \grade_item($dg->create_grade_item(['courseid' => $c2->id,'itemtype' => 'mod','itemmodule' => 'assign','iteminstance' => $a3->id]), false);$grades['feedback'] = '';$grades['userid'] = $ug1->id;$grades['usermodified'] = $ua2->id;$grades['rawgrade'] = 15;grade_update('mod/assign', $gi2a->courseid, $gi2a->itemtype, $gi2a->itemmodule, $gi2a->iteminstance,$gi2a->itemnumber, $grades);$grades['feedback'] = 'Well played!';$grades['userid'] = $ug1->id;$grades['usermodified'] = $ua2->id;$grades['rawgrade'] = 30;grade_update('mod/assign', $gi2b->courseid, $gi2b->itemtype, $gi2b->itemmodule, $gi2b->iteminstance,$gi2b->itemnumber, $grades);// Export action user 1 everywhere.provider::export_user_data(new approved_contextlist($ua1, 'core_grades', [$ug1ctx->id, $ug2ctx->id,$c1ctx->id, $c2ctx->id]));$this->assert_context_has_no_data($ug1ctx);$this->assert_context_has_no_data($ug2ctx);$this->assert_context_has_no_data($c1ctx);$this->assert_context_has_no_data($c2ctx);// Export action user 2 in course 1.writer::reset();provider::export_user_data(new approved_contextlist($ua2, 'core_grades', [$c1ctx->id]));$this->assert_context_has_no_data($ug1ctx);$this->assert_context_has_no_data($ug2ctx);$this->assert_context_has_no_data($c2ctx);$data = writer::with_context($c1ctx)->get_data($rootpath);$this->assertEmpty($data);// Here we are testing the export of grades that we've changed.$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades');$this->assertCount(2, $data->grades);$this->assertEquals($gi1->get_name(), $data->grades[0]['item']);$this->assertEquals(1, $data->grades[0]['grade']);$this->assertEquals('Hi', $data->grades[0]['feedback']);$this->assertEquals(transform::yesno(true), $data->grades[0]['created_or_modified_by_you']);$this->assertEquals($gi1->get_name(), $data->grades[1]['item']);$this->assertEquals(12, $data->grades[1]['grade']);$this->assertEquals('Hello', $data->grades[1]['feedback']);$this->assertEquals(transform::yesno(true), $data->grades[1]['created_or_modified_by_you']);$pathtofiles = [get_string('grades', 'core_grades'),get_string('feedbackfiles', 'core_grades')];$file = writer::with_context($gi1->get_context())->get_files($pathtofiles)['feedback1.txt'];$this->assertInstanceOf('stored_file', $file);$this->assertEquals('feedback1.txt', $file->get_filename());$relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);// Here we are testing the export of history of grades that we've changed.$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades_history');$this->assertCount(3, $data->modified_records);$grade = $data->modified_records[0];$this->assertEquals($ug1->id, $grade['userid']);$this->assertEquals($gi1->get_name(), $grade['item']);$this->assertEquals(100, $grade['grade']);$this->assertEquals('Well done!', $grade['feedback']);$this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);$grade = $data->modified_records[1];$this->assertEquals($ug1->id, $grade['userid']);$this->assertEquals($gi1->get_name(), $grade['item']);$this->assertEquals(1, $grade['grade']);$this->assertEquals('Hi', $grade['feedback']);$this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);$grade = $data->modified_records[2];$this->assertEquals($ug3->id, $grade['userid']);$this->assertEquals($gi1->get_name(), $grade['item']);$this->assertEquals(12, $grade['grade']);$this->assertEquals('Hello', $grade['feedback']);$this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);$pathtofiles = [get_string('grades', 'core_grades'),get_string('feedbackhistoryfiles', 'core_grades')];$file = writer::with_context($gi1->get_context())->get_files($pathtofiles)['feedback1.txt'];$this->assertInstanceOf('stored_file', $file);$this->assertEquals('feedback1.txt', $file->get_filename());// Create a history record with logged user.$this->setUser($ua3);$gi1->update_final_grade($ug3->id, 50, 'test', '...', FORMAT_PLAIN, $ua2->id);writer::reset();provider::export_user_data(new approved_contextlist($ua3, 'core_grades', [$c1ctx->id]));$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'grades_history');$this->assertCount(1, $data->modified_records);$grade = $data->modified_records[0];$this->assertEquals($ug3->id, $grade['userid']);$this->assertEquals($gi1->get_name(), $grade['item']);$this->assertEquals(50, $grade['grade']);$this->assertEquals('...', $grade['feedback']);$this->assertEquals(transform::yesno(true), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);// Test that we export our own grades.writer::reset();provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$c1ctx->id]));$data = writer::with_context($c1ctx)->get_data($rootpath);$this->assert_context_has_no_data($c2ctx);$this->assertCount(3, $data->grades);$grade = $data->grades[0];$this->assertEquals($ci1->get_name(), $grade['item']);$this->assertEquals(1, $grade['grade']);$grade = $data->grades[2];$this->assertEquals($gi1->get_name(), $grade['item']);$this->assertEquals(1, $grade['grade']);$this->assertEquals('Hi', $grade['feedback']);// Test that we export our own grades in two courses.writer::reset();provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$ug1ctx->id, $c1ctx->id, $c2ctx->id]));$this->assert_context_has_no_data($ug1ctx);$data = writer::with_context($c1ctx)->get_data($rootpath);$this->assertCount(3, $data->grades);$grade = $data->grades[0];$this->assertEquals($ci1->get_name(), $grade['item']);$this->assertEquals(1, $grade['grade']);$grade = $data->grades[2];$this->assertEquals($gi1->get_name(), $grade['item']);$this->assertEquals(1, $grade['grade']);$this->assertEquals('Hi', $grade['feedback']);$data = writer::with_context($c2ctx)->get_data($rootpath);$this->assertCount(5, $data->grades);$grade = $data->grades[0];$this->assertEquals($ci2->get_name(), $grade['item']);$grade = $data->grades[3];$this->assertEquals($gi2a->get_name(), $grade['item']);$this->assertEquals(15, $grade['grade']);$this->assertEquals('', $grade['feedback']);$grade = $data->grades[4];$this->assertEquals($gi2b->get_name(), $grade['item']);$this->assertEquals(30, $grade['grade']);$this->assertEquals('Well played!', $grade['feedback']);// Delete a grade item.$this->setUser($ua3);$gi1->delete();// Now, we should find history of grades in our own context.writer::reset();provider::export_user_data(new approved_contextlist($ug1, 'core_grades', [$ug1ctx->id, $c1ctx->id, $c2ctx->id]));$data = writer::with_context($c1ctx)->get_data($rootpath);$this->assertCount(2, $data->grades);$this->assertEquals($ci1->get_name(), $data->grades[0]['item']);$data = writer::with_context($c2ctx)->get_data($rootpath);$this->assertCount(5, $data->grades);$data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history');$this->assertCount(3, $data->grades);$grade = $data->grades[0];$this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);$this->assertEquals(100, $grade['grade']);$this->assertEquals('Well done!', $grade['feedback']);$this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']);$this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);$this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'), $grade['action']);$grade = $data->grades[1];$this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);$this->assertEquals(1, $grade['grade']);$this->assertEquals('Hi', $grade['feedback']);$this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']);$this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);$this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'), $grade['action']);$grade = $data->grades[2];$this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);$this->assertEquals(1, $grade['grade']);$this->assertEquals('Hi', $grade['feedback']);$this->assertEquals(transform::yesno(true), $grade['graded_user_was_you']);$this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);$this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']);// The action user 3 should have a record of the deletion in the user's context.writer::reset();provider::export_user_data(new approved_contextlist($ua3, 'core_grades', [$ug1ctx->id]));$data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history');$this->assertCount(1, $data->grades);$grade = $data->grades[0];$this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);$this->assertEquals(1, $grade['grade']);$this->assertEquals('Hi', $grade['feedback']);$this->assertEquals(transform::yesno(true), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(false), $grade['author_of_change_was_you']);$this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']);// The action user 2 should have a record of their edits in the user's context.writer::reset();provider::export_user_data(new approved_contextlist($ua2, 'core_grades', [$ug1ctx->id]));$data = writer::with_context($ug1ctx)->get_related_data($rootpath, 'history');$this->assertCount(3, $data->grades);$grade = $data->grades[0];$this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);$this->assertEquals(100, $grade['grade']);$this->assertEquals('Well done!', $grade['feedback']);$this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);$this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'), $grade['action']);$grade = $data->grades[1];$this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);$this->assertEquals(1, $grade['grade']);$this->assertEquals('Hi', $grade['feedback']);$this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);$this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'), $grade['action']);$grade = $data->grades[2];$this->assertEquals(get_string('privacy:request:unknowndeletedgradeitem', 'core_grades'), $grade['name']);$this->assertEquals(1, $grade['grade']);$this->assertEquals('Hi', $grade['feedback']);$this->assertEquals(transform::yesno(false), $grade['logged_in_user_was_you']);$this->assertEquals(transform::yesno(true), $grade['author_of_change_was_you']);$this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'), $grade['action']);}public function test_export_data_for_user_with_scale(): void {global $DB;$dg = $this->getDataGenerator();$c1 = $dg->create_course();$scale = $dg->create_scale(['scale' => 'Awesome,OK,Reasonable,Bad']);$u1 = $dg->create_user();$u2 = $dg->create_user();$u1ctx = \context_user::instance($u1->id);$c1ctx = \context_course::instance($c1->id);$rootpath = [get_string('grades', 'core_grades')];// Create another set for another user.$gi1 = new \grade_item($dg->create_grade_item(['courseid' => $c1->id, 'scaleid' => $scale->id]), false);$gi1->update_final_grade($u1->id, 1, 'test', '', FORMAT_PLAIN, $u2->id);$gi2 = new \grade_item($dg->create_grade_item(['courseid' => $c1->id, 'scaleid' => $scale->id]), false);$gi2->update_final_grade($u1->id, 3, 'test', '', FORMAT_PLAIN, $u2->id);// Export user's data.writer::reset();provider::export_user_data(new approved_contextlist($u1, 'core_grades', [$c1ctx->id]));$data = writer::with_context($c1ctx)->get_data($rootpath);$this->assertCount(3, $data->grades);$this->assertEquals(\grade_item::fetch_course_item($c1->id)->get_name(), $data->grades[0]['item']);$this->assertEquals($gi1->get_name(), $data->grades[1]['item']);$this->assertEquals(1, $data->grades[1]['grade']);$this->assertEquals('Awesome', $data->grades[1]['grade_formatted']);$this->assertEquals($gi2->get_name(), $data->grades[2]['item']);$this->assertEquals(3, $data->grades[2]['grade']);$this->assertEquals('Reasonable', $data->grades[2]['grade_formatted']);}public function test_export_data_for_user_about_gradebook_edits(): void {global $DB;$dg = $this->getDataGenerator();$c1 = $dg->create_course();$c2 = $dg->create_course();$u1 = $dg->create_user();$u2 = $dg->create_user();$u3 = $dg->create_user();$u4 = $dg->create_user();$u5 = $dg->create_user();$u6 = $dg->create_user();$u7 = $dg->create_user();$u8 = $dg->create_user();$u9 = $dg->create_user();$u10 = $dg->create_user();$sysctx = \context_system::instance();$u1ctx = \context_user::instance($u1->id);$u2ctx = \context_user::instance($u2->id);$u3ctx = \context_user::instance($u3->id);$u4ctx = \context_user::instance($u4->id);$u5ctx = \context_user::instance($u5->id);$u6ctx = \context_user::instance($u6->id);$c1ctx = \context_course::instance($c1->id);$c2ctx = \context_course::instance($c2->id);$rootpath = [get_string('grades', 'core_grades')];$relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);$allcontexts = [$sysctx->id, $c1ctx->id, $c2ctx->id, $u1ctx->id, $u2ctx->id, $u3ctx->id, $u4ctx->id,$u5ctx->id, $u6ctx->id];$updateactionstr = get_string('privacy:request:historyactionupdate', 'core_grades');// Create some stuff.$gi1a = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi1b = new \grade_item($dg->create_grade_item(['courseid' => $c1->id]), false);$gi2a = new \grade_item($dg->create_grade_item(['courseid' => $c2->id]), false);$gc1a = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);$gc1b = new \grade_category($dg->create_grade_category(['courseid' => $c1->id]), false);$gc2a = new \grade_category($dg->create_grade_category(['courseid' => $c2->id]), false);$go2 = new \grade_outcome($dg->create_grade_outcome(['courseid' => $c2->id, 'shortname' => 'go2','fullname' => 'go2']), false);$go0 = new \grade_outcome(['shortname' => 'go0', 'fullname' => 'go0', 'usermodified' => $u1->id]);$go0->insert();$go1 = new \grade_outcome(['shortname' => 'go1', 'fullname' => 'go1', 'courseid' => $c1->id, 'usermodified' => $u1->id]);$go1->insert();// Create scales.$s1 = new \grade_scale(['name' => 's1', 'scale' => 'a,b', 'userid' => $u7->id, 'courseid' => 0, 'description' => '']);$s1->insert();$s2 = new \grade_scale(['name' => 's2', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c1->id, 'description' => '']);$s2->insert();$s3 = new \grade_scale(['name' => 's3', 'scale' => 'a,b', 'userid' => $u8->id, 'courseid' => $c2->id, 'description' => '']);$s3->insert();// User 2 creates history.$this->setUser($u2);$go0->shortname .= ' edited';$go0->update();$gc1a->fullname .= ' edited';$gc1a->update();// User 3 creates history.$this->setUser($u3);$go1->shortname .= ' edited';$go1->update();$gc2a->fullname .= ' a';$gc2a->update();// User 4 updates an outcome in course (creates history).$this->setUser($u4);$go2->shortname .= ' edited';$go2->update();// User 5 updates an item.$this->setUser($u5);$gi1a->itemname .= ' edited';$gi1a->update();// User 6 creates history.$this->setUser($u6);$gi2a->delete();// User 9 creates history.$this->setUser($u9);$s1->name .= ' edited';$s1->update();// User 10 creates history.$this->setUser($u10);$s3->delete();$this->setAdminUser();// Export data for u1.writer::reset();provider::export_user_data(new approved_contextlist($u1, 'core_grades', $allcontexts));$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes');$this->assertCount(1, $data->outcomes);$this->assertEquals($go0->shortname, $data->outcomes[0]['shortname']);$this->assertEquals($go0->fullname, $data->outcomes[0]['fullname']);$this->assertEquals(transform::yesno(true), $data->outcomes[0]['created_or_modified_by_you']);$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes');$this->assertCount(1, $data->outcomes);$this->assertEquals($go1->shortname, $data->outcomes[0]['shortname']);$this->assertEquals($go1->fullname, $data->outcomes[0]['fullname']);$this->assertEquals(transform::yesno(true), $data->outcomes[0]['created_or_modified_by_you']);$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes_history');$this->assertEmpty($data);$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes_history');$this->assertEmpty($data);// Export data for u2.writer::reset();provider::export_user_data(new approved_contextlist($u2, 'core_grades', $allcontexts));$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes');$this->assertEmpty($data);$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes');$this->assertEmpty($data);$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'outcomes_history');$this->assertCount(1, $data->modified_records);$this->assertEquals($go0->shortname, $data->modified_records[0]['shortname']);$this->assertEquals($go0->fullname, $data->modified_records[0]['fullname']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);$this->assertEquals($updateactionstr, $data->modified_records[0]['action']);$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'categories_history');$this->assertCount(1, $data->modified_records);$this->assertEquals($gc1a->fullname, $data->modified_records[0]['name']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);$this->assertEquals($updateactionstr, $data->modified_records[0]['action']);// Export data for u3.writer::reset();provider::export_user_data(new approved_contextlist($u3, 'core_grades', $allcontexts));$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'outcomes_history');$this->assertCount(1, $data->modified_records);$this->assertEquals($go1->shortname, $data->modified_records[0]['shortname']);$this->assertEquals($go1->fullname, $data->modified_records[0]['fullname']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);$this->assertEquals($updateactionstr, $data->modified_records[0]['action']);$data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'categories_history');$this->assertCount(1, $data->modified_records);$this->assertEquals($gc2a->fullname, $data->modified_records[0]['name']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);$this->assertEquals($updateactionstr, $data->modified_records[0]['action']);// Export data for u4.writer::reset();provider::export_user_data(new approved_contextlist($u4, 'core_grades', $allcontexts));$data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'outcomes_history');$this->assertCount(1, $data->modified_records);$this->assertEquals($go2->shortname, $data->modified_records[0]['shortname']);$this->assertEquals($go2->fullname, $data->modified_records[0]['fullname']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);$this->assertEquals($updateactionstr, $data->modified_records[0]['action']);// Export data for u5.writer::reset();provider::export_user_data(new approved_contextlist($u5, 'core_grades', $allcontexts));$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'items_history');$this->assertCount(1, $data->modified_records);$this->assertEquals($gi1a->itemname, $data->modified_records[0]['name']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);$this->assertEquals($updateactionstr, $data->modified_records[0]['action']);// Export data for u6.writer::reset();provider::export_user_data(new approved_contextlist($u6, 'core_grades', $allcontexts));$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'items_history');$this->assertEmpty($data);$data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'items_history');$this->assertCount(1, $data->modified_records);$this->assertEquals($gi2a->itemname, $data->modified_records[0]['name']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['logged_in_user_was_you']);$this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'),$data->modified_records[0]['action']);// Export data for u7.writer::reset();provider::export_user_data(new approved_contextlist($u7, 'core_grades', $allcontexts));$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');$this->assertEmpty($data);$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');$this->assertCount(1, $data->scales);$this->assertEquals($s1->name, $data->scales[0]['name']);$this->assertEquals(transform::yesno(true), $data->scales[0]['created_or_modified_by_you']);// Export data for u8.writer::reset();provider::export_user_data(new approved_contextlist($u8, 'core_grades', $allcontexts));$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');$this->assertEmpty($data);$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');$this->assertCount(1, $data->scales);$this->assertEquals($s2->name, $data->scales[0]['name']);$this->assertEquals(transform::yesno(true), $data->scales[0]['created_or_modified_by_you']);$data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales_history');$this->assertCount(2, $data->modified_records);$this->assertEquals($s3->name, $data->modified_records[0]['name']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_change_was_you']);$this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_action_was_you']);$this->assertEquals(get_string('privacy:request:historyactioninsert', 'core_grades'),$data->modified_records[0]['action']);$this->assertEquals($s3->name, $data->modified_records[1]['name']);$this->assertEquals(transform::yesno(true), $data->modified_records[1]['author_of_change_was_you']);$this->assertEquals(transform::yesno(false), $data->modified_records[1]['author_of_action_was_you']);$this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'),$data->modified_records[1]['action']);// Export data for u9.writer::reset();provider::export_user_data(new approved_contextlist($u9, 'core_grades', $allcontexts));$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');$this->assertEmpty($data);$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');$this->assertEmpty($data);$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales_history');$this->assertCount(1, $data->modified_records);$this->assertEquals($s1->name, $data->modified_records[0]['name']);$this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_change_was_you']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_action_was_you']);$this->assertEquals(get_string('privacy:request:historyactionupdate', 'core_grades'),$data->modified_records[0]['action']);// Export data for u10.writer::reset();provider::export_user_data(new approved_contextlist($u10, 'core_grades', $allcontexts));$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales');$this->assertEmpty($data);$data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales');$this->assertEmpty($data);$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales');$this->assertEmpty($data);$data = writer::with_context($c1ctx)->get_related_data($relatedtomepath, 'scales_history');$this->assertEmpty($data);$data = writer::with_context($sysctx)->get_related_data($relatedtomepath, 'scales_history');$this->assertEmpty($data);$data = writer::with_context($c2ctx)->get_related_data($relatedtomepath, 'scales_history');$this->assertCount(1, $data->modified_records);$this->assertEquals($s3->name, $data->modified_records[0]['name']);$this->assertEquals(transform::yesno(false), $data->modified_records[0]['author_of_change_was_you']);$this->assertEquals(transform::yesno(true), $data->modified_records[0]['author_of_action_was_you']);$this->assertEquals(get_string('privacy:request:historyactiondelete', 'core_grades'),$data->modified_records[0]['action']);}/*** Assert there is no grade data in the context.** @param context $context The context.* @return void*/protected function assert_context_has_no_data(\context $context) {$rootpath = [get_string('grades', 'core_grades')];$relatedtomepath = array_merge($rootpath, [get_string('privacy:path:relatedtome', 'core_grades')]);$data = writer::with_context($context)->get_data($rootpath);$this->assertEmpty($data);$data = writer::with_context($context)->get_related_data($rootpath, 'history');$this->assertEmpty($data);$files = ['categories_history', 'items_history', 'outcomes', 'outcomes_history', 'grades', 'grades_history', 'history'];foreach ($files as $file) {$data = writer::with_context($context)->get_related_data($relatedtomepath, $file);$this->assertEmpty($data);}}/*** Creates a feedback file to copy to the gradebook area.*/private function add_feedback_file_to_copy() {$dummy = array('contextid' => 1,'component' => 'test','filearea' => 'testarea','itemid' => 1,'filepath' => '/','filename' => 'feedback1.txt');$fs = get_file_storage();$fs->create_file_from_string($dummy, '');}}