. /** * Data provider tests. * * @package core_grades * @category test * @copyright 2018 Frédéric Massart * @author Frédéric Massart * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ 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 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class core_grades_privacy_testcase extends provider_testcase { public function setUp() { global $PAGE; $this->resetAfterTest(); $PAGE->get_renderer('core'); } public function test_get_contexts_for_userid_gradebook_edits() { $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() { $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() { $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() { $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->assertEquals($course1userids, $userlist->get_userids(), '', 0.0, 10, true); $userlist = new \core_privacy\local\request\userlist($c2ctx, 'core_grades'); provider::get_users_in_context($userlist); $course2userids = [$u5->id, $u2->id]; $this->assertEquals($course2userids, $userlist->get_userids(), '', 0.0, 10, true); $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() { 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() { 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() { 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() { $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() { 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() { 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, ''); } }