use \core_privacy\local\metadata\collection;
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;
use \tool_monitor\subscription_manager;
use \tool_monitor\rule_manager;
* @copyright 2018 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\plugin\provider {
+class provider implements
+ \core_privacy\local\metadata\provider,
+ \core_privacy\local\request\core_userlist_provider,
+ \core_privacy\local\request\plugin\provider {
/**
* Get information about the user data stored by this plugin.
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();
+
+ if (!is_a($context, \context_user::class)) {
+ return;
+ }
+
+ $params = [
+ 'contextid' => $context->id,
+ 'contextuser' => CONTEXT_USER,
+ ];
+
+ $sql = "SELECT mr.userid
+ FROM {context} ctx
+ JOIN {tool_monitor_rules} mr ON ctx.instanceid = mr.userid
+ AND ctx.contextlevel = :contextuser
+ WHERE ctx.id = :contextid";
+
+ $userlist->add_from_sql('userid', $sql, $params);
+
+ $sql = "SELECT ms.userid
+ FROM {context} ctx
+ LEFT JOIN {tool_monitor_subscriptions} ms ON ctx.instanceid = ms.userid
+ AND ctx.contextlevel = :contextuser
+ WHERE ctx.id = :contextid";
+
+ $userlist->add_from_sql('userid', $sql, $params);
+ }
+
/**
* Export all event monitor information for the list of contexts and this user.
*
static::delete_user_data($contextlist->get_user()->id);
}
+ /**
+ * 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) {
+ $context = $userlist->get_context();
+ $userids = $userlist->get_userids();
+ $userid = reset($userids);
+
+ // Only delete data for user context, which should be a single user.
+ if ($context->contextlevel == CONTEXT_USER && count($userids) == 1 && $userid == $context->instanceid) {
+ static::delete_user_data($userid);
+ }
+ }
+
/**
* This does the deletion of user data for the event monitor.
*
use \tool_monitor\privacy\provider;
use \core_privacy\local\request\approved_contextlist;
+use \core_privacy\local\request\approved_userlist;
/**
* Privacy test for the event monitor
$this->assertEquals($usercontext2->id, $contextlist->get_contextids()[0]);
}
+ /**
+ * Check that the correct userlist is returned if there is any user data for this context.
+ */
+ public function test_get_users_in_context() {
+ $component = 'tool_monitor';
+ $user = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $usercontext = \context_user::instance($user->id);
+ $usercontext2 = \context_user::instance($user2->id);
+
+ $userlist = new \core_privacy\local\request\userlist($usercontext, $component);
+ provider::get_users_in_context($userlist);
+ $this->assertEmpty($userlist);
+
+ $userlist = new \core_privacy\local\request\userlist($usercontext2, $component);
+ provider::get_users_in_context($userlist);
+ $this->assertEmpty($userlist);
+
+ $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
+
+ // Create a rule with user.
+ $this->setUser($user);
+ $rule = $monitorgenerator->create_rule();
+ $userlist = new \core_privacy\local\request\userlist($usercontext, $component);
+ provider::get_users_in_context($userlist);
+
+ // Check that we only get back user.
+ $userids = $userlist->get_userids();
+ $this->assertCount(1, $userlist);
+ $this->assertEquals($user->id, $userids[0]);
+
+ // Create a subscription with user2.
+ $this->setUser($user2);
+
+ $record = new stdClass();
+ $record->courseid = 0;
+ $record->userid = $user2->id;
+ $record->ruleid = $rule->id;
+
+ $subscription = $monitorgenerator->create_subscription($record);
+ $userlist = new \core_privacy\local\request\userlist($usercontext2, $component);
+ provider::get_users_in_context($userlist);
+
+ // Check that user2 is returned for just subscribing to a rule.
+ $userids = $userlist->get_userids();
+ $this->assertCount(1, $userlist);
+ $this->assertEquals($user2->id, $userids[0]);
+ }
+
/**
* Test that user data is exported correctly.
*/
$this->assertEquals($user2->id, $dbsubs[$subscription2->id]->userid);
$this->assertEquals($user2->id, $dbsubs[$subscription3->id]->userid);
}
+
+ /**
+ * Test deleting user data for an approved userlist in a context.
+ */
+ public function test_delete_data_for_users() {
+ global $DB;
+
+ $component = 'tool_monitor';
+ $user = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $usercontext = \context_user::instance($user->id);
+ $usercontext2 = \context_user::instance($user2->id);
+ $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor');
+
+ $this->setUser($user);
+ // Need to give user one the ability to manage rules.
+ $this->assign_user_capability('tool/monitor:managerules', \context_system::instance());
+
+ $rulerecord = (object)['name' => 'privacy rule'];
+ $rule = $monitorgenerator->create_rule($rulerecord);
+
+ $secondrulerecord = (object)['name' => 'privacy rule2'];
+ $rule2 = $monitorgenerator->create_rule($secondrulerecord);
+
+ $subscription = (object)['ruleid' => $rule->id, 'userid' => $user->id];
+ $subscription = $monitorgenerator->create_subscription($subscription);
+
+ // Have user 2 subscribe to the second rule created by user 1.
+ $subscription2 = (object)['ruleid' => $rule2->id, 'userid' => $user2->id];
+ $subscription2 = $monitorgenerator->create_subscription($subscription2);
+
+ $this->setUser($user2);
+ $thirdrulerecord = (object)['name' => 'privacy rule for second user'];
+ $rule3 = $monitorgenerator->create_rule($thirdrulerecord);
+
+ $subscription3 = (object)['ruleid' => $rule3->id, 'userid' => $user2->id];
+ $subscription3 = $monitorgenerator->create_subscription($subscription3);
+
+ // Get all of the monitor rules, ensure all exist.
+ $dbrules = $DB->get_records('tool_monitor_rules');
+ $this->assertCount(3, $dbrules);
+
+ // Delete for user2 in first user's context, should have no effect.
+ $approveduserids = [$user2->id];
+ $approvedlist = new approved_userlist($usercontext, $component, $approveduserids);
+ provider::delete_data_for_users($approvedlist);
+
+ $dbrules = $DB->get_records('tool_monitor_rules');
+ $this->assertCount(3, $dbrules);
+
+ // Delete for user in usercontext.
+ $approveduserids = [$user->id];
+ $approvedlist = new approved_userlist($usercontext, $component, $approveduserids);
+ provider::delete_data_for_users($approvedlist);
+
+ // Only the rules for user 1 that does not have any more subscriptions should be deleted (the first rule).
+ $dbrules = $DB->get_records('tool_monitor_rules');
+ $this->assertCount(2, $dbrules);
+ $this->assertEquals($user->id, $dbrules[$rule2->id]->userid);
+ $this->assertEquals($user2->id, $dbrules[$rule3->id]->userid);
+
+ // There should be two subscriptions left, both for user 2.
+ $dbsubs = $DB->get_records('tool_monitor_subscriptions');
+ $this->assertCount(2, $dbsubs);
+ $this->assertEquals($user2->id, $dbsubs[$subscription2->id]->userid);
+ $this->assertEquals($user2->id, $dbsubs[$subscription3->id]->userid);
+
+ // Delete for user2 in context 2.
+ $approveduserids = [$user2->id];
+ $approvedlist = new approved_userlist($usercontext2, $component, $approveduserids);
+ provider::delete_data_for_users($approvedlist);
+
+ // There should be no subscriptions left.
+ $dbsubs = $DB->get_records('tool_monitor_subscriptions');
+ $this->assertEmpty($dbsubs);
+ }
}