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

@param   approved_contextlist $contextlist The approved contexts to export information for.
769456
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

        // If the user has repository_instances data, then only the User context should be present so get the first context.
        $contexts = $contextlist->get_contexts();
        if (count($contexts) == 0) {
            return;
        }
        $context = reset($contexts);

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

        $sql = "SELECT DISTINCT
                       ri.id as id,
                       r.type as type,
                       ri.name as name,
                       ri.timecreated as timecreated,
                       ri.timemodified as timemodified
                  FROM {repository_instances} ri
                  JOIN {repository} r ON r.id = ri.typeid
                 WHERE ri.userid = :userid";

        $params = [
            'userid' => $userid
        ];

        $repositoryinstances = $DB->get_records_sql($sql, $params);

        foreach ($repositoryinstances as $repositoryinstance) {
            // The repository_instances data export is organised in: {User Context}/Repository plug-ins/{Plugin Name}/data.json.
            $subcontext = [
                get_string('plugin', 'core_repository'),
                get_string('pluginname', 'repository_' . $repositoryinstance->type)
            ];

            $data = (object) [
                'type' => $repositoryinstance->type,
                'name' => $repositoryinstance->name,
                'timecreated' => transform::datetime($repositoryinstance->timecreated),
                'timemodified' => transform::datetime($repositoryinstance->timemodified)
            ];

            writer::with_context($context)->export_data($subcontext, $data);
        }
    }
1160678
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

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

        $user = $contextlist->get_user();

        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);

        $sql = "SELECT cm.id AS cmid,
                       co.text as answer,
                       ca.timemodified
                  FROM {context} c
            INNER JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
            INNER JOIN {modules} m ON m.id = cm.module AND m.name = :modname
            INNER JOIN {choice} ch ON ch.id = cm.instance
            INNER JOIN {choice_options} co ON co.choiceid = ch.id
            INNER JOIN {choice_answers} ca ON ca.optionid = co.id AND ca.choiceid = ch.id
                 WHERE c.id {$contextsql}
                       AND ca.userid = :userid
              ORDER BY cm.id";

        $params = ['modname' => 'choice', 'contextlevel' => CONTEXT_MODULE, 'userid' => $user->id] + $contextparams;

        // Reference to the choice activity seen in the last iteration of the loop. By comparing this with the current record, and
        // because we know the results are ordered, we know when we've moved to the answers for a new choice activity and therefore
        // when we can export the complete data for the last activity.
        $lastcmid = null;

        $choiceanswers = $DB->get_recordset_sql($sql, $params);
        foreach ($choiceanswers as $choiceanswer) {
            // If we've moved to a new choice, then write the last choice data and reinit the choice data array.
            if ($lastcmid != $choiceanswer->cmid) {
                if (!empty($choicedata)) {
                    $context = \context_module::instance($lastcmid);
                    self::export_choice_data_for_user($choicedata, $context, $user);
                }
                $choicedata = [
                    'answer' => [],
                    'timemodified' => \core_privacy\local\request\transform::datetime($choiceanswer->timemodified),
                ];
            }
            $choicedata['answer'][] = $choiceanswer->answer;
            $lastcmid = $choiceanswer->cmid;
        }
        $choiceanswers->close();

        // The data for the last activity won't have been written yet, so make sure to write it now!
        if (!empty($choicedata)) {
            $context = \context_module::instance($lastcmid);
            self::export_choice_data_for_user($choicedata, $context, $user);
        }
    }
834683
public static function export_user_data(approved_contextlist $contextlist) {
        $user = $contextlist->get_user();
        foreach ($contextlist->get_contexts() as $context) {
            // Check if the context is a user context.
            if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $user->id) {
                $results = static::get_records($user->id);
                foreach ($results as $result) {
                    $data = (object) [
                        'name' => $result->name,
                        'description' => $result->description,
                        'data' => transform::date($result->data)
                    ];
                    \core_privacy\local\request\writer::with_context($context)->export_data([
                        get_string('pluginname', 'profilefield_datetime')], $data);
                }
            }
        }
    }
196171
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

        if (!count($contextlist)) {
            return;
        }

        $user = $contextlist->get_user();

        // Export general information about all workshops.
        foreach ($contextlist->get_contexts() as $context) {
            if ($context->contextlevel != CONTEXT_MODULE) {
                continue;
            }
            $data = helper::get_context_data($context, $user);
            static::append_extra_workshop_data($context, $user, $data, []);
            writer::with_context($context)->export_data([], $data);
            helper::export_context_files($context, $user);
        }

        // Export the user's own submission and all example submissions he/she created.
        static::export_submissions($contextlist);

        // Export all given assessments.
        static::export_assessments($contextlist);
    }
581359
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

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

        $user = $contextlist->get_user();
        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
        $ratingquery = \core_rating\privacy\provider::get_sql_join('r', 'mod_glossary', 'entry', 'ge.id', $user->id);

        $sql = "SELECT ge.id as entryid,
                       cm.id AS cmid,
                       ge.userid,
                       ge.concept,
                       ge.definition,
                       ge.definitionformat,
                       ge.attachment,
                       ge.timecreated,
                       ge.timemodified
                  FROM {glossary_entries} ge
                  JOIN {glossary} g ON ge.glossaryid = g.id
                  JOIN {course_modules} cm ON g.id = cm.instance
                  JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
                  JOIN {context} c ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
             LEFT JOIN {comments} com ON com.itemid = ge.id AND com.commentarea = :commentarea AND com.userid = :commentuserid
             {$ratingquery->join}
                 WHERE c.id {$contextsql}
                   AND (ge.userid = :userid OR com.id IS NOT NULL OR {$ratingquery->userwhere})
               ORDER BY ge.id, cm.id";
        $params = [
                'userid' => $user->id,
                'modulename' => 'glossary',
                'contextlevel' => CONTEXT_MODULE,
                'commentarea' => 'glossary_entry',
                'commentuserid' => $user->id
            ] + $contextparams;
        $params = array_merge($params, $ratingquery->params);
        $glossaryentries = $DB->get_recordset_sql($sql, $params);

        // Reference to the glossary activity seen in the last iteration of the loop. By comparing this with the
        // current record, and because we know the results are ordered, we know when we've moved to the entries
        // for a new glossary activity and therefore when we can export the complete data for the last activity.
        $lastcmid = null;

        $glossarydata = [];
        foreach ($glossaryentries as $record) {
            $concept = format_string($record->concept);
            $path = array_merge([get_string('entries', 'mod_glossary'), $concept . " ({$record->entryid})"]);

            // If we've moved to a new glossary, then write the last glossary data and reinit the glossary data array.
            if (!is_null($lastcmid)) {
                if ($lastcmid != $record->cmid) {
                    if (!empty($glossarydata)) {
                        $context = \context_module::instance($lastcmid);
                        self::export_glossary_data_for_user($glossarydata, $context, [], $user);
                        $glossarydata = [];
                    }
                }
            }
            $lastcmid = $record->cmid;
            $context = \context_module::instance($lastcmid);

            // Export files added on the glossary entry definition field.
            $definition = format_text(writer::with_context($context)->rewrite_pluginfile_urls($path, 'mod_glossary',
                'entry',  $record->entryid, $record->definition), $record->definitionformat);

            // Export just the files attached to this user entry.
            if ($record->userid == $user->id) {
                // Get all files attached to the glossary attachment.
                writer::with_context($context)->export_area_files($path, 'mod_glossary', 'entry', $record->entryid);

                // Get all files attached to the glossary attachment.
                writer::with_context($context)->export_area_files($path, 'mod_glossary', 'attachment', $record->entryid);
            }

            // Export associated comments.
            \core_comment\privacy\provider::export_comments($context, 'mod_glossary', 'glossary_entry',
                    $record->entryid, $path, $record->userid != $user->id);

            // Export associated tags.
            \core_tag\privacy\provider::export_item_tags($user->id, $context, $path, 'mod_glossary', 'glossary_entries',
                    $record->entryid, $record->userid != $user->id);

            // Export associated ratings.
            \core_rating\privacy\provider::export_area_ratings($user->id, $context, $path, 'mod_glossary', 'entry',
                    $record->entryid, $record->userid != $user->id);

            $glossarydata['entries'][] = [
                'concept'       => $record->concept,
                'definition'    => $definition,
                'timecreated'   => \core_privacy\local\request\transform::datetime($record->timecreated),
                'timemodified'  => \core_privacy\local\request\transform::datetime($record->timemodified)
            ];
        }
        $glossaryentries->close();

        // The data for the last activity won't have been written yet, so make sure to write it now!
        if (!empty($glossarydata)) {
            $context = \context_module::instance($lastcmid);
            self::export_glossary_data_for_user($glossarydata, $context, [], $user);
        }
    }
1013733
public static function export_user_data(approved_contextlist $contextlist) {
        $contexts = $contextlist->get_contexts();
        foreach ($contexts as $context) {
            \core_comment\privacy\provider::export_comments(
                    $context,
                    'block_comments',
                    'page_comments',
                    0,
                    []
            );
        }
    }
402126
public static function delete_data_for_user(approved_contextlist $contextlist) {
        // If the user has data, then only the user context should be present so get the first context.
        $contexts = $contextlist->get_contexts();
        if (count($contexts) == 0) {
            return;
        }
        $context = reset($contexts);

        // Sanity check that context is at the user context level, then get the userid.
        if ($context->contextlevel !== CONTEXT_USER) {
            return;
        }
        $userid = $context->instanceid;
        // Delete all the userkeys.
        \core_userkey\privacy\provider::delete_userkeys('rss', $userid);
    }
765874
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

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

        $user = $contextlist->get_user();

        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);

        // Values of ep.receiver_email and ep.business are already normalised to lowercase characters by PayPal,
        // therefore there is no need to use LOWER() on them in the following query.
        $sql = "SELECT ep.*
                  FROM {enrol_paypal} ep
                  JOIN {enrol} e ON ep.instanceid = e.id
                  JOIN {context} ctx ON e.courseid = ctx.instanceid AND ctx.contextlevel = :contextcourse
                  JOIN {user} u ON u.id = ep.userid OR LOWER(u.email) = ep.receiver_email OR LOWER(u.email) = ep.business
                 WHERE ctx.id {$contextsql} AND u.id = :userid
              ORDER BY e.courseid";

        $params = [
            'contextcourse' => CONTEXT_COURSE,
            'userid'        => $user->id,
            'emailuserid'   => $user->id,
        ];
        $params += $contextparams;

        // Reference to the course seen in the last iteration of the loop. By comparing this with the current record, and
        // because we know the results are ordered, we know when we've moved to the PayPal transactions for a new course
        // and therefore when we can export the complete data for the last course.
        $lastcourseid = null;

        $strtransactions = get_string('transactions', 'enrol_paypal');
        $transactions = [];
        $paypalrecords = $DB->get_recordset_sql($sql, $params);
        foreach ($paypalrecords as $paypalrecord) {
            if ($lastcourseid != $paypalrecord->courseid) {
                if (!empty($transactions)) {
                    $coursecontext = \context_course::instance($paypalrecord->courseid);
                    writer::with_context($coursecontext)->export_data(
                            [$strtransactions],
                            (object) ['transactions' => $transactions]
                    );
                }
                $transactions = [];
            }

            $transaction = (object) [
                'receiver_id'         => $paypalrecord->receiver_id,
                'item_name'           => $paypalrecord->item_name,
                'userid'              => $paypalrecord->userid,
                'memo'                => $paypalrecord->memo,
                'tax'                 => $paypalrecord->tax,
                'option_name1'        => $paypalrecord->option_name1,
                'option_selection1_x' => $paypalrecord->option_selection1_x,
                'option_name2'        => $paypalrecord->option_name2,
                'option_selection2_x' => $paypalrecord->option_selection2_x,
                'payment_status'      => $paypalrecord->payment_status,
                'pending_reason'      => $paypalrecord->pending_reason,
                'reason_code'         => $paypalrecord->reason_code,
                'txn_id'              => $paypalrecord->txn_id,
                'parent_txn_id'       => $paypalrecord->parent_txn_id,
                'payment_type'        => $paypalrecord->payment_type,
                'timeupdated'         => \core_privacy\local\request\transform::datetime($paypalrecord->timeupdated),
            ];
            if ($paypalrecord->userid == $user->id) {
                $transaction->userid = $paypalrecord->userid;
            }
            if ($paypalrecord->business == \core_text::strtolower($user->email)) {
                $transaction->business = $paypalrecord->business;
            }
            if ($paypalrecord->receiver_email == \core_text::strtolower($user->email)) {
                $transaction->receiver_email = $paypalrecord->receiver_email;
            }

            $transactions[] = $paypalrecord;

            $lastcourseid = $paypalrecord->courseid;
        }
        $paypalrecords->close();

        // The data for the last activity won't have been written yet, so make sure to write it now!
        if (!empty($transactions)) {
            $coursecontext = \context_course::instance($paypalrecord->courseid);
            writer::with_context($coursecontext)->export_data(
                    [$strtransactions],
                    (object) ['transactions' => $transactions]
            );
        }
    }
66193
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

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

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

        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);

        // Export all notes written by and written about the user, and organize it by the associated Course context(s).
        $sql = "SELECT p.courseid as courseid,
                       p.content as content,
                       p.publishstate as publishstate,
                       p.userid as userid,
                       p.usermodified as usermodified,
                       p.created as datecreated,
                       p.lastmodified as datemodified
                  FROM {context} c
            INNER JOIN {post} p ON p.courseid = c.instanceid AND c.contextlevel = :contextcourse
                 WHERE p.module = 'notes'
                   AND (p.usermodified = :usermodified OR p.userid = :userid)
                   AND c.id {$contextsql}";

        $params = [
            'contextcourse' => CONTEXT_COURSE,
            'usermodified'  => $userid,
            'userid'        => $userid
        ];
        $params += $contextparams;

        $notes = $DB->get_recordset_sql($sql, $params);
        foreach ($notes as $note) {
            $contextcourse = \context_course::instance($note->courseid);

            // The exported notes will be organized in {Course Context}/Notes/{publishstate}/usernote-{userid}.json.
            $subcontext = [
                get_string('notes', 'notes'),
                $note->publishstate
            ];

            $name = 'usernote-' . transform::user($note->userid);

            $notecontent = (object) [
               'content' => $note->content,
               'publishstate' => $note->publishstate,
               'userid' => transform::user($note->userid),
               'usermodified' => transform::user($note->usermodified),
               'datecreated' => transform::datetime($note->datecreated),
               'datemodified' => transform::datetime($note->datemodified)
            ];

            writer::with_context($contextcourse)->export_related_data($subcontext, $name, $notecontent);
        }
        $notes->close();
    }
1117657
protected static function export_user_data_lti_types(approved_contextlist $contextlist) {
        global $DB;

        // Filter out any contexts that are not related to courses.
        $courseids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
            if ($context->contextlevel == CONTEXT_COURSE) {
                $carry[] = $context->instanceid;
            }
            return $carry;
        }, []);

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

        $user = $contextlist->get_user();

        list($insql, $inparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
        $params = array_merge($inparams, ['userid' => $user->id]);
        $ltitypes = $DB->get_recordset_select('lti_types', "course $insql AND createdby = :userid", $params, 'timecreated ASC');
        self::recordset_loop_and_export($ltitypes, 'course', [], function($carry, $record) {
            $context = \context_course::instance($record->course);
            $options = ['context' => $context];
            $carry[] = [
                'name' => format_string($record->name, true, $options),
                'createdby' => transform::user($record->createdby),
                'timecreated' => transform::datetime($record->timecreated),
                'timemodified' => transform::datetime($record->timemodified)
            ];
            return $carry;
        }, function($courseid, $data) {
            $context = \context_course::instance($courseid);
            $finaldata = (object) ['lti_types' => $data];
            writer::with_context($context)->export_data([], $finaldata);
        });
    }
246881
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

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

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

        // Get cohort data.
        $userid = $contextlist->get_user()->id;
        list($contextsql, $contextparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED);
        $sql = "SELECT c.name,
                       c.idnumber,
                       c.description,
                       c.visible,
                       cm.timeadded,
                       ctx.id as contextid
                  FROM {context} ctx
            INNER JOIN {cohort} c ON c.contextid = ctx.id
            INNER JOIN {cohort_members} cm ON cm.cohortid = c.id
                 WHERE ctx.id {$contextsql}
                       AND cm.userid = :userid";
        $params = [
                'userid'        => $userid
            ] + $contextparams;

        $cohorts = $DB->get_recordset_sql($sql, $params);
        foreach ($cohorts as $cohort) {
            $alldata[$cohort->contextid][] = (object)[
                    'name' => $cohort->name,
                    'idnumber' => $cohort->idnumber,
                    'visible' => transform::yesno($cohort->visible),
                    'timeadded' => transform::datetime($cohort->timeadded),
                ];
        }
        $cohorts->close();

        // Export cohort data.
        array_walk($alldata, function($data, $contextid) {
            $context = \context::instance_by_id($contextid);
            writer::with_context($context)->export_related_data([], 'cohort', $data);
        });

    }
1085779
public static function delete_data_for_user(approved_contextlist $contextlist) {
        global $DB;

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

        $userid = $contextlist->get_user()->id;
        foreach ($contextlist->get_contexts() as $context) {
            if (!$context instanceof \context_module) {
                continue;
            }
            $instanceid = $DB->get_field('course_modules', 'instance', ['id' => $context->instanceid], MUST_EXIST);
            $DB->delete_records('lti_submission', ['ltiid' => $instanceid, 'userid' => $userid]);
        }
    }
544950
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

        foreach ($contextlist as $context) {
            if ($context->contextlevel != CONTEXT_MODULE) {
                continue;
            }
            $user = $contextlist->get_user();

            $rs = $DB->get_recordset_sql('SELECT w.wikimode, s.id AS subwikiid,
                    s.groupid AS subwikigroupid, s.userid AS subwikiuserid,
                    p.id AS pageid, p.userid AS pageuserid, p.title, p.cachedcontent, p.timecreated AS pagetimecreated,
                    p.timemodified AS pagetimemodified, p.timerendered AS pagetimerendered, p.pageviews, p.readonly,
                    v.id AS versionid, v.content, v.contentformat, v.version, v.timecreated AS versiontimecreated,
                    l.id AS lockid, l.sectionname, l.lockedat
                FROM {course_modules} cm
                JOIN {wiki} w ON w.id = cm.instance
                JOIN {wiki_subwikis} s ON cm.instance = s.wikiid
                LEFT JOIN {wiki_pages} p ON p.subwikiid = s.id
                LEFT JOIN {wiki_versions} v ON v.pageid = p.id AND v.userid = :user4
                LEFT JOIN {wiki_locks} l ON l.pageid = p.id AND l.userid = :user5
                WHERE cm.id = :cmid AND (s.userid = :user1 OR p.userid = :user2 OR v.userid = :user3 OR l.userid = :user6 OR
                     EXISTS (SELECT 1 FROM {comments} com WHERE com.itemid = p.id AND com.commentarea = :commentarea
                          AND com.contextid = :ctxid AND com.userid = :user7)
                )
                ORDER BY s.id, p.id, v.id',
                ['cmid' => $context->instanceid,
                    'user1' => $user->id, 'user2' => $user->id, 'user3' => $user->id, 'user4' => $user->id,
                    'user5' => $user->id, 'user6' => $user->id, 'user7' => $user->id, 'commentarea' => 'wiki_page',
                    'ctxid' => $context->id]);

            if (!$rs->current()) {
                $rs->close();
                continue;
            }

            $subwiki = [];
            $wikimode = null;
            foreach ($rs as $record) {
                if ($wikimode === null) {
                    $wikimode = $record->wikimode;
                }
                if (!isset($subwiki[$record->subwikiid])) {
                    self::export_subwiki($user, $context, $subwiki, $wikimode);
                    $subwiki = [$record->subwikiid => [
                        'groupid' => $record->subwikigroupid,
                        'userid' => $record->subwikiuserid ? transform::user($record->subwikiuserid) : 0,
                        'pages' => []
                    ]];
                }

                if (!$record->pageid) {
                    // This is an empty individual wiki.
                    continue;
                }

                // Prepend page title with the page id to guarantee uniqueness.
                $pagetitle = format_string($record->title, true, ['context' => $context]);
                $page = $record->pageid . ' ' . $pagetitle;
                if (!isset($subwiki[$record->subwikiid]['pages'][$page])) {
                    // Export basic details about the page.
                    $subwiki[$record->subwikiid]['pages'][$page] = ['page' => [
                        'id' => $record->pageid,
                        'title' => $pagetitle,
                        'cachedcontent' => $record->cachedcontent,
                    ]];
                    if ($record->pageuserid == $user->id) {
                        // This page belongs to this user. Export all details.
                        $subwiki[$record->subwikiid]['pages'][$page]['page'] += [
                            'userid' => transform::user($user->id),
                            'timecreated' => transform::datetime($record->pagetimecreated),
                            'timemodified' => transform::datetime($record->pagetimemodified),
                            'timerendered' => transform::datetime($record->pagetimerendered),
                            'pageviews' => $record->pageviews,
                            'readonly' => $record->readonly,
                        ];

                        $subwiki[$record->subwikiid]['pages'][$page]['page']['userid'] = transform::user($user->id);
                    }
                }

                if ($record->versionid) {
                    $subwiki[$record->subwikiid]['pages'][$page]['revisions'][$record->versionid] = [
                        'content' => $record->content,
                        'contentformat' => $record->contentformat,
                        'version' => $record->version,
                        'timecreated' => transform::datetime($record->versiontimecreated)
                    ];
                }

                if ($record->lockid) {
                    $subwiki[$record->subwikiid]['pages'][$page]['locks'][$record->lockid] = [
                        'sectionname' => $record->sectionname,
                        'lockedat' => transform::datetime($record->lockedat),
                    ];
                }

            }
            self::export_subwiki($user, $context, $subwiki, $wikimode);

            if ($subwiki) {
                // Export wiki itself.
                $contextdata = helper::get_context_data($context, $user);
                helper::export_context_files($context, $user);
                writer::with_context($context)->export_data([], $contextdata);
            }

            $rs->close();
        }
    }
1111698
public static function delete_data_for_user(approved_contextlist $contextlist) {
        global $DB;

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

        $userid = $contextlist->get_user()->id;
        foreach ($contextlist->get_contexts() as $context) {
            if ($context instanceof \context_course) {
                $select = "itemid = :itemid AND userid = :userid AND type = :type";
                $params = [
                    'userid' => $userid,
                    'itemid' => $context->instanceid,
                    'type' => \backup::TYPE_1COURSE
                ];

                $DB->delete_records_select('backup_controllers', $select, $params);

                $params = [
                    'userid' => $userid,
                    'course' => $context->instanceid,
                    'type' => \backup::TYPE_1SECTION
                ];
                $sectionsql = "itemid IN (SELECT id FROM {course_sections} WHERE course = :course)";
                $select = $sectionsql . " AND userid = :userid AND type = :type";
                $DB->delete_records_select('backup_controllers', $select, $params);
            }
            if ($context instanceof \context_module) {
                list($usersql, $userparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);
                $select = "itemid = :itemid AND userid = :userid AND type = :type";
                $params = [
                    'itemid' => $context->instanceid,
                    'userid' => $userid,
                    'type' => \backup::TYPE_1ACTIVITY
                ];

                $DB->delete_records_select('backup_controllers', $select, $params);
            }

        }
    }
760972
protected static function export_user_calendar_subscription_data(approved_contextlist $contextlist) {
        // Calendar Subscriptions can exist at Site, Course Category, Course, Course Group, or User contexts.
        $subscriptiondetails = self::get_calendar_subscription_details_by_contextlist($contextlist);

        // Multiple Calendar Subscriptions of the same eventtype can exist for a context, so collate them for export.
        $subscriptionrecords = [];
        foreach ($subscriptiondetails as $subscriptiondetail) {
            // Create an array key based on the contextid and eventtype.
            $key = $subscriptiondetail->contextid . $subscriptiondetail->eventtype;

            if (array_key_exists($key, $subscriptionrecords) === false) {
                $subscriptionrecords[$key] = [ $subscriptiondetail ];
            } else {
                $subscriptionrecords[$key] = array_merge($subscriptionrecords[$key], [$subscriptiondetail]);
            }
        }
        $subscriptiondetails->close();

        // Export Calendar Subscription data.
        foreach ($subscriptionrecords as $subscriptionrecord) {
            $index = (count($subscriptionrecord) > 1) ? 1 : 0;

            foreach ($subscriptionrecord as $subscription) {
                // Export the events using the structure Calendar/Subscriptions/{eventtype}-subscription.json.
                $subcontexts = [
                    get_string('calendar', 'calendar'),
                    get_string('subscriptions', 'calendar')
                ];
                $name = $subscription->eventtype . '-subscription';

                // Use name {eventtype}-subscription-{index}.json if multiple eventtypes exists at the same context.
                if ($index != 0) {
                    $name .= '-' . $index;
                    $index++;
                }

                $context = \context::instance_by_id($subscription->contextid);
                writer::with_context($context)->export_related_data($subcontexts, $name, $subscription);
            }
        }
    }
1362479
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

        // If the user has data, then only the User context should be present so get the first context.
        $contexts = $contextlist->get_contexts();
        if (count($contexts) == 0) {
            return;
        }
        $context = reset($contexts);

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

        $sql = "SELECT roa.id as id,
                       roa.itemid as itemid,
                       roa.permissionid as permissionid,
                       roa.timecreated as timecreated,
                       roa.timemodified as timemodified
                  FROM {repository_onedrive_access} roa
                 WHERE roa.usermodified = :userid";

        $params = [
            'userid' => $userid
        ];

        $onedriveaccesses = $DB->get_records_sql($sql, $params);
        $index = 0;
        foreach ($onedriveaccesses as $onedriveaccess) {
            // Data export is organised in: {User Context}/Repository plug-ins/{Plugin Name}/Access/{index}/data.json.
            $index++;
            $subcontext = [
                get_string('plugin', 'core_repository'),
                get_string('pluginname', 'repository_onedrive'),
                get_string('access', 'repository_onedrive'),
                $index
            ];

            $data = (object) [
                'itemid' => $onedriveaccess->itemid,
                'permissionid' => $onedriveaccess->permissionid,
                'timecreated' => transform::datetime($onedriveaccess->timecreated),
                'timemodified' => transform::datetime($onedriveaccess->timemodified)
            ];

            writer::with_context($context)->export_data($subcontext, $data);
        }

    }
418589
public static function delete_data_for_user(approved_contextlist $contextlist) {
        foreach ($contextlist as $context) {
            // Let's be super certain that we have the right information for this user here.
            if ($context->contextlevel == CONTEXT_USER && $contextlist->get_user()->id == $context->instanceid) {
                static::delete_user_data($contextlist->get_user()->id, $contextlist->current());
            }
        }
    }