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.
321847
public static function get_users_in_context(\core_privacy\local\request\userlist $userlist) {
        $context = $userlist->get_context();

        if ($context->contextlevel == CONTEXT_COURSE) {
            $params = ['contextinstanceid' => $context->instanceid];

            $sql = "SELECT usermodified
                      FROM {grade_outcomes}
                     WHERE courseid = :contextinstanceid";
            $userlist->add_from_sql('usermodified', $sql, $params);

            $sql = "SELECT loggeduser
                      FROM {grade_outcomes_history}
                     WHERE courseid = :contextinstanceid";
            $userlist->add_from_sql('loggeduser', $sql, $params);

            $sql = "SELECT userid
                      FROM {scale}
                     WHERE courseid = :contextinstanceid";
            $userlist->add_from_sql('userid', $sql, $params);

            $sql = "SELECT loggeduser, userid
                      FROM {scale_history}
                     WHERE courseid = :contextinstanceid";
            $userlist->add_from_sql('loggeduser', $sql, $params);
            $userlist->add_from_sql('userid', $sql, $params);

            $sql = "SELECT loggeduser
                      FROM {grade_items_history}
                     WHERE courseid = :contextinstanceid";
            $userlist->add_from_sql('loggeduser', $sql, $params);

            $sql = "SELECT ggh.userid
                      FROM {grade_grades_history} ggh
                      JOIN {grade_items} gi ON ggh.itemid = gi.id
                     WHERE gi.courseid = :contextinstanceid";
            $userlist->add_from_sql('userid', $sql, $params);

            $sql = "SELECT gg.userid, gg.usermodified
                      FROM {grade_grades} gg
                      JOIN {grade_items} gi ON gg.itemid = gi.id
                     WHERE gi.courseid = :contextinstanceid";
            $userlist->add_from_sql('userid', $sql, $params);
            $userlist->add_from_sql('usermodified', $sql, $params);

            $sql = "SELECT loggeduser
                      FROM {grade_categories_history}
                     WHERE courseid = :contextinstanceid";
            $userlist->add_from_sql('loggeduser', $sql, $params);
        }

        // None of these are currently used (user deletion).
        if ($context->contextlevel == CONTEXT_SYSTEM) {
            $params = ['contextinstanceid' => 0];

            $sql = "SELECT usermodified
                      FROM {grade_outcomes}
                     WHERE (courseid IS NULL OR courseid < 1)";
            $userlist->add_from_sql('usermodified', $sql, []);

            $sql = "SELECT loggeduser
                      FROM {grade_outcomes_history}
                     WHERE (courseid IS NULL OR courseid < 1)";
            $userlist->add_from_sql('loggeduser', $sql, []);

            $sql = "SELECT userid
                      FROM {scale}
                     WHERE courseid = :contextinstanceid";
            $userlist->add_from_sql('userid', $sql, $params);

            $sql = "SELECT loggeduser, userid
                      FROM {scale_history}
                     WHERE courseid = :contextinstanceid";
            $userlist->add_from_sql('loggeduser', $sql, $params);
            $userlist->add_from_sql('userid', $sql, $params);
        }

        if ($context->contextlevel == CONTEXT_USER) {
            // If the grade item has been removed and we have an orphan entry then we link to the
            // user context.
            $sql = "SELECT ggh.userid
                      FROM {grade_grades_history} ggh
                 LEFT JOIN {grade_items} gi ON ggh.itemid = gi.id
                     WHERE gi.id IS NULL
                       AND ggh.userid = :contextinstanceid";
            $userlist->add_from_sql('userid', $sql, ['contextinstanceid' => $context->instanceid]);
        }
    }
1361373
public static function add_contexts_for_userid(contextlist $contextlist, $userid) {
        $sql = "
            SELECT l.contextid
              FROM {logstore_standard_log} l
             WHERE l.userid = :userid1
                OR l.relateduserid = :userid2
                OR l.realuserid = :userid3";
        $contextlist->add_from_sql($sql, [
            'userid1' => $userid,
            'userid2' => $userid,
            'userid3' => $userid,
        ]);
    }
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);
    }
143073
public static function add_userids_for_context(\core_privacy\local\request\userlist $userlist) {
        $context = $userlist->get_context();
        list($insql, $params) = static::get_sql_where_from_contexts([$context]);

        $sql = "SELECT l.userid
                  FROM {log} l
                 WHERE $insql";
        $userlist->add_from_sql('userid', $sql, $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, []);
    }
335832
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;
        $context = $userlist->get_context();

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

        // Prepare SQL to gather all completed IDs.
        $userids = $userlist->get_userids();
        list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);

        $sql = "SELECT ss.id
                  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
                 WHERE ctx.id = :contextid
                   AND ss.userid $insql";
        $params = array_merge($inparams, ['contextid' => $context->id]);

        static::delete_data('scorm_scoes_track', $sql, $params);
        static::delete_data('scorm_aicc_session', $sql, $params);
    }
989048
public static function delete_data_for_users(approved_userlist $userlist) {
        $context = $userlist->get_context();

        // Check what context we've been delivered.
        if (!$context instanceof \context_course) {
            return;
        }
        // Delete course completion data.
        \core_completion\privacy\provider::delete_completion_by_approved_userlist($userlist, $context->instanceid);
        // Delete course favourite data.
        \core_favourites\privacy\provider::delete_favourites_for_userlist($userlist, 'courses');
    }
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);
    }
977285
public static function delete_data_for_users(approved_userlist $userlist) {
        $context = $userlist->get_context();

        if ($context instanceof \context_system || $context instanceof \context_coursecat) {
            foreach ($userlist->get_userids() as $userid) {
                static::delete_data($context, $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);
    }
1326590
public static function delete_data_for_users(approved_userlist $userlist) {
        $context = $userlist->get_context();

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

        // Remove invalid users. If it ends up empty then early return.
        $userids = array_filter($userlist->get_userids(), function($userid) use($context) {
            return $context->instanceid == $userid;
        });

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

        static::delete_user_data($context->instanceid);
    }
1229845
public static function get_contexts_for_userid(int $userid) : contextlist {
        global $DB;
        $contextlist = new \core_privacy\local\request\contextlist();

        // Find the contexts of the frameworks, and related data, modified by the user.
        $sql = "
             SELECT DISTINCT ctx.id
               FROM {context} ctx
               JOIN {" . competency_framework::TABLE . "} cf
                 ON cf.contextid = ctx.id
          LEFT JOIN {" . competency::TABLE . "} c
                 ON c.competencyframeworkid = cf.id
          LEFT JOIN {" . related_competency::TABLE . "} cr
                 ON cr.competencyid = c.id
              WHERE cf.usermodified = :userid1
                 OR c.usermodified = :userid2
                 OR cr.usermodified = :userid3";
        $params = ['userid1' => $userid, 'userid2' => $userid, 'userid3' => $userid];
        $contextlist->add_from_sql($sql, $params);

        // Find the contexts of the templates, and related data, modified by the user.
        $sql = "
             SELECT DISTINCT ctx.id
               FROM {context} ctx
               JOIN {" . template::TABLE . "} tpl
                 ON tpl.contextid = ctx.id
          LEFT JOIN {" . template_cohort::TABLE . "} tch
                 ON tch.templateid = tpl.id
                AND tch.usermodified = :userid2
          LEFT JOIN {" . template_competency::TABLE . "} tc
                 ON tc.templateid = tpl.id
                AND tc.usermodified = :userid3
              WHERE tpl.usermodified = :userid1
                 OR tch.id IS NOT NULL
                 OR tc.id IS NOT NULL";
        $params = ['userid1' => $userid, 'userid2' => $userid, 'userid3' => $userid];
        $contextlist->add_from_sql($sql, $params);

        // Find the possible course contexts.
        $sql = "
             SELECT DISTINCT ctx.id
               FROM {" . course_competency::TABLE . "} cc
               JOIN {context} ctx
                 ON ctx.instanceid = cc.courseid
                AND ctx.contextlevel = :courselevel
              WHERE cc.usermodified = :userid";
        $params = ['courselevel' => CONTEXT_COURSE, 'userid' => $userid];
        $contextlist->add_from_sql($sql, $params);

        $sql = "
             SELECT DISTINCT ctx.id
               FROM {" . course_competency_settings::TABLE . "} ccs
               JOIN {context} ctx
                 ON ctx.instanceid = ccs.courseid
                AND ctx.contextlevel = :courselevel
              WHERE ccs.usermodified = :userid";
        $params = ['courselevel' => CONTEXT_COURSE, 'userid' => $userid];
        $contextlist->add_from_sql($sql, $params);

        $sql = "
             SELECT DISTINCT ctx.id
               FROM {" . user_competency_course::TABLE . "} ucc
               JOIN {context} ctx
                 ON ctx.instanceid = ucc.courseid
                AND ctx.contextlevel = :courselevel
              WHERE ucc.usermodified = :userid";
        $params = ['courselevel' => CONTEXT_COURSE, 'userid' => $userid];
        $contextlist->add_from_sql($sql, $params);

        // Find the possible module contexts.
        $sql = "
             SELECT DISTINCT ctx.id
               FROM {" . course_module_competency::TABLE . "} cmc
               JOIN {context} ctx
                 ON ctx.instanceid = cmc.cmid
                AND ctx.contextlevel = :modulelevel
              WHERE cmc.usermodified = :userid";
        $params = ['modulelevel' => CONTEXT_MODULE, 'userid' => $userid];
        $contextlist->add_from_sql($sql, $params);

        // Add user contexts through usermodified/reviewing of plan related data.
        $sql = "
             SELECT DISTINCT ctx.id
               FROM {" . plan::TABLE . "} p
               JOIN {context} ctx
                 ON ctx.instanceid = p.userid
                AND ctx.contextlevel = :userlevel
          LEFT JOIN {" . plan_competency::TABLE . "} pc
                 ON pc.planid = p.id
                AND pc.usermodified = :userid3
          LEFT JOIN {" . user_competency_plan::TABLE . "} upc
                 ON upc.planid = p.id
                AND upc.usermodified = :userid4
              WHERE p.usermodified = :userid1
                 OR p.reviewerid = :userid2
                 OR pc.id IS NOT NULL
                 OR upc.id IS NOT NULL";
        $params = [
            'userlevel' => CONTEXT_USER,
            'userid1' => $userid,
            'userid2' => $userid,
            'userid3' => $userid,
            'userid4' => $userid,
        ];
        $contextlist->add_from_sql($sql, $params);

        // Add user contexts through usermodified/reviewing of competency data.
        $sql = "
             SELECT DISTINCT ctx.id
               FROM {context} ctx
          LEFT JOIN {" . user_competency::TABLE . "} uc
                 ON uc.userid = ctx.instanceid
                AND ctx.contextlevel = :userlevel1
          LEFT JOIN {" . evidence::TABLE . "} e
                 ON e.usercompetencyid = uc.id
                AND (e.usermodified = :userid3 OR e.actionuserid = :userid4)
          LEFT JOIN {" . user_evidence::TABLE . "} ue
                 ON ue.userid = ctx.instanceid
                AND ctx.contextlevel = :userlevel2
                AND ue.usermodified = :userid5
          LEFT JOIN {" . user_evidence_competency::TABLE . "} uec
                 ON uec.userevidenceid = ue.id
                AND uec.usermodified = :userid6
              WHERE uc.usermodified = :userid1
                 OR uc.reviewerid = :userid2
                 OR e.id IS NOT NULL
                 OR ue.id IS NOT NULL
                 OR uec.id IS NOT NULL";
        $params = [
            'userlevel1' => CONTEXT_USER,
            'userlevel2' => CONTEXT_USER,
            'userid1' => $userid,
            'userid2' => $userid,
            'userid3' => $userid,
            'userid4' => $userid,
            'userid5' => $userid,
            'userid6' => $userid,
        ];
        $contextlist->add_from_sql($sql, $params);

        // Now, the easy part, we fetch the user context for user plans and competencies.
        // We also fetch the course context for the state of competencies for the user in courses.
        $sql = "
             SELECT DISTINCT ctx.id
               FROM {context} ctx
          LEFT JOIN {" . plan::TABLE . "} p
                 ON p.userid = ctx.instanceid
                AND ctx.contextlevel = :userlevel1
          LEFT JOIN {" . user_competency::TABLE . "} uc
                 ON uc.userid = ctx.instanceid
                AND ctx.contextlevel = :userlevel2
                AND uc.userid = :userid2
          LEFT JOIN {" . user_evidence::TABLE . "} ue
                 ON ue.userid = ctx.instanceid
                AND ctx.contextlevel = :userlevel3
                AND ue.userid = :userid3
          LEFT JOIN {" . user_competency_course::TABLE . "} ucc
                 ON ucc.courseid = ctx.instanceid
                AND ctx.contextlevel = :courselevel
                AND ucc.userid = :userid4
              WHERE p.userid = :userid1
                 OR uc.id IS NOT NULL
                 OR ue.id IS NOT NULL
                 OR ucc.id IS NOT NULL";
        $params = [
            'userlevel1' => CONTEXT_USER,
            'userlevel2' => CONTEXT_USER,
            'userlevel3' => CONTEXT_USER,
            'courselevel' => CONTEXT_COURSE,
            'userid1' => $userid,
            'userid2' => $userid,
            'userid3' => $userid,
            'userid4' => $userid,
        ];
        $contextlist->add_from_sql($sql, $params);

        // Include the user contexts in which the user commented.
        $sql = "
            SELECT ctx.id
              FROM {context} ctx
              JOIN {comments} c
                ON c.contextid = ctx.id
             WHERE c.component = :component
               AND c.commentarea IN (:planarea, :usercomparea)
               AND c.userid = :userid";
        $params = [
            'component' => 'competency',    // Must not be core_competency.
            'planarea' => 'plan',
            'usercomparea' => 'user_competency',
            'userid' => $userid
        ];
        $contextlist->add_from_sql($sql, $params);

        return $contextlist;
    }
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, []);
    }
1060388
public static function get_contexts_for_userid(int $userid) : \core_privacy\local\request\contextlist {
        $contextlist = new \core_privacy\local\request\contextlist();

        // Always add the user context so we're sure we're not dodging user keys, besides it's not costly to do so.
        $contextlist->add_user_context($userid);

        return $contextlist;
    }
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);
        }
    }
1027953
public static function add_contexts_for_userid(contextlist $contextlist, $userid) {
        $sql = "
            SELECT ctx.id
              FROM {context} ctx
              JOIN {log} l
                ON (l.cmid = 0 AND l.course = ctx.instanceid AND ctx.contextlevel = :courselevel)
                OR (l.cmid > 0 AND l.cmid = ctx.instanceid AND ctx.contextlevel = :modulelevel)
                OR (l.course <= 0 AND ctx.id = :syscontextid)
             WHERE l.userid = :userid";
        $params = [
            'courselevel' => CONTEXT_COURSE,
            'modulelevel' => CONTEXT_MODULE,
            'syscontextid' => SYSCONTEXTID,
            'userid' => $userid,
        ];
        $contextlist->add_from_sql($sql, $params);
    }
115170
public static function get_contexts_for_userid(int $userid) : \core_privacy\local\request\contextlist {
        $contextlist = new \core_privacy\local\request\contextlist();
        static::call_subplugins_method_with_args('add_contexts_for_userid', [$contextlist, $userid]);
        return $contextlist;
    }