From ac7d086d1da43c5fbadfc756ef906093a653514d Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Wed, 17 Oct 2018 11:51:52 +0800 Subject: [PATCH] MDL-63666 logging: Add support for removal of context users. This creates a new interface for the logging subplugins to implement for the users to be deleted separately. --- .../privacy/logstore_userlist_provider.php | 57 ++++++++ .../moodle_database_export_and_delete.php | 15 +++ admin/tool/log/classes/privacy/provider.php | 33 ++++- .../database/classes/privacy/provider.php | 35 ++++- .../log/store/database/tests/privacy_test.php | 94 +++++++++++++ .../store/legacy/classes/privacy/provider.php | 37 ++++- .../log/store/legacy/tests/privacy_test.php | 127 ++++++++++++++++++ .../standard/classes/privacy/provider.php | 19 ++- .../log/store/standard/tests/privacy_test.php | 88 ++++++++++++ 9 files changed, 498 insertions(+), 7 deletions(-) create mode 100644 admin/tool/log/classes/local/privacy/logstore_userlist_provider.php diff --git a/admin/tool/log/classes/local/privacy/logstore_userlist_provider.php b/admin/tool/log/classes/local/privacy/logstore_userlist_provider.php new file mode 100644 index 00000000000..c6506787ae1 --- /dev/null +++ b/admin/tool/log/classes/local/privacy/logstore_userlist_provider.php @@ -0,0 +1,57 @@ +. + +/** + * Logstore userlist provider interface. + * + * @package tool_log + * @copyright 2018 Adrian Greeve + * @author Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_log\local\privacy; +defined('MOODLE_INTERNAL') || die(); + +/** + * Logstore userlist provider interface. + * + * Logstore subplugins providers must implement this interface. + * + * @package tool_log + * @copyright 2018 Adrian Greeve + * @author Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +interface logstore_userlist_provider extends \core_privacy\local\request\plugin\subplugin_provider { + + /** + * Add user IDs that contain user information for the specified context. + * + * @param \core_privacy\local\request\userlist $userlist The userlist to add the users to. + * @return void + */ + public static function add_userids_for_context(\core_privacy\local\request\userlist $userlist); + + + /** + * Delete all data for all users in the specified context. + * + * @param \core_privacy\local\request\approved_userlist $userlist The specific context and users to delete data for. + * @return void + */ + public static function delete_data_for_all_users(\core_privacy\local\request\approved_userlist $userlist); +} diff --git a/admin/tool/log/classes/local/privacy/moodle_database_export_and_delete.php b/admin/tool/log/classes/local/privacy/moodle_database_export_and_delete.php index da973eadf92..24f4698f381 100644 --- a/admin/tool/log/classes/local/privacy/moodle_database_export_and_delete.php +++ b/admin/tool/log/classes/local/privacy/moodle_database_export_and_delete.php @@ -120,4 +120,19 @@ trait moodle_database_export_and_delete { $db->delete_records_select($table, "userid = :userid AND contextid $insql", $params); } + /** + * Delete all user data for the specified users, in the specified context. + * + * @param \core_privacy\local\request\approved_userlist $contextlist The approved contexts and user information to delete information for. + */ + public static function delete_data_for_all_users(\core_privacy\local\request\approved_userlist $userlist) { + list($db, $table) = static::get_database_and_table(); + if (!$db || !$table) { + return; + } + list($insql, $inparams) = $db->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED); + $params = array_merge($inparams, ['contextid' => $userlist->get_context()->id]); + $db->delete_records_select($table, "contextid = :contextid AND userid $insql", $params); + } + } diff --git a/admin/tool/log/classes/privacy/provider.php b/admin/tool/log/classes/privacy/provider.php index 252ba509e2f..1c1c77dc0da 100644 --- a/admin/tool/log/classes/privacy/provider.php +++ b/admin/tool/log/classes/privacy/provider.php @@ -43,7 +43,8 @@ use tool_log\log\manager; */ class provider implements \core_privacy\local\metadata\provider, - \core_privacy\local\request\subsystem\provider { + \core_privacy\local\request\subsystem\provider, + \core_privacy\local\request\core_userlist_provider { /** * Returns metadata. @@ -68,6 +69,17 @@ class provider implements return $contextlist; } + /** + * Get the list of contexts that contain user information for the specified user. + * + * @param \core_privacy\local\request\userlist $userlist The userlist containing the list of users who have data in + * this context/plugin combination. + */ + public static function get_users_in_context(\core_privacy\local\request\userlist $userlist) { + $interface = \tool_log\local\privacy\logstore_userlist_provider::class; + static::call_subplugins_method_with_args('add_userids_for_context', [$userlist], $interface); + } + /** * Export all user data for the specified user, in the specified contexts. * @@ -97,16 +109,29 @@ class provider implements static::call_subplugins_method_with_args('delete_data_for_user', [$contextlist]); } + /** + * Delete multiple users within a single context. + * + * @param \core_privacy\local\request\approved_userlist $userlist The approved context and user information to delete + * information for. + */ + public static function delete_data_for_users(\core_privacy\local\request\approved_userlist $userlist) { + $interface = \tool_log\local\privacy\logstore_userlist_provider::class; + static::call_subplugins_method_with_args('delete_data_for_all_users', [$userlist], $interface); + } + /** * Invoke the subplugins method with arguments. * * @param string $method The method name. * @param array $args The arguments. + * @param string $interface The interface to use. By default uses the logstore_provider. * @return void */ - protected static function call_subplugins_method_with_args($method, array $args = []) { - $interface = \tool_log\local\privacy\logstore_provider::class; + protected static function call_subplugins_method_with_args($method, array $args = [], string $interface = null) { + if (!isset($interface)) { + $interface = \tool_log\local\privacy\logstore_provider::class; + } \core_privacy\manager::plugintype_class_callback('logstore', $interface, $method, $args); } - } diff --git a/admin/tool/log/store/database/classes/privacy/provider.php b/admin/tool/log/store/database/classes/privacy/provider.php index b5e8eacf1b0..c9b31af931a 100644 --- a/admin/tool/log/store/database/classes/privacy/provider.php +++ b/admin/tool/log/store/database/classes/privacy/provider.php @@ -40,7 +40,8 @@ use core_privacy\local\request\contextlist; */ class provider implements \core_privacy\local\metadata\provider, - \tool_log\local\privacy\logstore_provider { + \tool_log\local\privacy\logstore_provider, + \tool_log\local\privacy\logstore_userlist_provider { use \tool_log\local\privacy\moodle_database_export_and_delete; @@ -91,6 +92,38 @@ class provider implements $contextlist->add_from_sql($sql, []); } + /** + * Add user IDs that contain user information for the specified context. + * + * @param \core_privacy\local\request\userlist $userlist The userlist to add the users to. + * @return void + */ + public static function add_userids_for_context(\core_privacy\local\request\userlist $userlist) { + list($db, $table) = static::get_database_and_table(); + if (!$db || !$table) { + return; + } + + $userids = []; + $records = $db->get_records($table, ['contextid' => $userlist->get_context()->id], '', + 'id, userid, relateduserid, realuserid'); + if (empty($records)) { + return; + } + + foreach ($records as $record) { + $userids[] = $record->userid; + if (!empty($record->relateduserid)) { + $userids[] = $record->relateduserid; + } + if (!empty($record->realuserid)) { + $userids[] = $record->realuserid; + } + } + $userids = array_unique($userids); + $userlist->add_users($userids); + } + /** * Get the database object. * diff --git a/admin/tool/log/store/database/tests/privacy_test.php b/admin/tool/log/store/database/tests/privacy_test.php index 4a1e37ec52d..a2c056537d9 100644 --- a/admin/tool/log/store/database/tests/privacy_test.php +++ b/admin/tool/log/store/database/tests/privacy_test.php @@ -151,6 +151,55 @@ class logstore_database_privacy_testcase extends provider_testcase { $this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx, $c2ctx]); } + /** + * Check that user IDs are returned for a given context. + */ + public function test_add_userids_for_context() { + $admin = \core_user::get_user(2); + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + $u4 = $this->getDataGenerator()->create_user(); + + $c1 = $this->getDataGenerator()->create_course(); + + $sysctx = context_system::instance(); + $c1ctx = context_course::instance($c1->id); + + $this->enable_logging(); + $manager = get_log_manager(true); + + $userlist = new \core_privacy\local\request\userlist($sysctx, 'logstore_database'); + $userids = $userlist->get_userids(); + $this->assertEmpty($userids); + provider::add_userids_for_context($userlist); + $userids = $userlist->get_userids(); + $this->assertEmpty($userids); + // User one should be added (userid). + $this->setUser($u1); + $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + // User two (userids) and three (relateduserid) should be added. + $this->setUser($u2); + $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx, 'relateduserid' => $u3->id]); + $e->trigger(); + // The admin user should be added (realuserid). + $this->setAdminUser(); + \core\session\manager::loginas($u2->id, context_system::instance()); + $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + // Set off an event in a different context. User 4 should not be returned below. + $this->setUser($u4); + $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]); + $e->trigger(); + + provider::add_userids_for_context($userlist); + $userids = $userlist->get_userids(); + $this->assertCount(4, $userids); + $expectedresult = [$admin->id, $u1->id, $u2->id, $u3->id]; + $this->assertEmpty(array_diff($expectedresult, $userids)); + } + public function test_delete_data_for_user() { global $DB; $u1 = $this->getDataGenerator()->create_user(); @@ -233,6 +282,51 @@ class logstore_database_privacy_testcase extends provider_testcase { $this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u2->id])); } + /** + * Check that data is removed for the listed users in a given context. + */ + public function test_delete_data_for_all_users() { + global $DB; + + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + $u4 = $this->getDataGenerator()->create_user(); + + $course = $this->getDataGenerator()->create_course(); + $sysctx = context_system::instance(); + $c1ctx = context_course::instance($course->id); + + $this->enable_logging(); + $manager = get_log_manager(true); + + $this->setUser($u1); + $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + $this->setUser($u2); + $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + $this->setUser($u3); + $e = \logstore_database\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + $this->setUser($u4); + $e = \logstore_database\event\unittest_executed::create(['context' => $c1ctx]); + $e->trigger(); + + // Check that four records were created. + $this->assertEquals(4, $DB->count_records('logstore_standard_log')); + + $userlist = new \core_privacy\local\request\approved_userlist($sysctx, 'logstore_database', [$u1->id, $u3->id]); + provider::delete_data_for_all_users($userlist); + // We should have a record for u2 and u4. + $this->assertEquals(2, $DB->count_records('logstore_standard_log')); + + $records = $DB->get_records('logstore_standard_log', ['contextid' => $sysctx->id]); + $this->assertCount(1, $records); + $currentrecord = array_shift($records); + $this->assertEquals($u2->id, $currentrecord->userid); + } + public function test_export_data_for_user() { $admin = \core_user::get_user(2); $u1 = $this->getDataGenerator()->create_user(); diff --git a/admin/tool/log/store/legacy/classes/privacy/provider.php b/admin/tool/log/store/legacy/classes/privacy/provider.php index 298d8215f63..ebaacb3b7d9 100644 --- a/admin/tool/log/store/legacy/classes/privacy/provider.php +++ b/admin/tool/log/store/legacy/classes/privacy/provider.php @@ -44,7 +44,8 @@ use tool_log\local\privacy\helper; */ class provider implements \core_privacy\local\metadata\provider, - \tool_log\local\privacy\logstore_provider { + \tool_log\local\privacy\logstore_provider, + \tool_log\local\privacy\logstore_userlist_provider { /** * Returns metadata. @@ -89,6 +90,22 @@ class provider implements $contextlist->add_from_sql($sql, $params); } + /** + * Add user IDs that contain user information for the specified context. + * + * @param \core_privacy\local\request\userlist $userlist The userlist to add the users to. + * @return void + */ + public static function add_userids_for_context(\core_privacy\local\request\userlist $userlist) { + $context = $userlist->get_context(); + list($insql, $params) = static::get_sql_where_from_contexts([$context]); + + $sql = "SELECT l.userid + FROM {log} l + WHERE $insql"; + $userlist->add_from_sql('userid', $sql, $params); + } + /** * Export all user data for the specified user, in the specified contexts. * @@ -168,6 +185,24 @@ class provider implements $DB->delete_records_select('log', "$sql AND userid = :userid", array_merge($params, ['userid' => $userid])); } + + /** + * Delete all data for all users in the specified context. + * + * @param \core_privacy\local\request\approved_userlist $userlist The specific context and users to delete data for. + * @return void + */ + public static function delete_data_for_all_users(\core_privacy\local\request\approved_userlist $userlist) { + global $DB; + list($sql, $params) = static::get_sql_where_from_contexts([$userlist->get_context()]); + if (empty($sql)) { + return; + } + list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED); + $params = array_merge($params, $userparams); + $DB->delete_records_select('log', "$sql AND userid $usersql", $params); + } + /** * Get an SQL where statement from a list of contexts. * diff --git a/admin/tool/log/store/legacy/tests/privacy_test.php b/admin/tool/log/store/legacy/tests/privacy_test.php index a60960ab311..9c7dfc7348b 100644 --- a/admin/tool/log/store/legacy/tests/privacy_test.php +++ b/admin/tool/log/store/legacy/tests/privacy_test.php @@ -87,6 +87,71 @@ class logstore_legacy_privacy_testcase extends provider_testcase { $this->assert_contextlist_equals($this->get_contextlist_for_user($u3), [$sysctx]); } + /** + * Test returning user IDs for a given context. + */ + public function test_add_userids_for_context() { + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + $course = $this->getDataGenerator()->create_course(); + $module = $this->getDataGenerator()->create_module('url', ['course' => $course]); + $sysctx = context_system::instance(); + $c1ctx = context_course::instance($course->id); + $cm1ctx = context_module::instance($module->cmid); + + $userctx = context_user::instance($u1->id); + + $this->enable_logging(); + $manager = get_log_manager(true); + + $this->setUser($u1); + $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 1]]); + $e->trigger(); + $this->setUser($u2); + $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 2]]); + $e->trigger(); + $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 3]]); + $e->trigger(); + $this->setUser($u3); + $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 4]]); + $e->trigger(); + $this->setUser($u1); + $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 5]]); + $e->trigger(); + $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 6]]); + $e->trigger(); + $this->setUser($u2); + $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 7]]); + $e->trigger(); + $this->setUser($u3); + $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 8]]); + $e->trigger(); + + // Start with system and check that each of the contexts returns what we expected. + $userlist = new \core_privacy\local\request\userlist($sysctx, 'logstore_legacy'); + provider::add_userids_for_context($userlist); + $systemuserids = $userlist->get_userids(); + $this->assertCount(2, $systemuserids); + $this->assertNotFalse(array_search($u1->id, $systemuserids)); + $this->assertNotFalse(array_search($u2->id, $systemuserids)); + // Check the course context. + $userlist = new \core_privacy\local\request\userlist($c1ctx, 'logstore_legacy'); + provider::add_userids_for_context($userlist); + $courseuserids = $userlist->get_userids(); + $this->assertCount(2, $courseuserids); + $this->assertNotFalse(array_search($u1->id, $courseuserids)); + $this->assertNotFalse(array_search($u3->id, $courseuserids)); + // Check the module context. + $userlist = new \core_privacy\local\request\userlist($cm1ctx, 'logstore_legacy'); + provider::add_userids_for_context($userlist); + $moduleuserids = $userlist->get_userids(); + $this->assertCount(3, $moduleuserids); + $this->assertNotFalse(array_search($u1->id, $moduleuserids)); + $this->assertNotFalse(array_search($u2->id, $moduleuserids)); + $this->assertNotFalse(array_search($u3->id, $moduleuserids)); + } + public function test_delete_data_for_user() { global $DB; @@ -241,6 +306,68 @@ class logstore_legacy_privacy_testcase extends provider_testcase { $this->assertEquals(0, $DB->count_records('log', ['userid' => $u2->id])); } + /** + * Test the deletion of data for users in a context. + */ + public function test_delete_data_for_all_users() { + global $DB; + + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + $course = $this->getDataGenerator()->create_course(); + $module = $this->getDataGenerator()->create_module('url', ['course' => $course]); + $sysctx = context_system::instance(); + $c1ctx = context_course::instance($course->id); + $cm1ctx = context_module::instance($module->cmid); + + $userctx = context_user::instance($u1->id); + + $this->enable_logging(); + $manager = get_log_manager(true); + + $this->setUser($u1); + $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 1]]); + $e->trigger(); + $this->setUser($u2); + $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 2]]); + $e->trigger(); + $e = unittest_executed::create(['context' => $sysctx, 'other' => ['sample' => 3]]); + $e->trigger(); + $this->setUser($u3); + $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 4]]); + $e->trigger(); + $this->setUser($u1); + $e = unittest_executed::create(['context' => $c1ctx, 'other' => ['sample' => 5]]); + $e->trigger(); + $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 6]]); + $e->trigger(); + $this->setUser($u2); + $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 7]]); + $e->trigger(); + $this->setUser($u3); + $e = unittest_executed::create(['context' => $cm1ctx, 'other' => ['sample' => 8]]); + $e->trigger(); + + // System context deleting one user. + $this->assertEquals(3, $DB->count_records('log', ['cmid' => 0, 'course' => 0])); + $userlist = new \core_privacy\local\request\approved_userlist($sysctx, 'logstore_legacy', [$u2->id]); + provider::delete_data_for_all_users($userlist); + $this->assertEquals(1, $DB->count_records('log', ['cmid' => 0, 'course' => 0])); + + // Course context deleting one user. + $this->assertEquals(2, $DB->count_records('log', ['cmid' => 0, 'course' => $course->id])); + $userlist = new \core_privacy\local\request\approved_userlist($c1ctx, 'logstore_legacy', [$u1->id]); + provider::delete_data_for_all_users($userlist); + $this->assertEquals(1, $DB->count_records('log', ['cmid' => 0, 'course' => $course->id])); + + // Module context deleting two users. + $this->assertEquals(3, $DB->count_records('log', ['cmid' => $module->cmid, 'course' => $course->id])); + $userlist = new \core_privacy\local\request\approved_userlist($cm1ctx, 'logstore_legacy', [$u1->id, $u3->id]); + provider::delete_data_for_all_users($userlist); + $this->assertEquals(1, $DB->count_records('log', ['cmid' => $module->cmid, 'course' => $course->id])); + } + public function test_export_data_for_user() { global $DB; diff --git a/admin/tool/log/store/standard/classes/privacy/provider.php b/admin/tool/log/store/standard/classes/privacy/provider.php index 4ee8007c1ea..76a4e1f782c 100644 --- a/admin/tool/log/store/standard/classes/privacy/provider.php +++ b/admin/tool/log/store/standard/classes/privacy/provider.php @@ -40,7 +40,8 @@ use core_privacy\local\request\contextlist; */ class provider implements \core_privacy\local\metadata\provider, - \tool_log\local\privacy\logstore_provider { + \tool_log\local\privacy\logstore_provider, + \tool_log\local\privacy\logstore_userlist_provider { use \tool_log\local\privacy\moodle_database_export_and_delete; @@ -86,6 +87,22 @@ class provider implements ]); } + /** + * Add user IDs that contain user information for the specified context. + * + * @param \core_privacy\local\request\userlist $userlist The userlist to add the users to. + * @return void + */ + public static function add_userids_for_context(\core_privacy\local\request\userlist $userlist) { + $params = ['contextid' => $userlist->get_context()->id]; + $sql = "SELECT userid, relateduserid, realuserid + FROM {logstore_standard_log} + WHERE contextid = :contextid"; + $userlist->add_from_sql('userid', $sql, $params); + $userlist->add_from_sql('relateduserid', $sql, $params); + $userlist->add_from_sql('realuserid', $sql, $params); + } + /** * Get the database object. * diff --git a/admin/tool/log/store/standard/tests/privacy_test.php b/admin/tool/log/store/standard/tests/privacy_test.php index 5103b3abec4..d54f5f575e4 100644 --- a/admin/tool/log/store/standard/tests/privacy_test.php +++ b/admin/tool/log/store/standard/tests/privacy_test.php @@ -109,6 +109,52 @@ class logstore_standard_privacy_testcase extends provider_testcase { $this->assert_contextlist_equals($this->get_contextlist_for_user($admin), [$sysctx, $c1ctx, $c2ctx]); } + public function test_add_userids_for_context() { + $admin = \core_user::get_user(2); + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + $u4 = $this->getDataGenerator()->create_user(); + + $c1 = $this->getDataGenerator()->create_course(); + + $sysctx = context_system::instance(); + $c1ctx = context_course::instance($c1->id); + + $this->enable_logging(); + $manager = get_log_manager(true); + + $userlist = new \core_privacy\local\request\userlist($sysctx, 'logstore_standard_log'); + $userids = $userlist->get_userids(); + $this->assertEmpty($userids); + provider::add_userids_for_context($userlist); + $userids = $userlist->get_userids(); + $this->assertEmpty($userids); + // User one should be added (userid). + $this->setUser($u1); + $e = \logstore_standard\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + // User two (userids) and three (relateduserid) should be added. + $this->setUser($u2); + $e = \logstore_standard\event\unittest_executed::create(['context' => $sysctx, 'relateduserid' => $u3->id]); + $e->trigger(); + // The admin user should be added (realuserid). + $this->setAdminUser(); + \core\session\manager::loginas($u2->id, context_system::instance()); + $e = \logstore_standard\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + // Set off an event in a different context. User 4 should not be returned below. + $this->setUser($u4); + $e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]); + $e->trigger(); + + provider::add_userids_for_context($userlist); + $userids = $userlist->get_userids(); + $this->assertCount(4, $userids); + $expectedresult = [$admin->id, $u1->id, $u2->id, $u3->id]; + $this->assertEmpty(array_diff($expectedresult, $userids)); + } + public function test_delete_data_for_user() { global $DB; $u1 = $this->getDataGenerator()->create_user(); @@ -191,6 +237,48 @@ class logstore_standard_privacy_testcase extends provider_testcase { $this->assertEquals(1, $DB->count_records('logstore_standard_log', ['userid' => $u2->id])); } + public function test_delete_data_for_all_users() { + global $DB; + + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + $u4 = $this->getDataGenerator()->create_user(); + + $course = $this->getDataGenerator()->create_course(); + $sysctx = context_system::instance(); + $c1ctx = context_course::instance($course->id); + + $this->enable_logging(); + $manager = get_log_manager(true); + + $this->setUser($u1); + $e = \logstore_standard\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + $this->setUser($u2); + $e = \logstore_standard\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + $this->setUser($u3); + $e = \logstore_standard\event\unittest_executed::create(['context' => $sysctx]); + $e->trigger(); + $this->setUser($u4); + $e = \logstore_standard\event\unittest_executed::create(['context' => $c1ctx]); + $e->trigger(); + + // Check that four records were created. + $this->assertEquals(4, $DB->count_records('logstore_standard_log')); + + $userlist = new \core_privacy\local\request\approved_userlist($sysctx, 'logstore_standard_log', [$u1->id, $u3->id]); + provider::delete_data_for_all_users($userlist); + // We should have a record for u2 and u4. + $this->assertEquals(2, $DB->count_records('logstore_standard_log')); + + $records = $DB->get_records('logstore_standard_log', ['contextid' => $sysctx->id]); + $this->assertCount(1, $records); + $currentrecord = array_shift($records); + $this->assertEquals($u2->id, $currentrecord->userid); + } + public function test_export_data_for_user() { $admin = \core_user::get_user(2); $u1 = $this->getDataGenerator()->create_user(); -- 2.43.0