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

@param approved_contextlist $contextlist The approved contexts to export information for.
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();
        }
    }
256956
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;
        $userid = $contextlist->get_user()->id;

        // Extract the block instance IDs.
        $instanceids = array_reduce($contextlist->get_contexts(), function($carry, $context) {
            if ($context->contextlevel == CONTEXT_BLOCK) {
                $carry[] = $context->instanceid;
            }
            return $carry;
        }, []);
        if (empty($instanceids)) {
            return;
        }

        // Query the blocks and their preferences.
        list($insql, $inparams) = $DB->get_in_or_equal($instanceids, SQL_PARAMS_NAMED);
        $hiddenkey = $DB->sql_concat("'block'", 'bi.id', "'hidden'");
        $dockedkey = $DB->sql_concat("'docked_block_instance_'", 'bi.id');
        $sql = "
            SELECT bi.id, h.value AS prefhidden, d.value AS prefdocked
              FROM {block_instances} bi
         LEFT JOIN {user_preferences} h
                ON h.userid = :userid1
               AND h.name = $hiddenkey
         LEFT JOIN {user_preferences} d
                ON d.userid = :userid2
               AND d.name = $dockedkey
             WHERE bi.id $insql
               AND (h.id IS NOT NULL
                OR d.id IS NOT NULL)";
        $params = array_merge($inparams, [
            'userid1' => $userid,
            'userid2' => $userid,
        ]);

        // Export all the things.
        $dockedstr = get_string('privacy:request:blockisdocked', 'core_block');
        $hiddenstr = get_string('privacy:request:blockishidden', 'core_block');
        $recordset = $DB->get_recordset_sql($sql, $params);
        foreach ($recordset as $record) {
            $context = context_block::instance($record->id);
            if ($record->prefdocked !== null) {
                writer::with_context($context)->export_user_preference(
                    'core_block',
                    'block_is_docked',
                    transform::yesno($record->prefdocked),
                    $dockedstr
                );
            }
            if ($record->prefhidden !== null) {
                writer::with_context($context)->export_user_preference(
                    'core_block',
                    'block_is_hidden',
                    transform::yesno($record->prefhidden),
                    $hiddenstr
                );
            }
        }
        $recordset->close();
    }
796723
protected static function export_submissions(approved_contextlist $contextlist) {
        global $DB;

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

        $sql = "SELECT ws.id, ws.authorid, ws.example, ws.timecreated, ws.timemodified, ws.title,
                       ws.content, ws.contentformat, ws.grade, ws.gradeover, ws.feedbackauthor, ws.feedbackauthorformat,
                       ws.published, ws.late,
                       w.phase, w.course, cm.id AS cmid, ".\context_helper::get_preload_record_columns_sql('ctx')."
                  FROM {course_modules} cm
                  JOIN {modules} m ON cm.module = m.id AND m.name = :module
                  JOIN {context} ctx ON ctx.contextlevel = :contextlevel AND ctx.instanceid = cm.id
                  JOIN {workshop} w ON cm.instance = w.id
                  JOIN {workshop_submissions} ws ON ws.workshopid = w.id AND ws.authorid = :authorid
                 WHERE ctx.id {$contextsql}";

        $params = $contextparams + [
            'module' => 'workshop',
            'contextlevel' => CONTEXT_MODULE,
            'authorid' => $user->id,
        ];

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

        foreach ($rs as $record) {
            \context_helper::preload_from_record($record);
            $context = \context_module::instance($record->cmid);
            $writer = \core_privacy\local\request\writer::with_context($context);

            if ($record->example) {
                $subcontext = [get_string('examplesubmissions', 'mod_workshop'), $record->id];
                $mysubmission = null;
            } else {
                $subcontext = [get_string('mysubmission', 'mod_workshop')];
                $mysubmission = $record;
            }

            $phase = $record->phase;
            $courseid = $record->course;

            $data = (object) [
                'example' => transform::yesno($record->example),
                'timecreated' => transform::datetime($record->timecreated),
                'timemodified' => $record->timemodified ? transform::datetime($record->timemodified) : null,
                'title' => $record->title,
                'content' => $writer->rewrite_pluginfile_urls($subcontext, 'mod_workshop',
                    'submission_content', $record->id, $record->content),
                'contentformat' => $record->contentformat,
                'grade' => $record->grade,
                'gradeover' => $record->gradeover,
                'feedbackauthor' => $record->feedbackauthor,
                'feedbackauthorformat' => $record->feedbackauthorformat,
                'published' => transform::yesno($record->published),
                'late' => transform::yesno($record->late),
            ];

            $writer->export_data($subcontext, $data);
            $writer->export_area_files($subcontext, 'mod_workshop', 'submission_content', $record->id);
            $writer->export_area_files($subcontext, 'mod_workshop', 'submission_attachment', $record->id);

            // Export peer-assessments of my submission if the workshop was closed. We do not export received
            // assessments from peers before they were actually effective. Before the workshop is closed, grades are not
            // pushed into the gradebook. So peer assessments did not affect evaluation of the user's performance and
            // they should not be considered as their personal data. This is different from assessments given by the
            // user that are always exported.
            if ($mysubmission && $phase == \workshop::PHASE_CLOSED) {
                $assessments = $DB->get_records('workshop_assessments', ['submissionid' => $mysubmission->id], '',
                    'id, reviewerid, weight, timecreated, timemodified, grade, feedbackauthor, feedbackauthorformat');

                foreach ($assessments as $assessment) {
                    $assid = $assessment->id;
                    $assessment->selfassessment = transform::yesno($assessment->reviewerid == $user->id);
                    $assessment->timecreated = transform::datetime($assessment->timecreated);
                    $assessment->timemodified = $assessment->timemodified ? transform::datetime($assessment->timemodified) : null;
                    $assessment->feedbackauthor = $writer->rewrite_pluginfile_urls($subcontext,
                        'mod_workshop', 'overallfeedback_content', $assid, $assessment->feedbackauthor);

                    $assessmentsubcontext = array_merge($subcontext, [get_string('assessments', 'mod_workshop'), $assid]);

                    unset($assessment->id);
                    unset($assessment->reviewerid);

                    $writer->export_data($assessmentsubcontext, $assessment);
                    $writer->export_area_files($assessmentsubcontext, 'mod_workshop', 'overallfeedback_content', $assid);
                    $writer->export_area_files($assessmentsubcontext, 'mod_workshop', 'overallfeedback_attachment', $assid);

                    // Export details of how the assessment forms were filled.
                    static::export_assessment_forms($user, $context, $assessmentsubcontext, $assid);
                }
            }

            // Export plagiarism data related to the submission content.
            // The last $linkarray argument consistent with how we call {@link plagiarism_get_links()} in the renderer.
            \core_plagiarism\privacy\provider::export_plagiarism_user_data($user->id, $context, $subcontext, [
                'userid' => $user->id,
                'content' => format_text($data->content, $data->contentformat, ['overflowdiv' => true]),
                'cmid' => $context->instanceid,
                'course' => $courseid,
            ]);
        }

        $rs->close();
    }
593004
public static function delete_data_for_user(approved_contextlist $contextlist) {
        global $DB;
        $userid = $contextlist->get_user()->id;

        // Ensure that we only act on module contexts.
        $contextids = array_map(function($context) {
            return $context->instanceid;
        }, array_filter($contextlist->get_contexts(), function($context) {
            return $context->contextlevel == CONTEXT_MODULE;
        }));

        // Prepare SQL to gather all completed IDs.
        list($insql, $inparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED);
        $completedsql = "
            SELECT fc.id
              FROM {%s} fc
              JOIN {modules} m
                ON m.name = :feedback
              JOIN {course_modules} cm
                ON cm.instance = fc.feedback
               AND cm.module = m.id
             WHERE fc.userid = :userid
               AND cm.id $insql";
        $completedparams = array_merge($inparams, ['userid' => $userid, 'feedback' => 'feedback']);

        // Delete all submissions in progress.
        $completedtmpids = $DB->get_fieldset_sql(sprintf($completedsql, 'feedback_completedtmp'), $completedparams);
        if (!empty($completedtmpids)) {
            list($insql, $inparams) = $DB->get_in_or_equal($completedtmpids, SQL_PARAMS_NAMED);
            $DB->delete_records_select('feedback_valuetmp', "completed $insql", $inparams);
            $DB->delete_records_select('feedback_completedtmp', "id $insql", $inparams);
        }

        // Delete all final submissions.
        $completedids = $DB->get_fieldset_sql(sprintf($completedsql, 'feedback_completed'), $completedparams);
        if (!empty($completedids)) {
            list($insql, $inparams) = $DB->get_in_or_equal($completedids, SQL_PARAMS_NAMED);
            $DB->delete_records_select('feedback_value', "completed $insql", $inparams);
            $DB->delete_records_select('feedback_completed', "id $insql", $inparams);
        }
    }
739170
public static function delete_data_for_user(approved_contextlist $contextlist) {
        global $DB;
        $userid = $contextlist->get_user()->id;
        $prefnames = array_reduce($contextlist->get_contexts(), function($carry, $context) {
            if ($context->contextlevel == CONTEXT_BLOCK) {
                $carry[] = "block{$context->instanceid}hidden";
                $carry[] = "docked_block_instance_{$context->instanceid}";
            }
            return $carry;
        }, []);

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

        list($insql, $inparams) = $DB->get_in_or_equal($prefnames, SQL_PARAMS_NAMED);
        $sql = "userid = :userid AND name $insql";
        $params = array_merge($inparams, ['userid' => $userid]);
        $DB->delete_records_select('user_preferences', $sql, $params);
    }
758082
public static function export_user_data(approved_contextlist $contextlist) {
        $user = $contextlist->get_user();
        $userid = $user->id;

        // Re-arrange the contexts by context level.
        $groupedcontexts = array_reduce($contextlist->get_contexts(), function($carry, $context) {
            $contextlevel = $context->contextlevel;
            if (!in_array($contextlevel, [CONTEXT_USER, CONTEXT_COURSE, CONTEXT_MODULE, CONTEXT_SYSTEM, CONTEXT_COURSECAT])) {
                return $carry;
            }
            $carry[$contextlevel][] = $context;
            return $carry;
        }, [
            CONTEXT_COURSE => [],
            CONTEXT_COURSECAT => [],
            CONTEXT_MODULE => [],
            CONTEXT_SYSTEM => [],
            CONTEXT_USER => [],
        ]);

        // Process module contexts.
        static::export_user_data_in_module_contexts($userid, $groupedcontexts[CONTEXT_MODULE]);

        // Process course contexts.
        static::export_user_data_in_course_contexts($userid, $groupedcontexts[CONTEXT_COURSE]);

        // Process course categories context.
        static::export_user_data_in_category_contexts($userid, $groupedcontexts[CONTEXT_COURSECAT]);

        // Process system context.
        if (!empty($groupedcontexts[CONTEXT_SYSTEM])) {
            static::export_user_data_in_system_context($userid);
        }

        // Process user contexts.
        static::export_user_data_in_user_contexts($userid, $groupedcontexts[CONTEXT_USER]);
    }
88427
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

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

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

        $sql = "SELECT
                    q.*,
                    qg.id AS hasgrade,
                    qg.grade AS bestgrade,
                    qg.timemodified AS grademodified,
                    qo.id AS hasoverride,
                    qo.timeopen AS override_timeopen,
                    qo.timeclose AS override_timeclose,
                    qo.timelimit AS override_timelimit,
                    c.id AS contextid,
                    cm.id AS cmid
                  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 {quiz} q ON q.id = cm.instance
             LEFT JOIN {quiz_overrides} qo ON qo.quiz = q.id AND qo.userid = :qouserid
             LEFT JOIN {quiz_grades} qg ON qg.quiz = q.id AND qg.userid = :qguserid
                 WHERE c.id {$contextsql}";

        $params = [
            'contextlevel'      => CONTEXT_MODULE,
            'modname'           => 'quiz',
            'qguserid'          => $userid,
            'qouserid'          => $userid,
        ];
        $params += $contextparams;

        // Fetch the individual quizzes.
        $quizzes = $DB->get_recordset_sql($sql, $params);
        foreach ($quizzes as $quiz) {
            list($course, $cm) = get_course_and_cm_from_cmid($quiz->cmid, 'quiz');
            $quizobj = new \quiz($quiz, $cm, $course);
            $context = $quizobj->get_context();

            $quizdata = \core_privacy\local\request\helper::get_context_data($context, $contextlist->get_user());
            \core_privacy\local\request\helper::export_context_files($context, $contextlist->get_user());

            if (!empty($quizdata->timeopen)) {
                $quizdata->timeopen = transform::datetime($quiz->timeopen);
            }
            if (!empty($quizdata->timeclose)) {
                $quizdata->timeclose = transform::datetime($quiz->timeclose);
            }
            if (!empty($quizdata->timelimit)) {
                $quizdata->timelimit = $quiz->timelimit;
            }

            if (!empty($quiz->hasoverride)) {
                $quizdata->override = (object) [];

                if (!empty($quizdata->override_override_timeopen)) {
                    $quizdata->override->timeopen = transform::datetime($quiz->override_timeopen);
                }
                if (!empty($quizdata->override_timeclose)) {
                    $quizdata->override->timeclose = transform::datetime($quiz->override_timeclose);
                }
                if (!empty($quizdata->override_timelimit)) {
                    $quizdata->override->timelimit = $quiz->override_timelimit;
                }
            }

            $quizdata->accessdata = (object) [];

            $components = \core_component::get_plugin_list('quizaccess');
            $exportparams = [
                    $quizobj,
                    $user,
                ];
            foreach (array_keys($components) as $component) {
                $classname = manager::get_provider_classname_for_component("quizaccess_$component");
                if (class_exists($classname) && is_subclass_of($classname, quizaccess_provider::class)) {
                    $result = component_class_callback($classname, 'export_quizaccess_user_data', $exportparams);
                    if (count((array) $result)) {
                        $quizdata->accessdata->$component = $result;
                    }
                }
            }

            if (empty((array) $quizdata->accessdata)) {
                unset($quizdata->accessdata);
            }

            writer::with_context($context)
                ->export_data([], $quizdata);
        }
        $quizzes->close();

        // Store all quiz attempt data.
        static::export_quiz_attempts($contextlist);
    }
813435
public static function export_user_data(approved_contextlist $contextlist) {
        $context = $contextlist->current();
        $user = \core_user::get_user($contextlist->get_user()->id);
        static::export_recentitems($user->id, $context);
    }
637449
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;

        // Some sneeky person might have sent us the wrong context list. We should check.
        if ($contextlist->get_component() != 'report_stats') {
            return;
        }

        // Got to check that someone hasn't foolishly added a context between creating the context list and then filtering down
        // to an approved context.
        $contexts = array_filter($contextlist->get_contexts(), function($context) {
            if ($context->contextlevel == CONTEXT_COURSE) {
                return $context;
            }
        });

        $tables = [
            'stats_user_daily' => get_string('privacy:dailypath', 'report_stats'),
            'stats_user_weekly' => get_string('privacy:weeklypath', 'report_stats'),
            'stats_user_monthly' => get_string('privacy:monthlypath', 'report_stats')
        ];

        $courseids = array_map(function($context) {
            return $context->instanceid;
        }, $contexts);

        foreach ($tables as $table => $path) {

            list($insql, $params) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
            $sql = "SELECT s.id, c.fullname, s.roleid, s.timeend, s.statsreads, s.statswrites, s.stattype, c.id as courseid
                      FROM {" . $table . "} s
                      JOIN {course} c ON s.courseid = c.id
                     WHERE s.userid = :userid AND c.id $insql
                     ORDER BY c.id ASC";
            $params['userid'] = $contextlist->get_user()->id;
            $records = $DB->get_records_sql($sql, $params);

            $statsrecords = [];
            foreach ($records as $record) {
                $context = \context_course::instance($record->courseid);
                if (!isset($statsrecords[$record->courseid])) {
                    $statsrecords[$record->courseid] = new \stdClass();
                    $statsrecords[$record->courseid]->context = $context;
                }
                $statsrecords[$record->courseid]->entries[] = [
                    'course' => format_string($record->fullname, true, ['context' => $context]),
                    'roleid' => $record->roleid,
                    'timeend' => \core_privacy\local\request\transform::datetime($record->timeend),
                    'statsreads' => $record->statsreads,
                    'statswrites' => $record->statswrites,
                    'stattype' => $record->stattype
                ];
            }
            foreach ($statsrecords as $coursestats) {
                \core_privacy\local\request\writer::with_context($coursestats->context)->export_data([$path],
                        (object) $coursestats->entries);
            }
        }
    }
754781
public static function export_user_data(approved_contextlist $contextlist) {
        if (empty($contextlist)) {
            return;
        }

        self::export_user_calendar_event_data($contextlist);
        self::export_user_calendar_subscription_data($contextlist);
    }
483510
public static function export_user_data(approved_contextlist $contextlist) {
        global $DB;
        if (empty($contextlist->count())) {
            return;
        }
        $userid = $contextlist->get_user()->id;
        $contextuser = \context_user::instance($userid);
        list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
        $params = [
            'userid' => $userid,
            'contextlevel' => CONTEXT_USER
         ];
        $params += $inparams;
        $sql = "SELECT me.id,
                       me.rolename,
                       me.enroltime,
                       me.enroltype,
                       mh.name as hostname,
                       mc.fullname
                  FROM {mnetservice_enrol_enrolments} me
                  JOIN {context} ctx
                    ON ctx.instanceid = me.userid
                   AND ctx.contextlevel = :contextlevel
                  JOIN {mnet_host} mh
                    ON mh.id = me.hostid
                  JOIN {mnetservice_enrol_courses} mc
                    ON mc.remoteid = me.remotecourseid
                 WHERE me.userid = :userid
                   AND ctx.id {$insql}";
        $mnetenrolments = $DB->get_records_sql($sql, $params);
        foreach ($mnetenrolments as $mnetenrolment) {
            // The core_enrol data export is organised in:
            // {User Context}/User enrolments/data.json.
            $data[] = (object) [
                'host' => $mnetenrolment->hostname,
                'remotecourseid' => $mnetenrolment->fullname,
                'rolename' => $mnetenrolment->rolename,
                'enroltime' => transform::datetime($mnetenrolment->enroltime),
                'enroltype' => $mnetenrolment->enroltype
            ];
        }
        writer::with_context($contextuser)->export_data(
                [get_string('privacy:metadata:mnetservice_enrol_enrolments', 'mnetservice_enrol')],
                (object)$data
            );
    }
155561
public static function delete_data_for_user(approved_contextlist $contextlist) {
        global $DB;

        // Questions are considered to be 'owned' by the institution, even if they were originally written by a specific
        // user. They are still exported in the list of a users data, but they are not removed.
        // The userid is instead anonymised.

        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
        $contextparams['createdby'] = $contextlist->get_user()->id;
        $DB->set_field_select('question', 'createdby', 0, "
                category IN (SELECT id FROM {question_categories} WHERE contextid {$contextsql})
            AND createdby = :createdby", $contextparams);

        list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
        $contextparams['modifiedby'] = $contextlist->get_user()->id;
        $DB->set_field_select('question', 'modifiedby', 0, "
                category IN (SELECT id FROM {question_categories} WHERE contextid {$contextsql})
            AND modifiedby = :modifiedby", $contextparams);
    }
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);
        }
    }
1242757
public static function export_user_data(approved_contextlist $contextlist) {
        if (empty($contextlist->count())) {
            return;
        }

        $user = $contextlist->get_user();
        $datarequests = api::get_data_requests($user->id);
        $context = context_user::instance($user->id);
        $contextdatatowrite = [];
        foreach ($datarequests as $request) {
            $record = $request->to_record();
            $data = new stdClass();

            // The user ID that made the request/the request is made for.
            if ($record->requestedby != $record->userid) {
                if ($user->id != $record->requestedby) {
                    // This request is done by this user for another user.
                    $data->userid = fullname($user);
                } else if ($user->id != $record->userid) {
                    // This request was done by another user on behalf of this user.
                    $data->requestedby = fullname($user);
                }
            }

            // Request type.
            $data->type = tool_helper::get_shortened_request_type_string($record->type);
            // Status.
            $data->status = tool_helper::get_request_status_string($record->status);
            // Creation method.
            $data->creationmethod = tool_helper::get_request_creation_method_string($record->creationmethod);
            // Comments.
            $data->comments = $record->comments;
            // The DPO's comment about this request.
            $data->dpocomment = $record->dpocomment;
            // The date and time this request was lodged.
            $data->timecreated = transform::datetime($record->timecreated);
            $contextdatatowrite[] = $data;
        }

        // User context / Privacy and policies / Data requests.
        $subcontext = [
            get_string('privacyandpolicies', 'admin'),
            get_string('datarequests', 'tool_dataprivacy'),
        ];
        writer::with_context($context)->export_data($subcontext, (object)$contextdatatowrite);

        // Write generic module intro files.
        helper::export_context_files($context, $user);
    }
597097
public static function export_user_data(approved_contextlist $contextlist) {
        foreach ($contextlist->get_contexts() as $context) {
            // Check that the context is a module context.
            if ($context->contextlevel != CONTEXT_MODULE) {
                continue;
            }
            $user = $contextlist->get_user();
            $assigndata = helper::get_context_data($context, $user);
            helper::export_context_files($context, $user);

            writer::with_context($context)->export_data([], $assigndata);
            $assign = new \assign($context, null, null);

            // I need to find out if I'm a student or a teacher.
            if ($userids = self::get_graded_users($user->id, $assign)) {
                // Return teacher info.
                $currentpath = [get_string('privacy:studentpath', 'mod_assign')];
                foreach ($userids as $studentuserid) {
                    $studentpath = array_merge($currentpath, [$studentuserid->id]);
                    static::export_submission($assign, $studentuserid, $context, $studentpath, true);
                }
            }

            static::export_overrides($context, $assign, $user);
            static::export_submission($assign, $user, $context, []);
            // Meta data.
            self::store_assign_user_flags($context, $assign, $user->id);
            if ($assign->is_blind_marking()) {
                $uniqueid = $assign->get_uniqueid_for_user_static($assign->get_instance()->id, $contextlist->get_user()->id);
                if ($uniqueid) {
                    writer::with_context($context)
                            ->export_metadata([get_string('blindmarking', 'mod_assign')], 'blindmarkingid', $uniqueid,
                                    get_string('privacy:blindmarkingidentifier', 'mod_assign'));
                }
            }
        }
    }
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());
            }
        }
    }
1274022
public static function export_user_data(approved_contextlist $contextlist) {
        if (empty($contextlist)) {
            return;
        }
        foreach ($contextlist as $context) {
            if ($context->contextlevel == CONTEXT_COURSE) {
                \core_group\privacy\provider::export_groups(
                    $context,
                    'enrol_meta',
                    [get_string('pluginname', 'enrol_meta')]
                );
            }
        }
    }