diff --git a/search/engine/simpledb/classes/privacy/provider.php b/search/engine/simpledb/classes/privacy/provider.php index 05b09b94e60..5645b6b1116 100644 --- a/search/engine/simpledb/classes/privacy/provider.php +++ b/search/engine/simpledb/classes/privacy/provider.php @@ -26,10 +26,12 @@ namespace search_simpledb\privacy; defined('MOODLE_INTERNAL') || die(); use core_privacy\local\metadata\collection; -use core_privacy\local\request\writer; -use core_privacy\local\request\transform; use core_privacy\local\request\contextlist; use core_privacy\local\request\approved_contextlist; +use core_privacy\local\request\approved_userlist; +use core_privacy\local\request\transform; +use core_privacy\local\request\userlist; +use core_privacy\local\request\writer; /** * Provider for the search_simpledb plugin. @@ -39,6 +41,7 @@ use core_privacy\local\request\approved_contextlist; */ class provider implements \core_privacy\local\metadata\provider, + \core_privacy\local\request\core_userlist_provider, \core_privacy\local\request\plugin\provider { /** @@ -80,12 +83,39 @@ class provider implements $contextlist = new \core_privacy\local\request\contextlist(); $params = ['userid' => $userid, 'owneruserid' => $userid]; - $sql = "SELECT DISTINCT contextid FROM {search_simpledb_index} WHERE (userid = :userid OR owneruserid = :owneruserid)"; + $sql = "SELECT DISTINCT contextid + FROM {search_simpledb_index} + WHERE (userid = :userid OR owneruserid = :owneruserid)"; $contextlist->add_from_sql($sql, $params); return $contextlist; } + /** + * Get the list of users who have data within a context. + * + * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. + */ + public static function get_users_in_context(userlist $userlist) { + $context = $userlist->get_context(); + + $params = [ + 'contextid' => $context->id, + ]; + + $sql = "SELECT ssi.userid + FROM {search_simpledb_index} ssi + WHERE ssi.contextid = :contextid"; + + $userlist->add_from_sql('userid', $sql, $params); + + $sql = "SELECT ssi.owneruserid AS userid + FROM {search_simpledb_index} ssi + WHERE ssi.contextid = :contextid"; + + $userlist->add_from_sql('userid', $sql, $params); + } + /** * Export all user data for the specified user, in the specified contexts. * @@ -159,4 +189,22 @@ class provider implements $params = ['userid' => $userid, 'owneruserid' => $userid] + $contextparams; $DB->delete_records_select('search_simpledb_index', $select, $params); } + + /** + * Delete multiple users within a single context. + * + * @param approved_userlist $userlist The approved context and user information to delete information for. + */ + public static function delete_data_for_users(approved_userlist $userlist) { + global $DB; + $context = $userlist->get_context(); + + list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED); + list($ownersql, $ownerparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED); + + $select = "contextid = :contextid AND (userid {$usersql} OR owneruserid {$ownersql})"; + $params = ['contextid' => $context->id] + $userparams + $ownerparams; + + $DB->delete_records_select('search_simpledb_index', $select, $params); + } } diff --git a/search/engine/simpledb/tests/privacy_test.php b/search/engine/simpledb/tests/privacy_test.php index 28b6fe2da0f..9bc7c2e7c99 100644 --- a/search/engine/simpledb/tests/privacy_test.php +++ b/search/engine/simpledb/tests/privacy_test.php @@ -112,6 +112,60 @@ class privacy_model_testcase extends \core_privacy\tests\provider_testcase { } } + /** + * Test fetching contexts for a given user ID. + */ + public function test_get_contexts_for_userid() { + // Ensure both contexts are found for both users. + $expected = [$this->c1context->id, $this->c2context->id]; + sort($expected); + + // User 1. + $contextlist = provider::get_contexts_for_userid($this->u1->id); + $this->assertCount(2, $contextlist); + + $actual = $contextlist->get_contextids(); + sort($actual); + $this->assertEquals($expected, $actual); + + // User 2. + $contextlist = provider::get_contexts_for_userid($this->u2->id); + $this->assertCount(2, $contextlist); + + $actual = $contextlist->get_contextids(); + sort($actual); + $this->assertEquals($expected, $actual); + } + + /** + * Test fetching user IDs for a given context. + */ + public function test_get_users_in_context() { + $component = 'search_simpledb'; + + // Ensure both users are found for both contexts. + $expected = [$this->u1->id, $this->u2->id]; + sort($expected); + + // User 1. + $userlist = new \core_privacy\local\request\userlist($this->c1context, $component); + provider::get_users_in_context($userlist); + $this->assertCount(2, $userlist); + + $actual = $userlist->get_userids(); + sort($actual); + $this->assertEquals($expected, $actual); + + // User 2. + $userlist = new \core_privacy\local\request\userlist($this->c2context, $component); + provider::get_users_in_context($userlist); + $this->assertCount(2, $userlist); + + $actual = $userlist->get_userids(); + sort($actual); + $this->assertEquals($expected, $actual); + } + /** * Test export user data. * @@ -182,6 +236,37 @@ class privacy_model_testcase extends \core_privacy\tests\provider_testcase { $this->assertEquals(4, $DB->count_records('search_simpledb_index')); } + /** + * Test deleting data for an approved userlist. + */ + public function test_delete_data_for_users() { + global $DB; + $component = 'search_simpledb'; + $select = 'contextid = :contextid AND (owneruserid = :owneruserid OR userid = :userid)'; + + // Ensure expected amount of data for both users exists in each context. + $this->assertEquals(4, $DB->count_records('search_simpledb_index', ['contextid' => $this->c1context->id])); + $this->assertEquals(4, $DB->count_records('search_simpledb_index', ['contextid' => $this->c2context->id])); + + // Delete user 1's data in context 1. + $approveduserids = [$this->u1->id]; + $approvedlist = new \core_privacy\local\request\approved_userlist($this->c1context, $component, $approveduserids); + provider::delete_data_for_users($approvedlist); + + $params = ['contextid' => $this->c1context->id, 'owneruserid' => $this->u1->id, 'userid' => $this->u1->id]; + $this->assertEquals(0, $DB->count_records_select('search_simpledb_index', $select, $params)); + + // Ensure user 2's data in context 1 is retained. + $params = ['contextid' => $this->c1context->id, 'owneruserid' => $this->u2->id, 'userid' => $this->u2->id]; + $this->assertEquals(2, $DB->count_records_select('search_simpledb_index', $select, $params)); + + // Ensure both users' data in context 2 is retained. + $params = ['contextid' => $this->c2context->id, 'owneruserid' => $this->u1->id, 'userid' => $this->u1->id]; + $this->assertEquals(2, $DB->count_records_select('search_simpledb_index', $select, $params)); + $params = ['contextid' => $this->c2context->id, 'owneruserid' => $this->u2->id, 'userid' => $this->u2->id]; + $this->assertEquals(2, $DB->count_records_select('search_simpledb_index', $select, $params)); + } + /** * Mssql with fulltext support requires manual updates. *