From 69e66bf86f0bc0213e8eaa5a060c0caae03bb8ca Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Fri, 19 Oct 2018 10:35:52 +0800 Subject: [PATCH] MDL-63702 core_block: Update to use new userlist interface. This allows user data to be deleted on a role basis. --- blocks/classes/privacy/provider.php | 45 +++++++++++++++++- blocks/tests/privacy_test.php | 72 +++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) diff --git a/blocks/classes/privacy/provider.php b/blocks/classes/privacy/provider.php index cbee6444dee..954f72be09b 100644 --- a/blocks/classes/privacy/provider.php +++ b/blocks/classes/privacy/provider.php @@ -44,7 +44,8 @@ use core_privacy\local\request\writer; class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\subsystem\provider, - \core_privacy\local\request\user_preference_provider { + \core_privacy\local\request\user_preference_provider, + \core_privacy\local\request\core_userlist_provider { /** * Returns metadata. @@ -103,6 +104,28 @@ 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) { + global $DB; + + $context = $userlist->get_context(); + if ($context->contextlevel != CONTEXT_BLOCK) { + return; + } + + $params = ['docked' => 'docked_block_instance_' . $context->instanceid, + 'hidden' => 'block' . $context->instanceid . 'hidden']; + + $sql = "SELECT userid + FROM {user_preferences} + WHERE name = :hidden OR name = :docked"; + $userlist->add_from_sql('userid', $sql, $params); + } + /** * Export all user data for the specified user, in the specified contexts. * @@ -224,4 +247,24 @@ class provider implements $DB->delete_records_select('user_preferences', $sql, $params); } + + /** + * 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) { + global $DB; + $context = $userlist->get_context(); + if ($context->contextlevel != CONTEXT_BLOCK) { + return; + } + + list($insql, $params) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED); + $params['hidden'] = 'block' . $context->instanceid . 'hidden'; + $params['docked'] = 'docked_block_instance_' . $context->instanceid; + + $DB->delete_records_select('user_preferences', "(name = :hidden OR name = :docked) AND userid $insql", $params); + } } diff --git a/blocks/tests/privacy_test.php b/blocks/tests/privacy_test.php index 8c6327eeede..20df9d9fecb 100644 --- a/blocks/tests/privacy_test.php +++ b/blocks/tests/privacy_test.php @@ -93,6 +93,37 @@ class core_block_privacy_testcase extends provider_testcase { $this->assertTrue(in_array($blockmentees->context->id, $contextids)); } + /** + * Test that user IDs are returned for a given context. + */ + public function test_get_users_in_context() { + global $DB; + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + + $course = $this->getDataGenerator()->create_course(); + + $manager = $this->get_block_manager(['region-a'], context_course::instance($course->id)); + $manager->add_block('myprofile', 'region-a', 0, false); + $manager->load_blocks(); + $blockmyprofile = $manager->get_blocks_for_region('region-a')[0]; + + $this->set_hidden_pref($blockmyprofile, true, $u1->id); + $this->set_hidden_pref($blockmyprofile, true, $u3->id); + $this->set_docked_pref($blockmyprofile, true, $u2->id); + $this->set_docked_pref($blockmyprofile, true, $u3->id); + + $records = $DB->get_records('block_instances', ['blockname' => 'myprofile']); + $record = array_shift($records); + $blockcontext = context_block::instance($record->id); + + $userlist = new \core_privacy\local\request\userlist($blockcontext, 'core_block'); + provider::get_users_in_context($userlist); + $this->assertCount(3, $userlist->get_userids()); + } + + public function test_delete_data_for_user() { global $DB; $dg = $this->getDataGenerator(); @@ -266,6 +297,47 @@ class core_block_privacy_testcase extends provider_testcase { 'name' => "docked_block_instance_{$blockmentees->instance->id}"])); } + /** + * Test the deletion of data related to a context and a list of users. + */ + public function test_delete_data_for_users() { + global $DB; + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + + $course = $this->getDataGenerator()->create_course(); + + $manager = $this->get_block_manager(['region-a'], context_course::instance($course->id)); + $manager->add_block('myprofile', 'region-a', 0, false); + $manager->load_blocks(); + $blockmyprofile = $manager->get_blocks_for_region('region-a')[0]; + + $this->set_hidden_pref($blockmyprofile, true, $u1->id); + $this->set_hidden_pref($blockmyprofile, true, $u3->id); + $this->set_docked_pref($blockmyprofile, true, $u2->id); + $this->set_docked_pref($blockmyprofile, true, $u3->id); + + $records = $DB->get_records('block_instances', ['blockname' => 'myprofile']); + $record = array_shift($records); + $blockcontext = context_block::instance($record->id); + + $userlist = new \core_privacy\local\request\userlist($blockcontext, 'core_block'); + provider::get_users_in_context($userlist); + $this->assertCount(3, $userlist->get_userids()); + + // Delete preferences for user 1 and 3 for the my profile block. + $userlist = new \core_privacy\local\request\approved_userlist($blockcontext, 'core_block', [$u1->id, $u3->id]); + provider::delete_data_for_users($userlist); + + // Only user 2's preference is left. + $this->assertCount(1, $DB->get_records('user_preferences', + ['name' => "docked_block_instance_{$blockcontext->instanceid}"])); + // All of these are gone. + $this->assertEmpty($DB->get_records('user_preferences', + ['name' => "block{$blockcontext->instanceid}hidden"])); + } + public function test_export_data_for_user() { global $DB; $dg = $this->getDataGenerator();