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.
323667
public static function get_users_in_context(userlist $userlist) {
        $context = $userlist->get_context();

        // When we process user deletions and expiries, we always delete from the user context.
        // As a result the cohort role assignments would be deleted, which has a knock-on effect with courses
        // as roles may change and data may be removed earlier than it should be.

        $allowedcontextlevels = [
            CONTEXT_SYSTEM,
            CONTEXT_COURSECAT
        ];

        if (!in_array($context->contextlevel, $allowedcontextlevels)) {
            return;
        }

        $sql = "SELECT tc.userid as userid
                  FROM {tool_cohortroles} tc
                  JOIN {cohort} c
                       ON tc.cohortid = c.id
                 WHERE c.contextid = :contextid";

        $params = [
            'contextid' => $context->id
        ];

        $userlist->add_from_sql('userid', $sql, $params);
    }
502868
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);
    }
387467
public static function delete_data_for_users(approved_userlist $userlist) {

        $context = $userlist->get_context();

        if ($context instanceof \context_user) {
            \core_userkey\privacy\provider::delete_userkeys('rss', $context->instanceid);
        }
    }
954163
public static function get_users_in_context(userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if (!$context instanceof \context_module) {
            return;
        }

        $params = [
            'instanceid' => $context->instanceid,
            'module' => 'workshop',
        ];

        // One query to fetch them all, one query to find them, one query to bring them all and into the userlist add them.
        $sql = "SELECT ws.authorid, ws.gradeoverby, wa.reviewerid, wa.gradinggradeoverby, wr.userid
                  FROM {course_modules} cm
                  JOIN {modules} m ON cm.module = m.id AND m.name = :module
                  JOIN {workshop} w ON cm.instance = w.id
                  JOIN {workshop_submissions} ws ON ws.workshopid = w.id
             LEFT JOIN {workshop_assessments} wa ON wa.submissionid = ws.id
             LEFT JOIN {workshop_aggregations} wr ON wr.workshopid = w.id
                 WHERE cm.id = :instanceid";

        $userids = [];
        $rs = $DB->get_recordset_sql($sql, $params);

        foreach ($rs as $r) {
            if ($r->authorid) {
                $userids[$r->authorid] = true;
            }
            if ($r->gradeoverby) {
                $userids[$r->gradeoverby] = true;
            }
            if ($r->reviewerid) {
                $userids[$r->reviewerid] = true;
            }
            if ($r->gradinggradeoverby) {
                $userids[$r->gradinggradeoverby] = true;
            }
            if ($r->userid) {
                $userids[$r->userid] = true;
            }
        }

        $rs->close();

        if ($userids) {
            $userlist->add_users(array_keys($userids));
        }
    }
148976
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if (!($context instanceof \context_course || $context instanceof \context_module)) {
            return;
        }

        $enrolltitools = $DB->get_fieldset_select('enrol_lti_tools', 'id', 'contextid = :contextid',
                ['contextid' => $context->id]);
        if (!empty($enrolltitools)) {
            list($toolsql, $toolparams) = $DB->get_in_or_equal($enrolltitools, SQL_PARAMS_NAMED);
            $userids = $userlist->get_userids();
            list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
            $params = $toolparams + $userparams;
            $DB->delete_records_select('enrol_lti_users', "toolid $toolsql AND userid $usersql", $params);
        }
    }
1101198
public static function get_users_in_context(userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if (!$context instanceof \context_user) {
            return;
        }

        $userid = $context->instanceid;

        // Messages are in the user context.
        // For the sake of performance, there is no need to call add_from_sql for each of the below cases.
        // It is enough to add the user's context as soon as we come to the conclusion that the user has some data.
        // Also, the order of checking is sorted by the probability of occurrence (just by guess).
        // There is no need to check the message_user_actions table, as there needs to be a message in order to be a message action.
        // There is no need to check the message_conversation_actions table, as there needs to be a conversation in order to
        // be a conversation action.
        // So, checking messages table would suffice.

        $hasdata = false;
        $hasdata = $hasdata || $DB->record_exists_select('notifications', 'useridfrom = ? OR useridto = ?', [$userid, $userid]);
        $sql = "SELECT mc.id
              FROM {message_conversations} mc
              JOIN {message_conversation_members} mcm
                ON (mcm.conversationid = mc.id AND mcm.userid = :userid)
             WHERE mc.contextid IS NULL";
        $hasdata = $hasdata || $DB->record_exists_sql($sql, ['userid' => $userid]);
        $sql = "SELECT mc.id
              FROM {message_conversations} mc
              JOIN {messages} m
                ON (m.conversationid = mc.id AND m.useridfrom = :useridfrom)
             WHERE mc.contextid IS NULL";
        $hasdata = $hasdata || $DB->record_exists_sql($sql, ['useridfrom' => $userid]);
        $hasdata = $hasdata || $DB->record_exists_select('message_contacts', 'userid = ? OR contactid = ?', [$userid, $userid]);
        $hasdata = $hasdata || $DB->record_exists_select('message_users_blocked', 'userid = ? OR blockeduserid = ?',
                        [$userid, $userid]);
        $hasdata = $hasdata || $DB->record_exists_select('message_contact_requests', 'userid = ? OR requesteduserid = ?',
                        [$userid, $userid]);

        if ($hasdata) {
            $userlist->add_user($userid);
        }

        // Add favourite conversations.
        $component = $userlist->get_component();
        if ($component != 'core_message') {
            $userlist->set_component('core_message');
        }
        \core_favourites\privacy\provider::add_userids_for_context($userlist, 'message_conversations');
        if ($component != 'core_message') {
            $userlist->set_component($component);
        }
    }
352151
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if ($context instanceof \context_user) {
            $DB->delete_records('repository_instances', ['userid' => $context->instanceid]);
        }
    }
224891
public static function add_userids_for_context(\core_privacy\local\request\userlist $userlist) {
        list($db, $table) = static::get_database_and_table();
        if (!$db || !$table) {
            return;
        }

        $userids = [];
        $records = $db->get_records($table, ['contextid' => $userlist->get_context()->id], '',
                'id, userid, relateduserid, realuserid');
        if (empty($records)) {
            return;
        }

        foreach ($records as $record) {
            $userids[] = $record->userid;
            if (!empty($record->relateduserid)) {
                $userids[] = $record->relateduserid;
            }
            if (!empty($record->realuserid)) {
                $userids[] = $record->realuserid;
            }
        }
        $userids = array_unique($userids);
        $userlist->add_users($userids);
    }
162563
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();
        $userids = $userlist->get_userids();

        list($useridsql, $useridsqlparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
        $params = ['contextid' => $context->id] + $useridsqlparams;

        $DB->delete_records_select('editor_atto_autosave', "contextid = :contextid AND userid {$useridsql}",
            $params);
    }
487503
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);
    }
880862
public static function get_users_in_context(userlist $userlist) {
        $context = $userlist->get_context();

        if (!$context instanceof \context_course) {
            return;
        }

        \core_group\privacy\provider::get_group_members_in_context($userlist, 'enrol_meta');
    }
391131
public static function get_users_in_context(userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if (!$context instanceof \context_course) {
            return;
        }

        $params = [
            'instanceid' => $context->instanceid
        ];

        $sql = "SELECT usermodified as userid
                  FROM {post}
                 WHERE module = 'notes'
                       AND courseid = :instanceid";

        $userlist->add_from_sql('userid', $sql, $params);

        $publishstates = [
            NOTES_STATE_PUBLIC,
            NOTES_STATE_SITE
        ];

        list($publishstatesql, $publishstateparams) = $DB->get_in_or_equal($publishstates, SQL_PARAMS_NAMED);
        $params += $publishstateparams;

        $sql = "SELECT userid
                  FROM {post}
                 WHERE module = 'notes'
                       AND courseid = :instanceid
                       AND publishstate {$publishstatesql}";

        $userlist->add_from_sql('userid', $sql, $params);
    }
1034674
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();
        $cm = $DB->get_record('course_modules', ['id' => $context->instanceid]);
        $forum = $DB->get_record('forum', ['id' => $cm->instance]);

        list($userinsql, $userinparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);
        $params = array_merge(['forumid' => $forum->id], $userinparams);

        $DB->delete_records_select('forum_track_prefs', "forumid = :forumid AND userid {$userinsql}", $params);
        $DB->delete_records_select('forum_subscriptions', "forum = :forumid AND userid {$userinsql}", $params);
        $DB->delete_records_select('forum_read', "forumid = :forumid AND userid {$userinsql}", $params);
        $DB->delete_records_select(
            'forum_queue',
            "userid {$userinsql} AND discussionid IN (SELECT id FROM {forum_discussions} WHERE forum = :forumid)",
            $params
        );
        $DB->delete_records_select('forum_discussion_subs', "forum = :forumid AND userid {$userinsql}", $params);

        // Do not delete discussion or forum posts.
        // Instead update them to reflect that the content has been deleted.
        $postsql = "userid {$userinsql} AND discussion IN (SELECT id FROM {forum_discussions} WHERE forum = :forumid)";
        $postidsql = "SELECT fp.id FROM {forum_posts} fp WHERE {$postsql}";

        // Update the subject.
        $DB->set_field_select('forum_posts', 'subject', '', $postsql, $params);

        // Update the subject and its format.
        $DB->set_field_select('forum_posts', 'message', '', $postsql, $params);
        $DB->set_field_select('forum_posts', 'messageformat', FORMAT_PLAIN, $postsql, $params);

        // Mark the post as deleted.
        $DB->set_field_select('forum_posts', 'deleted', 1, $postsql, $params);

        // Note: Do _not_ delete ratings of other users. Only delete ratings on the users own posts.
        // Ratings are aggregate fields and deleting the rating of this post will have an effect on the rating
        // of any post.
        \core_rating\privacy\provider::delete_ratings_select($context, 'mod_forum', 'post', "IN ($postidsql)", $params);

        // Delete all Tags.
        \core_tag\privacy\provider::delete_item_tags_select($context, 'mod_forum', 'forum_posts', "IN ($postidsql)", $params);

        // Delete all files from the posts.
        $fs = get_file_storage();
        $fs->delete_area_files_select($context->id, 'mod_forum', 'post', "IN ($postidsql)", $params);
        $fs->delete_area_files_select($context->id, 'mod_forum', 'attachment', "IN ($postidsql)", $params);
    }
288099
public static function get_users_in_context(userlist $userlist) {
        $context = $userlist->get_context();

        if (!$context instanceof \context_module) {
            return;
        }

        $params = [
            'cmid'    => $context->instanceid,
            'modname' => 'quiz',
        ];

        // Users who attempted the quiz.
        $sql = "SELECT qa.userid
                  FROM {course_modules} cm
                  JOIN {modules} m ON m.id = cm.module AND m.name = :modname
                  JOIN {quiz} q ON q.id = cm.instance
                  JOIN {quiz_attempts} qa ON qa.quiz = q.id
                 WHERE cm.id = :cmid AND qa.preview = 0";
        $userlist->add_from_sql('userid', $sql, $params);

        // Users with quiz overrides.
        $sql = "SELECT qo.userid
                  FROM {course_modules} cm
                  JOIN {modules} m ON m.id = cm.module AND m.name = :modname
                  JOIN {quiz} q ON q.id = cm.instance
                  JOIN {quiz_overrides} qo ON qo.quiz = q.id
                 WHERE cm.id = :cmid";
        $userlist->add_from_sql('userid', $sql, $params);

        // Question usages in context.
        // This includes where a user is the manual marker on a question attempt.
        $sql = "SELECT qa.uniqueid
                  FROM {course_modules} cm
                  JOIN {modules} m ON m.id = cm.module AND m.name = :modname
                  JOIN {quiz} q ON q.id = cm.instance
                  JOIN {quiz_attempts} qa ON qa.quiz = q.id
                 WHERE cm.id = :cmid AND qa.preview = 0";
        \core_question\privacy\provider::get_users_in_context_from_sql($userlist, 'qn', $sql, $params);
    }
477408
public static function get_users_in_context(userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if (!$context instanceof \context_user) {
            return;
        }

        $userid = $context->instanceid;

        $hasdata = false;
        $hasdata = $hasdata || $DB->record_exists_select('external_tokens', 'userid = ? OR creatorid = ?', [$userid, $userid]);
        $hasdata = $hasdata || $DB->record_exists('external_services_users', ['userid' => $userid]);

        if ($hasdata) {
            $userlist->add_user($userid);
        }
    }
519910
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;
        $context = $userlist->get_context();

        // Sanity check that context is at the User context level, then get the userid.
        if ($context->contextlevel !== CONTEXT_USER) {
            return;
        }

        $userids = $userlist->get_userids();
        list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
        $params = [
            'contextid' => $context->id,
            'contextuser' => CONTEXT_USER,
        ];
        $params = array_merge($params, $inparams);

        // Fetch the repository_onedrive_access IDs in the context for approved users.
        $sql = "SELECT roa.id
                  FROM {repository_onedrive_access} roa
                  JOIN {context} c ON c.instanceid = roa.usermodified
                   AND c.contextlevel = :contextuser
                   AND c.id = :contextid
                 WHERE roa.usermodified {$insql}";
        $accessids = $DB->get_fieldset_sql($sql, $params);

        // Delete the relevant repository_onedrive_access data.
        list($insql, $params) = $DB->get_in_or_equal($accessids, SQL_PARAMS_NAMED);
        $DB->delete_records_select('repository_onedrive_access', "id {$insql}", $params);
    }
356542
public static function add_contexts_for_userid(contextlist $contextlist, $userid) {
        list($db, $table) = static::get_database_and_table();
        if (!$db || !$table) {
            return;
        }

        $sql = 'userid = :userid1 OR relateduserid = :userid2 OR realuserid = :userid3';
        $params = ['userid1' => $userid, 'userid2' => $userid, 'userid3' => $userid];
        $contextids = $db->get_fieldset_select($table, 'DISTINCT contextid', $sql, $params);
        if (empty($contextids)) {
            return;
        }

        $sql = implode(' UNION ', array_map(function($id) use ($db) {
            return 'SELECT ' . $id . $db->sql_null_from_clause();
        }, $contextids));
        $contextlist->add_from_sql($sql, []);
    }