Get the list of users who have data within a context.

@param   \core_privacy\local\request\userlist    $userlist   The userlist containing the list of users who have data in this context/plugin combination.
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);
    }
783050
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if ($context instanceof \context_course) {
            list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);

            $sql = "SELECT ue.id
                      FROM {user_enrolments} ue
                      JOIN {enrol} e ON e.id = ue.enrolid
                     WHERE e.courseid = :courseid
                           AND ue.userid {$usersql}";

            $params = ['courseid' => $context->instanceid] + $userparams;
            $enrolsids = $DB->get_fieldset_sql($sql, $params);

            if (!empty($enrolsids)) {
                list($insql, $inparams) = $DB->get_in_or_equal($enrolsids, SQL_PARAMS_NAMED);
                static::delete_user_data($insql, $inparams);
            }
        }
    }
535725
public static function get_users_in_context(userlist $userlist) {
        $context = $userlist->get_context();

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

        static::get_group_members_in_context($userlist, '');
    }
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, []);
    }
754777
public static function get_users_in_context(userlist $userlist) {
        $context = $userlist->get_context();

        if (!is_a($context, \context_module::class)) {
            return;
        }

        // Find users with glossary entries.
        $sql = "SELECT ge.userid
                  FROM {context} c
                  JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
                  JOIN {modules} m ON m.id = cm.module AND m.name = :modname
                  JOIN {glossary} g ON g.id = cm.instance
                  JOIN {glossary_entries} ge ON ge.glossaryid = g.id
                 WHERE c.id = :contextid";

        $params = [
            'contextid' => $context->id,
            'contextlevel' => CONTEXT_MODULE,
            'modname' => 'glossary',
        ];

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

        // Find users with glossary comments.
        \core_comment\privacy\provider::get_users_in_context_from_sql($userlist, 'com', 'mod_glossary', 'glossary_entry',
                $context->id);

        // Find users with glossary ratings.
        $sql = "SELECT ge.id
                  FROM {context} c
                  JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
                  JOIN {modules} m ON m.id = cm.module AND m.name = :modname
                  JOIN {glossary} g ON g.id = cm.instance
                  JOIN {glossary_entries} ge ON ge.glossaryid = g.id
                 WHERE c.id = :contextid";

        $params = [
            'contextid' => $context->id,
            'contextlevel' => CONTEXT_MODULE,
            'modname' => 'glossary',
        ];

        \core_rating\privacy\provider::get_users_in_context_from_sql($userlist, 'rat', 'mod_glossary', 'entry', $sql, $params);
    }
1007064
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if ($context->contextlevel != CONTEXT_MODULE) {
            // Only quiz module will be handled.
            return;
        }

        $cm = get_coursemodule_from_id('quiz', $context->instanceid);
        if (!$cm) {
            // Only quiz module will be handled.
            return;
        }

        $quizobj = \quiz::create($cm->instance);
        $quiz = $quizobj->get_quiz();

        $userids = $userlist->get_userids();

        // Handle the 'quizaccess' quizaccess.
        manager::plugintype_class_callback(
                'quizaccess',
                quizaccess_user_provider::class,
                'delete_quizaccess_data_for_users',
                [$userlist]
        );

        foreach ($userids as $userid) {
            // Remove overrides for this user.
            $overrides = $DB->get_records('quiz_overrides' , [
                'quiz' => $quizobj->get_quizid(),
                'userid' => $userid,
            ]);

            foreach ($overrides as $override) {
                quiz_delete_override($quiz, $override->id, false);
            }

            // This will delete all question attempts, quiz attempts, and quiz grades for this user in the given quiz.
            quiz_delete_user_attempts($quizobj, (object)['id' => $userid]);
        }
    }
371739
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if ($context instanceof \context_course) {
            list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);
            $select = "courseid = :courseid AND userid {$usersql}";
            $params = ['courseid' => $context->instanceid] + $userparams;

            $DB->delete_records_select('stats_user_daily', $select, $params);
            $DB->delete_records_select('stats_user_weekly', $select, $params);
            $DB->delete_records_select('stats_user_monthly', $select, $params);
        }
    }
614140
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);
        }
    }
113095
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;
        $context = $userlist->get_context();
        $userids = $userlist->get_userids();

        if ($context->contextlevel != CONTEXT_MODULE) {
            return;
        }

        // Remove only individual subwikis. Contributions to collaborative wikis is not considered personal contents.
        list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
        $params = [
            'wiki' => 'wiki',
            'contextmod' => CONTEXT_MODULE,
            'contextid' => $context->id,
        ];

        $params = array_merge($inparams, $params);
        $sql = "SELECT s.id
                  FROM {context} ctx
                  JOIN {course_modules} cm ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextmod
                  JOIN {modules} m ON m.name = :wiki AND cm.module = m.id
                  JOIN {wiki_subwikis} s ON s.wikiid = cm.instance
                 WHERE ctx.id = :contextid
                   AND s.userid {$insql}";

        $subwikis = $DB->get_fieldset_sql($sql, $params);

        if ($subwikis) {
            // We found individual subwikis that need to be deleted completely.

            $fs = get_file_storage();
            foreach ($subwikis as $subwikiid) {
                $fs->delete_area_files($context->id, 'mod_wiki', 'attachments', $subwikiid);
                \core_comment\privacy\provider::delete_comments_for_all_users_select(context::instance_by_id($context->id),
                    'mod_wiki', 'wiki_page', "IN (SELECT id FROM {wiki_pages} WHERE subwikiid=:subwikiid)",
                    ['subwikiid' => $subwikiid]);
            }

            list($insql, $inparams) = $DB->get_in_or_equal($subwikis, SQL_PARAMS_NAMED);
            $params = ['component' => 'mod_wiki', 'itemtype' => 'page'];
            $params = array_merge($inparams, $params);
            $sql = "DELETE FROM {tag_instance}
                          WHERE component=:component
                            AND itemtype=:itemtype
                            AND itemid IN
                                (SELECT id
                                FROM {wiki_pages}
                                WHERE subwikiid $insql)";

            $DB->execute($sql, $params);

            $DB->delete_records_select('wiki_locks', "pageid IN (SELECT id FROM {wiki_pages} WHERE subwikiid {$insql})", $params);
            $DB->delete_records_select('wiki_versions', "pageid IN (SELECT id FROM {wiki_pages} WHERE subwikiid {$insql})",
                    $params);
            $DB->delete_records_select('wiki_synonyms', "subwikiid {$insql}", $params);
            $DB->delete_records_select('wiki_links', "subwikiid {$insql}", $params);
            $DB->delete_records_select('wiki_pages', "subwikiid {$insql}", $params);
            $DB->delete_records_select('wiki_subwikis', "id {$insql}", $params);
        }

        // Remove comments made by this user on all other wiki pages.
        \core_comment\privacy\provider::delete_comments_for_users($userlist, 'mod_wiki', 'wiki_page');
    }
1010965
public static function get_users_in_context(userlist $userlist) {
        $context = $userlist->get_context();

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

        $sql = "SELECT userid
                  FROM {tag}";

        $userlist->add_from_sql('userid', $sql, []);
    }
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);
    }
966289
public static function delete_data_for_users(approved_userlist $userlist) {
        $context = $userlist->get_context();
        $userids = $userlist->get_userids();

        // Since this falls within a user context, only that user should be valid.
        if ($context->contextlevel != CONTEXT_USER || count($userids) != 1 || $context->instanceid != $userids[0]) {
            return;
        }

        static::delete_user_data($userids[0]);
    }
795850
public static function get_users_in_context(userlist $userlist) {
        $context = $userlist->get_context();

        if (!is_a($context, \context_module::class)) {
            return;
        }

        $sql = "SELECT ss.userid
                  FROM {%s} ss
                  JOIN {modules} m
                    ON m.name = 'scorm'
                  JOIN {course_modules} cm
                    ON cm.instance = ss.scormid
                   AND cm.module = m.id
                  JOIN {context} ctx
                    ON ctx.instanceid = cm.id
                   AND ctx.contextlevel = :modlevel
                 WHERE ctx.id = :contextid";

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

        $userlist->add_from_sql('userid', sprintf($sql, 'scorm_scoes_track'), $params);
        $userlist->add_from_sql('userid', sprintf($sql, 'scorm_aicc_session'), $params);
    }
338847
public static function get_users_in_context(userlist $userlist) {
        $context = $userlist->get_context();

        if (!is_a($context, \context_module::class)) {
            return;
        }

        $params = [
            'lesson' => 'lesson',
            'modulelevel' => CONTEXT_MODULE,
            'contextid' => $context->id,
        ];

        // Mapping of lesson tables which may contain user data.
        $joins = [
            'lesson_attempts',
            'lesson_branch',
            'lesson_grades',
            'lesson_overrides',
            'lesson_timer',
        ];

        foreach ($joins as $join) {
            $sql = "
                SELECT lx.userid
                  FROM {lesson} l
                  JOIN {modules} m
                    ON m.name = :lesson
                  JOIN {course_modules} cm
                    ON cm.instance = l.id
                   AND cm.module = m.id
                  JOIN {context} ctx
                    ON ctx.instanceid = cm.id
                   AND ctx.contextlevel = :modulelevel
                  JOIN {{$join}} lx
                    ON lx.lessonid = l.id
                 WHERE ctx.id = :contextid";

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

        // 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.

        $userids = $userlist->get_userids();

        if (empty($userids)) {
            return;
        }

        $context = $userlist->get_context();

        $allowedcontextlevels = [
            CONTEXT_SYSTEM,
            CONTEXT_COURSECAT
        ];

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

        $cohortids = $DB->get_fieldset_select('cohort', 'id', 'contextid = :contextid',
            ['contextid' => $context->id]);

        if (empty($cohortids)) {
            return;
        }

        list($cohortsql, $cohortparams) = $DB->get_in_or_equal($cohortids, SQL_PARAMS_NAMED);
        list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);

        $params = $cohortparams + $userparams;
        $select = "cohortid {$cohortsql} AND userid {$usersql}";

        // Delete the tool_cohortroles records created in the specific context for an approved list of users.
        $DB->delete_records_select('tool_cohortroles', $select, $params);
    }
446384
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();

        if ($context->contextlevel != CONTEXT_COURSE) {
            return;
        }

        $userids = $userlist->get_userids();

        list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);

        $params = ['courseid' => $context->instanceid] + $userparams;

        $select = "courseid = :courseid AND userid $usersql";
        $DB->delete_records_select('enrol_paypal', $select, $params);

        // We do not want to delete the payment record when the user is just the receiver of payment.
        // In that case, we just delete the receiver's info from the transaction record.

        $select = "courseid = :courseid AND business IN (SELECT LOWER(email) FROM {user} WHERE id $usersql)";
        $DB->set_field_select('enrol_paypal', 'business', '', $select, $params);

        $select = "courseid = :courseid AND receiver_email IN (SELECT LOWER(email) FROM {user} WHERE id $usersql)";
        $DB->set_field_select('enrol_paypal', 'receiver_email', '', $select, $params);
    }
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);
    }