MDL-63702 core_block: Update to use new userlist interface.
authorAdrian Greeve <abgreeve@gmail.com>
Fri, 19 Oct 2018 02:35:52 +0000 (10:35 +0800)
committerMihail Geshoski <mihail@moodle.com>
Wed, 31 Oct 2018 02:01:44 +0000 (10:01 +0800)
This allows user data to be deleted on a role basis.

blocks/classes/privacy/provider.php
blocks/tests/privacy_test.php

index cbee644..954f72b 100644 (file)
@@ -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);
+    }
 }
index 8c6327e..20df9d9 100644 (file)
@@ -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();