From c844eafd6f3355e862d0804246a1f9166bb69ecc Mon Sep 17 00:00:00 2001 From: Mihail Geshoski Date: Wed, 31 Oct 2018 14:10:08 +0800 Subject: [PATCH] MDL-63684 core_calendar: Add support for removal of context users This issue is part of the MDL-62560 Epic. --- calendar/classes/privacy/provider.php | 239 ++++++++++++++++++--- calendar/tests/privacy_test.php | 295 ++++++++++++++++++++++++++ 2 files changed, 504 insertions(+), 30 deletions(-) diff --git a/calendar/classes/privacy/provider.php b/calendar/classes/privacy/provider.php index 33324214b47..8ed10c216b6 100644 --- a/calendar/classes/privacy/provider.php +++ b/calendar/classes/privacy/provider.php @@ -20,7 +20,9 @@ * @copyright 2018 Zig Tan * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + namespace core_calendar\privacy; + defined('MOODLE_INTERNAL') || die(); use \core_privacy\local\metadata\collection; @@ -29,6 +31,8 @@ use \core_privacy\local\request\context; use \core_privacy\local\request\contextlist; use \core_privacy\local\request\transform; use \core_privacy\local\request\writer; +use \core_privacy\local\request\userlist; +use \core_privacy\local\request\approved_userlist; /** * Privacy Subsystem for core_calendar implementing metadata, plugin, and user_preference providers. @@ -38,9 +42,10 @@ use \core_privacy\local\request\writer; * @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, - \core_privacy\local\request\user_preference_provider + \core_privacy\local\metadata\provider, + \core_privacy\local\request\plugin\provider, + \core_privacy\local\request\core_userlist_provider, + \core_privacy\local\request\user_preference_provider { /** @@ -149,6 +154,101 @@ class provider implements return $contextlist; } + /** + * Get the list of users within a specific 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(); + + $allowedcontexts = [ + CONTEXT_SYSTEM, + CONTEXT_COURSECAT, + CONTEXT_COURSE, + CONTEXT_MODULE, + CONTEXT_USER + ]; + + if (!in_array($context->contextlevel, $allowedcontexts)) { + return; + } + + $params = [ + 'modulecontext' => CONTEXT_MODULE, + 'contextid' => $context->id, + ]; + + $sql = "SELECT e.userid + FROM {course_modules} cm + JOIN {modules} m + ON m.id = cm.module + JOIN {event} e + ON e.modulename = m.name + AND e.courseid = cm.course + AND e.instance = cm.instance + JOIN {context} ctx + ON ctx.instanceid = cm.id + AND ctx.contextlevel = :modulecontext + WHERE ctx.id = :contextid"; + + $userlist->add_from_sql('userid', $sql, $params); + + // Calendar Events can exist at Site, Course Category, Course, Course Group, User, or Course Modules contexts. + $params = [ + 'sitecontext' => CONTEXT_SYSTEM, + 'categorycontext' => CONTEXT_COURSECAT, + 'coursecontext' => CONTEXT_COURSE, + 'groupcontext' => CONTEXT_COURSE, + 'usercontext' => CONTEXT_USER, + 'contextid' => $context->id + ]; + + // Get contexts of Calendar Events for the owner. + $sql = "SELECT e.userid + FROM {event} e + JOIN {context} ctx + ON (ctx.contextlevel = :sitecontext + AND e.eventtype = 'site') + OR (ctx.contextlevel = :categorycontext + AND ctx.instanceid = e.categoryid + AND e.eventtype = 'category') + OR (ctx.contextlevel = :coursecontext + AND ctx.instanceid = e.courseid + AND e.eventtype = 'course') + OR (ctx.contextlevel = :groupcontext + AND ctx.instanceid = e.courseid + AND e.eventtype = 'group') + OR (ctx.contextlevel = :usercontext + AND ctx.instanceid = e.userid + AND e.eventtype = 'user') + WHERE ctx.id = :contextid"; + + $userlist->add_from_sql('userid', $sql, $params); + + // Get contexts for Calendar Subscriptions for the owner. + $sql = "SELECT s.userid + FROM {event_subscriptions} s + JOIN {context} ctx + ON (ctx.contextlevel = :sitecontext + AND s.eventtype = 'site') + OR (ctx.instanceid = s.categoryid + AND ctx.contextlevel = :categorycontext + AND s.eventtype = 'category') + OR (ctx.instanceid = s.courseid + AND ctx.contextlevel = :coursecontext + AND s.eventtype = 'course') + OR (ctx.instanceid = s.courseid + AND ctx.contextlevel = :groupcontext + AND s.eventtype = 'group') + OR (ctx.instanceid = s.userid + AND ctx.contextlevel = :usercontext + AND s.eventtype = 'user') + WHERE ctx.id = :contextid"; + + $userlist->add_from_sql('userid', $sql, $params); + } + /** * Export all user data for the specified user, in the specified contexts. * @@ -198,6 +298,42 @@ class provider implements } } + /** + * 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(); + + $allowedcontexts = [ + CONTEXT_SYSTEM, + CONTEXT_COURSECAT, + CONTEXT_COURSE, + CONTEXT_MODULE, + CONTEXT_USER + ]; + + if (!in_array($context->contextlevel, $allowedcontexts)) { + return; + } + + if (empty($userids)) { + return; + } + + // Delete all Calendar Events in the specified context in batches. + if ($eventids = array_keys(self::get_calendar_event_ids_by_context($context, $userids))) { + self::delete_batch_records('event', 'id', $eventids); + } + + // Delete all Calendar Subscriptions in the specified context in batches. + if ($subscriptionids = array_keys(self::get_calendar_subscription_ids_by_context($context, $userids))) { + self::delete_batch_records('event_subscriptions', 'id', $subscriptionids); + } + } + /** * Delete all user data for the specified user, in the specified contexts. * @@ -334,18 +470,25 @@ class provider implements } /** - * Helper function to return all Calendar Event id results for a specified context. + * Helper function to return all Calendar Event id results for a specified context and optionally + * included user list. * * @param \context $context + * @param array $userids * @return array|null * @throws \dml_exception */ - protected static function get_calendar_event_ids_by_context(\context $context) { + protected static function get_calendar_event_ids_by_context(\context $context, $userids = array()) { global $DB; - // Calendar Events can exist at Site, Course Category, Course, Course Group, User, or Course Modules contexts. - $events = null; + $whereusersql = ''; + $userparams = array(); + if (!empty($userids)) { + list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); + $whereusersql = "AND e.userid {$usersql}"; + } + // Calendar Events can exist at Site, Course Category, Course, Course Group, User, or Course Modules contexts. if ($context->contextlevel == CONTEXT_MODULE) { // Course Module Contexts. $params = [ 'modulecontext' => $context->contextlevel, @@ -356,11 +499,17 @@ class provider implements $sql = "SELECT DISTINCT e.id AS eventid FROM {context} ctx - INNER JOIN {course_modules} cm ON cm.id = ctx.instanceid AND ctx.contextlevel = :modulecontext - INNER JOIN {modules} m ON m.id = cm.module - INNER JOIN {event} e ON e.modulename = m.name AND e.courseid = cm.course AND e.instance = cm.instance - WHERE ctx.id = :contextid"; - $events = $DB->get_records_sql($sql, $params); + INNER JOIN {course_modules} cm + ON cm.id = ctx.instanceid + AND ctx.contextlevel = :modulecontext + INNER JOIN {modules} m + ON m.id = cm.module + INNER JOIN {event} e + ON e.modulename = m.name + AND e.courseid = cm.course + AND e.instance = cm.instance + WHERE ctx.id = :contextid + {$whereusersql}"; } else { // Other Moodle Contexts. $params = [ 'sitecontext' => CONTEXT_SYSTEM, @@ -375,26 +524,38 @@ class provider implements $sql = "SELECT DISTINCT e.id AS eventid FROM {context} ctx - INNER JOIN {event} e ON - (e.eventtype = 'site' AND ctx.contextlevel = :sitecontext) OR - (e.categoryid = ctx.instanceid AND e.eventtype = 'category' AND ctx.contextlevel = :categorycontext) OR - (e.courseid = ctx.instanceid AND (e.eventtype = 'course' OR e.eventtype = 'group' OR e.modulename != '0') AND ctx.contextlevel = :coursecontext) OR - (e.userid = ctx.instanceid AND e.eventtype = 'user' AND ctx.contextlevel = :usercontext) - WHERE ctx.id = :contextid"; - $events = $DB->get_records_sql($sql, $params); + INNER JOIN {event} e + ON (e.eventtype = 'site' + AND ctx.contextlevel = :sitecontext) + OR (e.categoryid = ctx.instanceid + AND e.eventtype = 'category' + AND ctx.contextlevel = :categorycontext) + OR (e.courseid = ctx.instanceid + AND (e.eventtype = 'course' + OR e.eventtype = 'group' + OR e.modulename != '0') + AND ctx.contextlevel = :coursecontext) + OR (e.userid = ctx.instanceid + AND e.eventtype = 'user' + AND ctx.contextlevel = :usercontext) + WHERE ctx.id = :contextid + {$whereusersql}"; } + $params += $userparams; - return $events; + return $DB->get_records_sql($sql, $params); } /** - * Helper function to return all Calendar Subscription id results for a specified context. + * Helper function to return all Calendar Subscription id results for a specified context and optionally + * included user list. * * @param \context $context + * @param array $userids * @return array * @throws \dml_exception */ - protected static function get_calendar_subscription_ids_by_context(\context $context) { + protected static function get_calendar_subscription_ids_by_context(\context $context, $userids = array()) { global $DB; // Calendar Subscriptions can exist at Site, Course Category, Course, Course Group, or User contexts. @@ -407,17 +568,36 @@ class provider implements 'contextid' => $context->id ]; + $whereusersql = ''; + $userparams = array(); + if (!empty($userids)) { + list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); + $whereusersql = "AND s.userid {$usersql}"; + } + // Get Calendar Subscriptions for the specified context. $sql = "SELECT DISTINCT s.id AS subscriptionid FROM {context} ctx - INNER JOIN {event_subscriptions} s ON - (s.eventtype = 'site' AND ctx.contextlevel = :sitecontext) OR - (s.categoryid = ctx.instanceid AND s.eventtype = 'category' AND ctx.contextlevel = :categorycontext) OR - (s.courseid = ctx.instanceid AND s.eventtype = 'course' AND ctx.contextlevel = :coursecontext) OR - (s.courseid = ctx.instanceid AND s.eventtype = 'group' AND ctx.contextlevel = :groupcontext) OR - (s.userid = ctx.instanceid AND s.eventtype = 'user' AND ctx.contextlevel = :usercontext) - WHERE ctx.id = :contextid"; + INNER JOIN {event_subscriptions} s + ON (s.eventtype = 'site' + AND ctx.contextlevel = :sitecontext) + OR (s.categoryid = ctx.instanceid + AND s.eventtype = 'category' + AND ctx.contextlevel = :categorycontext) + OR (s.courseid = ctx.instanceid + AND s.eventtype = 'course' + AND ctx.contextlevel = :coursecontext) + OR (s.courseid = ctx.instanceid + AND s.eventtype = 'group' + AND ctx.contextlevel = :groupcontext) + OR (s.userid = ctx.instanceid + AND s.eventtype = 'user' + AND ctx.contextlevel = :usercontext) + WHERE ctx.id = :contextid + {$whereusersql}"; + + $params += $userparams; return $DB->get_records_sql($sql, $params); } @@ -552,5 +732,4 @@ class provider implements $DB->delete_records_list($tablename, $field, $batchrecord); } } - } diff --git a/calendar/tests/privacy_test.php b/calendar/tests/privacy_test.php index 4a47348c623..1b0edc65657 100644 --- a/calendar/tests/privacy_test.php +++ b/calendar/tests/privacy_test.php @@ -34,6 +34,7 @@ use \core_privacy\local\metadata\collection; use \core_privacy\local\request\approved_contextlist; use \core_privacy\local\request\writer; use \core_privacy\tests\provider_testcase; +use \core_privacy\local\request\approved_userlist; /** * Unit tests for calendar/classes/privacy/provider @@ -429,6 +430,300 @@ class core_calendar_privacy_testcase extends provider_testcase { $this->assertCount(1, $eventsubscriptions); } + /** + * Test that only users with a user context are fetched. + */ + public function test_get_users_in_context() { + $component = 'core_calendar'; + + // Create user1 to create Calendar Events and Subscriptions. + $user1 = $this->getDataGenerator()->create_user(); + $usercontext1 = context_user::instance($user1->id); + // Create user2 to create Calendar Events and Subscriptions. + $user2 = $this->getDataGenerator()->create_user(); + $usercontext2 = context_user::instance($user2->id); + // Create user3 to create Calendar Events and Subscriptions. + $user3 = $this->getDataGenerator()->create_user(); + $usercontext3 = context_user::instance($user3->id); + + // Create a Category and Courses to assign Calendar Events and Subscriptions. + $category = $this->getDataGenerator()->create_category(); + $categorycontext = context_coursecat::instance($category->id); + $course1 = $this->getDataGenerator()->create_course(); + $course1context = context_course::instance($course1->id); + $course2 = $this->getDataGenerator()->create_course(); + $course2context = context_course::instance($course2->id); + $course3 = $this->getDataGenerator()->create_course(); + $course3context = context_course::instance($course3->id); + $grouprecord = (object)[ + 'courseid' => $course3->id, + 'name' => 'test_group' + ]; + $course3group = $this->getDataGenerator()->create_group($grouprecord); + + // Add Category Calendar Events for Category. + $this->setUser($user1); + $this->create_test_standard_calendar_event('category', $user1->id, time(), '', + $category->id); + $this->setUser($user2); + $this->create_test_standard_calendar_event('category', $user2->id, time(), '', + $category->id); + + // Add User Calendar Events for user1 and user2. + $this->setUser($user1); + $this->create_test_standard_calendar_event('user', $user1->id, time(), ''); + $this->create_test_standard_calendar_event('user', $user1->id, time(), '', + 0, $course1->id); + $this->create_test_standard_calendar_event('user', $user1->id, time(), '', + 0, $course2->id); + $this->setUser($user2); + $this->create_test_standard_calendar_event('user', $user2->id, time(), '', + 0, $course1->id); + + // Add a Course Calendar Events for Course 1. + $this->setUser($user1); + $this->create_test_standard_calendar_event('course', $user1->id, time(), '', + 0, $course1->id); + $this->setUser($user2); + $this->create_test_standard_calendar_event('course', $user2->id, time(), '', + 0, $course1->id); + + // Add a Course Assignment Action Calendar Event for Course 2. + $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); + $params['course'] = $course2->id; + $params['assignsubmission_onlinetext_enabled'] = 1; + $instance = $generator->create_instance($params); + $cm = get_coursemodule_from_instance('assign', $instance->id); + $modulecontext = context_module::instance($cm->id); + $assign = new assign($modulecontext, $cm, $course2); + $this->setUser($user2); + $this->create_test_action_calendar_event('duedate', $course2->id, $instance->id, + 'assign', $user2->id, time()); + $this->create_test_action_calendar_event('gradingduedate', $course2->id, $instance->id, + 'assign', $user2->id, time()); + + // Add a Calendar Subscription and Group Calendar Event to Course 3. + $this->create_test_standard_calendar_event('group', $user2->id, time(), '', 0, + $course3->id, $course3group->id); + $this->setUser($user3); + $this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user3->id, + 0, $course3->id); + + // The user list for usercontext1 should return user1. + $userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component); + provider::get_users_in_context($userlist1); + $this->assertCount(1, $userlist1); + $this->assertTrue(in_array($user1->id, $userlist1->get_userids())); + // The user list for usercontext2 should return user2. + $userlist2 = new \core_privacy\local\request\userlist($usercontext2, $component); + provider::get_users_in_context($userlist2); + $this->assertCount(1, $userlist2); + $this->assertTrue(in_array($user2->id, $userlist2->get_userids())); + // The user list for course1context should return user1 and user2. + $userlist3 = new \core_privacy\local\request\userlist($course1context, $component); + provider::get_users_in_context($userlist3); + $this->assertCount(2, $userlist3); + $this->assertTrue(in_array($user1->id, $userlist3->get_userids())); + $this->assertTrue(in_array($user2->id, $userlist3->get_userids())); + // The user list for course2context should not return any users. + $userlist4 = new \core_privacy\local\request\userlist($course2context, $component); + provider::get_users_in_context($userlist4); + $this->assertCount(0, $userlist4); + // The user list for course3context should return user2 and user3. + $userlist5 = new \core_privacy\local\request\userlist($course3context, $component); + provider::get_users_in_context($userlist5); + $this->assertCount(2, $userlist5); + $this->assertTrue(in_array($user2->id, $userlist5->get_userids())); + $this->assertTrue(in_array($user3->id, $userlist5->get_userids())); + // The user list for categorycontext should return user1 and user2. + $userlist6 = new \core_privacy\local\request\userlist($categorycontext, $component); + provider::get_users_in_context($userlist6); + $this->assertCount(2, $userlist6); + $this->assertTrue(in_array($user1->id, $userlist6->get_userids())); + $this->assertTrue(in_array($user2->id, $userlist6->get_userids())); + // The user list for modulecontext should return user2. + $userlist7 = new \core_privacy\local\request\userlist($modulecontext, $component); + provider::get_users_in_context($userlist7); + $this->assertCount(1, $userlist7); + $this->assertTrue(in_array($user2->id, $userlist7->get_userids())); + // The user list for usercontext3 should not return any users. + $userlist8 = new \core_privacy\local\request\userlist($usercontext3, $component); + provider::get_users_in_context($userlist8); + $this->assertCount(0, $userlist8); + } + + /** + * Test that data for users in approved userlist is deleted. + */ + public function test_delete_data_for_users() { + $component = 'core_calendar'; + + // Create user1 to create Calendar Events and Subscriptions. + $user1 = $this->getDataGenerator()->create_user(); + $usercontext1 = context_user::instance($user1->id); + // Create user2 to create Calendar Events and Subscriptions. + $user2 = $this->getDataGenerator()->create_user(); + $usercontext2 = context_user::instance($user2->id); + // Create user3 to create Calendar Events and Subscriptions. + $user3 = $this->getDataGenerator()->create_user(); + $usercontext3 = context_user::instance($user3->id); + + // Create a Category and Courses to assign Calendar Events and Subscriptions. + $category = $this->getDataGenerator()->create_category(); + $categorycontext = context_coursecat::instance($category->id); + $course1 = $this->getDataGenerator()->create_course(); + $course1context = context_course::instance($course1->id); + $course2 = $this->getDataGenerator()->create_course(); + $course2context = context_course::instance($course2->id); + $course3 = $this->getDataGenerator()->create_course(); + $course3context = context_course::instance($course3->id); + $grouprecord = (object)[ + 'courseid' => $course3->id, + 'name' => 'test_group' + ]; + $course3group = $this->getDataGenerator()->create_group($grouprecord); + + // Add Category Calendar Events for Category. + $this->setUser($user1); + $this->create_test_standard_calendar_event('category', $user1->id, time(), '', + $category->id); + $this->setUser($user2); + $this->create_test_standard_calendar_event('category', $user2->id, time(), '', + $category->id); + + // Add User Calendar Events for user1 and user2. + $this->setUser($user1); + $this->create_test_standard_calendar_event('user', $user1->id, time(), ''); + $this->create_test_standard_calendar_event('user', $user1->id, time(), '', + 0, $course1->id); + $this->create_test_standard_calendar_event('user', $user1->id, time(), '', + 0, $course2->id); + $this->setUser($user2); + $this->create_test_standard_calendar_event('user', $user2->id, time(), '', + 0, $course1->id); + + // Add a Course Calendar Events for Course 1. + $this->setUser($user1); + $this->create_test_standard_calendar_event('course', $user1->id, time(), '', + 0, $course1->id); + $this->setUser($user2); + $this->create_test_standard_calendar_event('course', $user2->id, time(), '', + 0, $course1->id); + + // Add a Course Assignment Action Calendar Event for Course 2. + $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); + $params['course'] = $course2->id; + $params['assignsubmission_onlinetext_enabled'] = 1; + $instance = $generator->create_instance($params); + $cm = get_coursemodule_from_instance('assign', $instance->id); + $modulecontext = context_module::instance($cm->id); + $assign = new assign($modulecontext, $cm, $course2); + $this->setUser($user2); + $this->create_test_action_calendar_event('duedate', $course2->id, $instance->id, + 'assign', $user2->id, time()); + $this->create_test_action_calendar_event('gradingduedate', $course2->id, $instance->id, + 'assign', $user2->id, time()); + + // Add a Calendar Subscription and Group Calendar Event to Course 3. + $this->create_test_standard_calendar_event('group', $user2->id, time(), '', 0, + $course3->id, $course3group->id); + $this->setUser($user3); + $this->create_test_calendar_subscription('course', 'https://calendar.google.com/', $user3->id, + 0, $course3->id); + + // The user list for usercontext1 should return user1. + $userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component); + provider::get_users_in_context($userlist1); + $this->assertCount(1, $userlist1); + // The user list for usercontext2 should return user2. + $userlist2 = new \core_privacy\local\request\userlist($usercontext2, $component); + provider::get_users_in_context($userlist2); + $this->assertCount(1, $userlist2); + // The user list for course1context should return user1 and user2. + $userlist3 = new \core_privacy\local\request\userlist($course1context, $component); + provider::get_users_in_context($userlist3); + $this->assertCount(2, $userlist3); + // The user list for course2context should not return any users. + $userlist4 = new \core_privacy\local\request\userlist($course2context, $component); + provider::get_users_in_context($userlist4); + $this->assertCount(0, $userlist4); + // The user list for course3context should return user2 and user3. + $userlist5 = new \core_privacy\local\request\userlist($course3context, $component); + provider::get_users_in_context($userlist5); + $this->assertCount(2, $userlist5); + // The user list for categorycontext should return user1 and user2. + $userlist6 = new \core_privacy\local\request\userlist($categorycontext, $component); + provider::get_users_in_context($userlist6); + $this->assertCount(2, $userlist6); + // The user list for modulecontext should return user2. + $userlist7 = new \core_privacy\local\request\userlist($modulecontext, $component); + provider::get_users_in_context($userlist7); + $this->assertCount(1, $userlist7); + // The user list for usercontext3 should not return any users. + $userlist8 = new \core_privacy\local\request\userlist($usercontext3, $component); + provider::get_users_in_context($userlist8); + $this->assertCount(0, $userlist8); + + // Convert $userlist1 into an approved_contextlist. + $approvedlist1 = new approved_userlist($usercontext1, $component, $userlist1->get_userids()); + // Delete using delete_data_for_user. + provider::delete_data_for_users($approvedlist1); + // The user list for usercontext1 should not return any users. + $userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component); + provider::get_users_in_context($userlist1); + $this->assertCount(0, $userlist1); + // The user list for usercontext2 should still return users2. + $userlist2 = new \core_privacy\local\request\userlist($usercontext2, $component); + provider::get_users_in_context($userlist2); + $this->assertCount(1, $userlist2); + + // Convert $userlist3 into an approved_contextlist. + // Pass an empty array as a value for the approved user list. + $approvedlist2 = new approved_userlist($course1context, $component, []); + // Delete using delete_data_for_user. + provider::delete_data_for_users($approvedlist2); + // The user list for course1context should return user1 and user2. + $userlist3 = new \core_privacy\local\request\userlist($course1context, $component); + provider::get_users_in_context($userlist3); + $this->assertCount(2, $userlist3); + $this->assertTrue(in_array($user1->id, $userlist3->get_userids())); + $this->assertTrue(in_array($user2->id, $userlist3->get_userids())); + + // Convert $userlist3 into an approved_contextlist. + // Pass the ID of user1 as a value for the approved user list. + $approvedlist2 = new approved_userlist($course1context, $component, [$user1->id]); + // Delete using delete_data_for_user. + provider::delete_data_for_users($approvedlist2); + // The user list for course1context should return user2. + $userlist3 = new \core_privacy\local\request\userlist($course1context, $component); + provider::get_users_in_context($userlist3); + $this->assertCount(1, $userlist3); + $this->assertTrue(in_array($user2->id, $userlist3->get_userids())); + + // The user list for course3context should still return user2 and user3. + $userlist5 = new \core_privacy\local\request\userlist($course3context, $component); + provider::get_users_in_context($userlist5); + $this->assertCount(2, $userlist5); + + // Convert $userlist6 into an approved_contextlist. + $approvedlist3 = new approved_userlist($categorycontext, $component, $userlist6->get_userids()); + // Delete using delete_data_for_user. + provider::delete_data_for_users($approvedlist3); + // The user list for categorycontext should not return any users. + $userlist6 = new \core_privacy\local\request\userlist($categorycontext, $component); + provider::get_users_in_context($userlist6); + $this->assertCount(0, $userlist6); + + // Convert $userlist7 into an approved_contextlist. + $approvedlist4 = new approved_userlist($modulecontext, $component, $userlist7->get_userids()); + // Delete using delete_data_for_user. + provider::delete_data_for_users($approvedlist4); + // The user list for modulecontext should not return any users. + $userlist7 = new \core_privacy\local\request\userlist($modulecontext, $component); + provider::get_users_in_context($userlist7); + $this->assertCount(0, $userlist7); + } + // Start of helper functions. /**