Delete all user data for the specified user, in the specified contexts.

@param approved_contextlist $contextlist The approved contexts and user information to delete information for.
491112
public static function delete_data_for_user(approved_contextlist $contextlist) {
        global $DB;

        // Remove contexts different from COURSE_MODULE.
        $contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
            if ($context->contextlevel == CONTEXT_MODULE) {
                $carry[] = $context->id;
            }
            return $carry;
        }, []);

        if (empty($contextids)) {
            return;
        }
        $userid = $contextlist->get_user()->id;
        // Prepare SQL to gather all completed IDs.
        list($insql, $inparams) = $DB->get_in_or_equal($contextids, 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 ss.userid = :userid
                   AND ctx.id $insql";
        $params = array_merge($inparams, ['userid' => $userid]);

        static::delete_data('scorm_scoes_track', $sql, $params);
        static::delete_data('scorm_aicc_session', $sql, $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);
        }
    }
1242533
public static function delete_data_for_userlist(\core_privacy\local\request\approved_userlist $userlist) {
        global $DB;
        list($sql, $params) = static::get_sql_where_from_contexts([$userlist->get_context()]);
        if (empty($sql)) {
            return;
        }
        list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);
        $params = array_merge($params, $userparams);
        $DB->delete_records_select('log', "$sql AND userid $usersql", $params);
    }
1016032
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();
        // If the context isn't for a module then return early.
        if ($context->contextlevel != CONTEXT_MODULE) {
            return;
        }
        // Fetch the assignment.
        $assignment = self::get_assignment_by_context($context);
        $userids = $userlist->get_userids();

        list($inorequalsql, $params) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
        $params['assignmentid'] = $assignment->id;

        // Get submission ids.
        $sql = "
            SELECT s.id
            FROM {assignment_submissions} s
            JOIN {assignment} a ON s.assignment = a.id
            WHERE a.id = :assignmentid
            AND s.userid $inorequalsql
        ";

        $submissionids = $DB->get_records_sql($sql, $params);
        list($submissionidsql, $submissionparams) = $DB->get_in_or_equal(array_keys($submissionids), SQL_PARAMS_NAMED);
        $fs = get_file_storage();
        $fs->delete_area_files_select($context->id, 'mod_assignment', 'submission', $submissionidsql, $submissionparams);
        // Delete related tables.
        $DB->delete_records_list('assignment_submissions', 'id', array_keys($submissionids));
    }
546517
public static function delete_data_for_all_users_in_context(context $context) {
        global $DB;
        if ($context->contextlevel != CONTEXT_BLOCK) {
            return;
        }

        // Delete the user preferences.
        $instanceid = $context->instanceid;
        $DB->delete_records_list('user_preferences', 'name', [
            "block{$instanceid}hidden",
            "docked_block_instance_{$instanceid}"
        ]);
    }
1231340
public static function delete_data_for_user(approved_contextlist $contextlist) {
        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.

        // Remove contexts different from SYSTEM or COURSECAT.
        $contextids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
            if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT) {
                $carry[] = $context->id;
            }
            return $carry;
        }, []);

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

        $userid = $contextlist->get_user()->id;

        list($contextsql, $contextparams) =  $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
        $selectcontext = "contextid {$contextsql}";
        // Get the cohorts in the specified contexts.
        $cohortids = $DB->get_fieldset_select('cohort', 'id', $selectcontext, $contextparams);

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

        list($cohortsql, $cohortparams) =  $DB->get_in_or_equal($cohortids, SQL_PARAMS_NAMED);
        $selectcohort = "cohortid {$cohortsql} AND userid = :userid";
        $params = ['userid' => $userid] + $cohortparams;

        // Delete the tool_cohortroles records created for the userid.
        $DB->delete_records_select('tool_cohortroles', $selectcohort, $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);
    }
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]);
        }
    }
1192519
public static function delete_data_for_all_users_in_context(context $context) {
        global $DB;

        switch ($context->contextlevel) {
            case CONTEXT_USER:
                $userid = $context->instanceid;
                static::delete_user_evidence_of_prior_learning($userid);
                static::delete_user_plans($userid);
                static::delete_user_competencies($userid);
                break;

            case CONTEXT_COURSE:
                static::delete_user_competencies_in_course($context->instanceid);
                break;
        }
    }
1305104
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

        // Export user agreements.
        foreach ($contextlist->get_contexts() as $context) {
            if ($context->contextlevel == CONTEXT_USER) {
                static::export_policy_agreements_for_context($context);
            } else if ($context->contextlevel == CONTEXT_SYSTEM) {
                static::export_authored_policies($contextlist->get_user());
            }
        }
    }
906672
public static function delete_data_for_user(approved_contextlist $contextlist) {
        global $DB;

        if (empty($contextlist->count())) {
            return;
        }

        $userid = $contextlist->get_user()->id;

        // Only retrieve assignment submissions submitted by the user for deletion.
        $assignmentsubmissionids = array_keys(self::get_assignment_submissions_by_contextlist($contextlist, $userid));
        $DB->delete_records_list('assignment_submissions', 'id', $assignmentsubmissionids);

        // Delete all file uploads associated with the assignment submission for the user's specified list of contexts.
        $fs = get_file_storage();
        foreach ($contextlist->get_contextids() as $contextid) {
            foreach ($assignmentsubmissionids as $submissionid) {
                $fs->delete_area_files($contextid, 'mod_assignment', 'submission', $submissionid);
            }
        }
    }
1203217
public static function delete_data_for_all_users_in_context(context $context) {
        list($db, $table) = static::get_database_and_table();
        if (!$db || !$table) {
            return;
        }
        $db->delete_records($table, ['contextid' => $context->id]);
    }
1299852
public static function delete_data_for_user(approved_contextlist $contextlist) {
        global $DB;

        if (empty($contextlist->count())) {
            return;
        }

        $user = $contextlist->get_user();
        $recordstobedeleted = [];

        foreach ($contextlist->get_contexts() as $context) {
            $sql = "SELECT " . self::sql_fields() . "
                FROM {context} ctx
                JOIN {course_modules} cm ON cm.id = ctx.instanceid
                JOIN {modules} m ON m.id = cm.module AND m.name = :modname
                JOIN {data} d ON d.id = cm.instance
                JOIN {data_records} dr ON dr.dataid = d.id AND dr.userid = :userid
                LEFT JOIN {data_content} dc ON dc.recordid = dr.id
                LEFT JOIN {data_fields} df ON df.id = dc.fieldid
                WHERE ctx.id = :ctxid AND ctx.contextlevel = :contextlevel
                ORDER BY dr.id";
            $rs = $DB->get_recordset_sql($sql, ['ctxid' => $context->id, 'contextlevel' => CONTEXT_MODULE,
                'modname' => 'data', 'userid' => $user->id]);
            foreach ($rs as $row) {
                self::mark_data_content_for_deletion($context, $row);
                $recordstobedeleted[$row->recordid] = $row->recordid;
            }
            $rs->close();
            self::delete_data_records($context, $recordstobedeleted);
        }

        // Additionally remove comments this user made on other entries.
        \core_comment\privacy\provider::delete_comments_for_user($contextlist, 'mod_data', 'database_entry');

        // We do not delete ratings made by this user on other records because it may change grades.
    }
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);
    }
1366962
public static function delete_data_for_users(approved_userlist $userlist) {
        global $DB;

        $context = $userlist->get_context();
        $userids = $userlist->get_userids();
        $instanceid = $DB->get_field('course_modules', 'instance', ['id' => $context->instanceid], MUST_EXIST);
        list($userinsql, $userinparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);

        $glossaryentrieswhere = "glossaryid = :instanceid AND userid {$userinsql}";
        $userinstanceparams = $userinparams + ['instanceid' => $instanceid];

        $entriesobject = $DB->get_recordset_select('glossary_entries', $glossaryentrieswhere, $userinstanceparams, 'id', 'id');
        $entries = [];

        foreach ($entriesobject as $entry) {
            $entries[] = $entry->id;
        }

        $entriesobject->close();

        if (!$entries) {
            return;
        }

        list($insql, $inparams) = $DB->get_in_or_equal($entries, SQL_PARAMS_NAMED);

        // Delete related entry aliases.
        $DB->delete_records_list('glossary_alias', 'entryid', $entries);

        // Delete related entry categories.
        $DB->delete_records_list('glossary_entries_categories', 'entryid', $entries);

        // Delete related entry and attachment files.
        get_file_storage()->delete_area_files_select($context->id, 'mod_glossary', 'entry', $insql, $inparams);
        get_file_storage()->delete_area_files_select($context->id, 'mod_glossary', 'attachment', $insql, $inparams);

        // Delete user tags related to this glossary.
        \core_tag\privacy\provider::delete_item_tags_select($context, 'mod_glossary', 'glossary_entries', $insql, $inparams);

        // Delete related ratings.
        \core_rating\privacy\provider::delete_ratings_select($context, 'mod_glossary', 'entry', $insql, $inparams);

        // Delete comments.
        \core_comment\privacy\provider::delete_comments_for_users($userlist, 'mod_glossary', 'glossary_entry');

        // Now delete all user related entries.
        $deletewhere = "glossaryid = :instanceid AND userid {$userinsql}";
        $DB->delete_records_select('glossary_entries', $deletewhere, $userinstanceparams);
    }
1044130
public static function delete_data_for_user(approved_contextlist $contextlist) {
        global $DB;
        $context = \context_system::instance();
        if (!$contextlist->count() || !in_array($context->id, $contextlist->get_contextids())) {
            return;
        }

        // Do not delete tags themselves in case they are used by somebody else.
        // If the user is the only one using the tag, it will be automatically deleted anyway during the next cron cleanup.
        $DB->set_field_select('tag', 'userid', 0, 'userid = ?', [$contextlist->get_user()->id]);
    }
1128408
public static function export_user_data(approved_contextlist $contextlist) {
        $context = $contextlist->current();
        $user = \core_user::get_user($contextlist->get_user()->id);
        static::export_user($user, $context);
        static::export_password_history($user->id, $context);
        static::export_password_resets($user->id, $context);
        static::export_lastaccess($user->id, $context);
        static::export_course_requests($user->id, $context);
        static::export_user_devices($user->id, $context);
        static::export_user_session_data($user->id, $context);
    }