���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home3/cpr76684/public_html/provider.php.tar
���ѧ٧ѧ�
home3/cpr76684/public_html/Aem/question/classes/privacy/provider.php 0000644 00000067536 15151252324 0021333 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Privacy Subsystem implementation for core_question. * * @package core_question * @category privacy * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_question\privacy; use core_privacy\local\metadata\collection; use core_privacy\local\request\approved_contextlist; use core_privacy\local\request\approved_userlist; use core_privacy\local\request\contextlist; use core_privacy\local\request\transform; use core_privacy\local\request\userlist; use core_privacy\local\request\writer; defined('MOODLE_INTERNAL') || die(); require_once($CFG->libdir . '/questionlib.php'); require_once($CFG->dirroot . '/question/format.php'); require_once($CFG->dirroot . '/question/editlib.php'); require_once($CFG->dirroot . '/question/engine/datalib.php'); /** * Privacy Subsystem implementation for core_question. * * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements // This component has data. // We need to return all question information where the user is // listed in either the question.createdby or question.modifiedby fields. // We may also need to fetch this informtion from individual plugins in some cases. // e.g. to fetch the full and other question-specific meta-data. \core_privacy\local\metadata\provider, // This is a subsysytem which provides information to core. \core_privacy\local\request\subsystem\provider, // This is a subsysytem which provides information to plugins. \core_privacy\local\request\subsystem\plugin_provider, // This plugin is capable of determining which users have data within it. \core_privacy\local\request\core_userlist_provider, // This plugin is capable of determining which users have data within it for the plugins it provides data to. \core_privacy\local\request\shared_userlist_provider { /** * Describe the types of data stored by the question subsystem. * * @param collection $items The collection to add metadata to. * @return collection The array of metadata */ public static function get_metadata(collection $items) : collection { // Other tables link against it. // The 'question_usages' table does not contain any user data. // The table links the but doesn't store itself. // The 'question_attempts' table contains data about question attempts. // It does not contain any user ids - these are stored by the caller. $items->add_database_table('question_attempts', [ 'flagged' => 'privacy:metadata:database:question_attempts:flagged', 'responsesummary' => 'privacy:metadata:database:question_attempts:responsesummary', 'timemodified' => 'privacy:metadata:database:question_attempts:timemodified', ], 'privacy:metadata:database:question_attempts');; // The 'question_attempt_steps' table contains data about changes to the state of a question attempt. $items->add_database_table('question_attempt_steps', [ 'state' => 'privacy:metadata:database:question_attempt_steps:state', 'timecreated' => 'privacy:metadata:database:question_attempt_steps:timecreated', 'fraction' => 'privacy:metadata:database:question_attempt_steps:fraction', 'userid' => 'privacy:metadata:database:question_attempt_steps:userid', ], 'privacy:metadata:database:question_attempt_steps'); // The 'question_attempt_step_data' table contains specific all metadata for each state. $items->add_database_table('question_attempt_step_data', [ 'name' => 'privacy:metadata:database:question_attempt_step_data:name', 'value' => 'privacy:metadata:database:question_attempt_step_data:value', ], 'privacy:metadata:database:question_attempt_step_data'); // These are all part of the set of the question definition // The 'question' table is used to store instances of each question. // It contains a createdby and modifiedby which related to specific users. $items->add_database_table('question', [ 'name' => 'privacy:metadata:database:question:name', 'questiontext' => 'privacy:metadata:database:question:questiontext', 'generalfeedback' => 'privacy:metadata:database:question:generalfeedback', 'timecreated' => 'privacy:metadata:database:question:timecreated', 'timemodified' => 'privacy:metadata:database:question:timemodified', 'createdby' => 'privacy:metadata:database:question:createdby', 'modifiedby' => 'privacy:metadata:database:question:modifiedby', ], 'privacy:metadata:database:question'); // The 'question_answers' table is used to store the set of answers, with appropriate feedback for each question. // It does not contain user data. // The 'question_hints' table is used to store hints about the correct answer for a question. // It does not contain user data. // The 'question_categories' table contains structural information about how questions are presented in the UI. // It does not contain user data. // The 'question_statistics' table contains aggregated statistics about responses. // It does not contain any identifiable user data. $items->add_database_table('question_bank_entries', [ 'ownerid' => 'privacy:metadata:database:question_bank_entries:ownerid', ], 'privacy:metadata:database:question_bank_entries'); // The question subsystem makes use of the qtype, qformat, and qbehaviour plugin types. $items->add_plugintype_link('qtype', [], 'privacy:metadata:link:qtype'); $items->add_plugintype_link('qformat', [], 'privacy:metadata:link:qformat'); $items->add_plugintype_link('qbehaviour', [], 'privacy:metadata:link:qbehaviour'); return $items; } /** * Export the data for all question attempts on this question usage. * * Where a user is the owner of the usage, then the full detail of that usage will be included. * Where a user has been involved in the usage, but it is not their own usage, then only their specific * involvement will be exported. * * @param int $userid The userid to export. * @param \context $context The context that the question was used within. * @param array $usagecontext The subcontext of this usage. * @param int $usage The question usage ID. * @param \question_display_options $options The display options used for formatting. * @param bool $isowner Whether the user being exported is the user who used the question. */ public static function export_question_usage( int $userid, \context $context, array $usagecontext, int $usage, \question_display_options $options, bool $isowner ) { // Determine the questions in this usage. $quba = \question_engine::load_questions_usage_by_activity($usage); $basepath = $usagecontext; $questionscontext = array_merge($usagecontext, [ get_string('questions', 'core_question'), ]); foreach ($quba->get_attempt_iterator() as $qa) { $question = $qa->get_question(false); $slotno = $qa->get_slot(); $questionnocontext = array_merge($questionscontext, [$slotno]); if ($isowner) { // This user is the overal owner of the question attempt and all data wil therefore be exported. // // Respect _some_ of the question_display_options to ensure that they don't have access to // generalfeedback and mark if the display options prevent this. // This is defensible because they can submit questions without completing a quiz and perform an SAR to // get prior access to the feedback and mark to improve upon it. // Export the response. $data = (object) [ 'name' => $question->name, 'question' => $qa->get_question_summary(), 'answer' => $qa->get_response_summary(), 'timemodified' => transform::datetime($qa->timemodified), ]; if ($options->marks >= \question_display_options::MARK_AND_MAX) { $data->mark = $qa->format_mark($options->markdp); } if ($options->flags != \question_display_options::HIDDEN) { $data->flagged = transform::yesno($qa->is_flagged()); } if ($options->generalfeedback != \question_display_options::HIDDEN) { $data->generalfeedback = $question->format_generalfeedback($qa); } if ($options->manualcomment != \question_display_options::HIDDEN) { if ($qa->has_manual_comment()) { // Note - the export of the step data will ensure that the files are exported. // No need to do it again here. list($comment, $commentformat, $step) = $qa->get_manual_comment(); $comment = writer::with_context($context) ->rewrite_pluginfile_urls( $questionnocontext, 'question', 'response_bf_comment', $step->get_id(), $comment ); $data->comment = $qa->get_behaviour(false)->format_comment($comment, $commentformat); } } writer::with_context($context) ->export_data($questionnocontext, $data); // Export the step data. static::export_question_attempt_steps($userid, $context, $questionnocontext, $qa, $options, $isowner); } } } /** * Export the data for each step transition for each question in each question attempt. * * Where a user is the owner of the usage, then all steps in the question usage will be exported. * Where a user is not the owner, but has been involved in the usage, then only their specific * involvement will be exported. * * @param int $userid The user to export for * @param \context $context The context that the question was used within. * @param array $questionnocontext The subcontext of this question number. * @param \question_attempt $qa The attempt being checked * @param \question_display_options $options The display options used for formatting. * @param bool $isowner Whether the user being exported is the user who used the question. */ public static function export_question_attempt_steps( int $userid, \context $context, array $questionnocontext, \question_attempt $qa, \question_display_options $options, $isowner ) { $attemptdata = (object) [ 'steps' => [], ]; $stepno = 0; foreach ($qa->get_step_iterator() as $i => $step) { $stepno++; if ($isowner || ($step->get_user_id() != $userid)) { // The user is the owner, or the author of the step. $restrictedqa = new \question_attempt_with_restricted_history($qa, $i, null); $stepdata = (object) [ // Note: Do not include the user here. 'time' => transform::datetime($step->get_timecreated()), 'action' => $qa->summarise_action($step), ]; if ($options->marks >= \question_display_options::MARK_AND_MAX) { $stepdata->mark = $qa->format_fraction_as_mark($step->get_fraction(), $options->markdp); } if ($options->correctness != \question_display_options::HIDDEN) { $stepdata->state = $restrictedqa->get_state_string($options->correctness); } if ($step->has_behaviour_var('comment')) { $comment = $step->get_behaviour_var('comment'); $commentformat = $step->get_behaviour_var('commentformat'); if (empty(trim($comment))) { // Skip empty comments. continue; } // Format the comment. $comment = writer::with_context($context) ->rewrite_pluginfile_urls( $questionnocontext, 'question', 'response_bf_comment', $step->get_id(), $comment ); // Export any files associated with the comment files area. writer::with_context($context) ->export_area_files( $questionnocontext, 'question', "response_bf_comment", $step->get_id() ); $stepdata->comment = $qa->get_behaviour(false)->format_comment($comment, $commentformat); } // Export any response files associated with this step. foreach (\question_engine::get_all_response_file_areas() as $filearea) { writer::with_context($context) ->export_area_files( $questionnocontext, 'question', $filearea, $step->get_id() ); } $attemptdata->steps[$stepno] = $stepdata; } } if (!empty($attemptdata->steps)) { writer::with_context($context) ->export_related_data($questionnocontext, 'steps', $attemptdata); } } /** * Get the list of contexts where the specified user has either created, or edited a question. * * To export usage of a question, please call {@link provider::export_question_usage()} from the module which * instantiated the usage of the question. * * @param int $userid The user to search. * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. */ public static function get_contexts_for_userid(int $userid) : contextlist { $contextlist = new contextlist(); // A user may have created or updated a question. // Questions are linked against a question category, which has a contextid field. $sql = "SELECT qc.contextid FROM {question} q JOIN {question_versions} qv ON qv.questionid = q.id JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid WHERE q.createdby = :useridcreated OR q.modifiedby = :useridmodified"; $params = [ 'useridcreated' => $userid, 'useridmodified' => $userid, ]; $contextlist->add_from_sql($sql, $params); return $contextlist; } /** * Get the list of users who have data within a context. * * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. */ public static function get_users_in_context(userlist $userlist) { $context = $userlist->get_context(); // A user may have created or updated a question. // Questions are linked against a question category, which has a contextid field. $sql = "SELECT q.createdby, q.modifiedby FROM {question} q JOIN {question_versions} qv ON qv.questionid = q.id JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid WHERE qc.contextid = :contextid"; $params = [ 'contextid' => $context->id ]; $userlist->add_from_sql('createdby', $sql, $params); $userlist->add_from_sql('modifiedby', $sql, $params); } /** * Determine related question usages for a user. * * @param string $prefix A unique prefix to add to the table alias * @param string $component The name of the component to fetch usages for. * @param string $joinfield The SQL field name to use in the JOIN ON - e.g. q.usageid * @param int $userid The user to search. * @return \qubaid_join */ public static function get_related_question_usages_for_user(string $prefix, string $component, string $joinfield, int $userid) : \qubaid_join { return new \qubaid_join(" JOIN {question_usages} {$prefix}_qu ON {$prefix}_qu.id = {$joinfield} AND {$prefix}_qu.component = :{$prefix}_usagecomponent JOIN {question_attempts} {$prefix}_qa ON {$prefix}_qa.questionusageid = {$prefix}_qu.id JOIN {question_attempt_steps} {$prefix}_qas ON {$prefix}_qas.questionattemptid = {$prefix}_qa.id", "{$prefix}_qu.id", "{$prefix}_qas.userid = :{$prefix}_stepuserid", [ "{$prefix}_stepuserid" => $userid, "{$prefix}_usagecomponent" => $component, ]); } /** * Add the list of users who have rated in the specified constraints. * * @param userlist $userlist The userlist to add the users to. * @param string $prefix A unique prefix to add to the table alias to avoid interference with your own sql. * @param string $insql The SQL to use in a sub-select for the question_usages.id query. * @param array $params The params required for the insql. * @param int|null $contextid An optional context id, in case the $sql query is not already filtered by that. */ public static function get_users_in_context_from_sql(userlist $userlist, string $prefix, string $insql, $params, int $contextid = null) { $sql = "SELECT {$prefix}_qas.userid FROM {question_attempt_steps} {$prefix}_qas JOIN {question_attempts} {$prefix}_qa ON {$prefix}_qas.questionattemptid = {$prefix}_qa.id JOIN {question_usages} {$prefix}_qu ON {$prefix}_qa.questionusageid = {$prefix}_qu.id WHERE {$prefix}_qu.id IN ({$insql})"; if ($contextid) { $sql .= " AND {$prefix}_qu.contextid = :{$prefix}_contextid"; $params["{$prefix}_contextid"] = $contextid; } $userlist->add_from_sql('userid', $sql, $params); } /** * Export all user data for the specified user, in the specified contexts. * * @param approved_contextlist $contextlist The approved contexts to export information for. */ public static function export_user_data(approved_contextlist $contextlist) { global $CFG, $DB, $SITE; if (empty($contextlist)) { return; } // Use the Moodle XML Data format. // It is the only lossless format that we support. $format = "xml"; require_once($CFG->dirroot . "/question/format/{$format}/format.php"); // THe export system needs questions in a particular format. // The easiest way to fetch these is with get_questions_category() which takes the details of a question // category. // We fetch the root question category for each context and the get_questions_category function recurses to // After fetching them, we filter out any not created or modified by the requestor. $user = $contextlist->get_user(); $userid = $user->id; list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED); $categories = $DB->get_records_select('question_categories', "contextid {$contextsql} AND parent = 0", $contextparams); $classname = "qformat_{$format}"; foreach ($categories as $category) { $context = \context::instance_by_id($category->contextid); $questions = get_questions_category($category, true); $questions = array_filter($questions, function($question) use ($userid) { return ($question->createdby == $userid) || ($question->modifiedby == $userid); }, ARRAY_FILTER_USE_BOTH); if (empty($questions)) { continue; } $qformat = new $classname(); $qformat->setQuestions($questions); $qformat->setContexts([$context]); $qformat->setContexttofile(true); // We do not know which course this belongs to, and it's not actually used except in error, so use Site. $qformat->setCourse($SITE); $content = ''; if ($qformat->exportpreprocess()) { $content = $qformat->exportprocess(false); } $subcontext = [ get_string('questionbank', 'core_question'), ]; writer::with_context($context)->export_custom_file($subcontext, 'questions.xml', $content); } } /** * Delete all data for all users in the specified context. * * @param \context $context The specific context to delete data for. * @throws \dml_exception */ public static function delete_data_for_all_users_in_context(\context $context) { 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. $sql = 'SELECT q.* FROM {question} q JOIN {question_versions} qv ON qv.questionid = q.id JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid WHERE qc.contextid = ?'; $questions = $DB->get_records_sql($sql, [$context->id]); foreach ($questions as $question) { $question->createdby = 0; $question->modifiedby = 0; $DB->update_record('question', $question); } } /** * 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. */ 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; $questiondata = $DB->get_records_sql( "SELECT q.* FROM {question} q JOIN {question_versions} qv ON qv.questionid = q.id JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid WHERE qc.contextid {$contextsql} AND q.createdby = :createdby", $contextparams); foreach ($questiondata as $question) { $question->createdby = 0; $DB->update_record('question', $question); } list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED); $contextparams['modifiedby'] = $contextlist->get_user()->id; $questiondata = $DB->get_records_sql( "SELECT q.* FROM {question} q JOIN {question_versions} qv ON qv.questionid = q.id JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid WHERE qc.contextid {$contextsql} AND q.modifiedby = :modifiedby", $contextparams); foreach ($questiondata as $question) { $question->modifiedby = 0; $DB->update_record('question', $question); } } /** * Delete multiple users within a single context. * * @param approved_userlist $userlist The approved context and user information to delete information for. */ public static function delete_data_for_users(approved_userlist $userlist) { 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. $context = $userlist->get_context(); $userids = $userlist->get_userids(); list($createdbysql, $createdbyparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); list($modifiedbysql, $modifiedbyparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); $params = ['contextid' => $context->id]; $questiondata = $DB->get_records_sql( "SELECT q.* FROM {question} q JOIN {question_versions} qv ON qv.questionid = q.id JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid WHERE qc.contextid = :contextid AND q.createdby {$createdbysql}", $params + $createdbyparams); foreach ($questiondata as $question) { $question->createdby = 0; $DB->update_record('question', $question); } $questiondata = $DB->get_records_sql( "SELECT q.* FROM {question} q JOIN {question_versions} qv ON qv.questionid = q.id JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid WHERE qc.contextid = :contextid AND q.modifiedby {$modifiedbysql}", $params + $modifiedbyparams); foreach ($questiondata as $question) { $question->modifiedby = 0; $DB->update_record('question', $question); } } } home3/cpr76684/public_html/Aem/admin/roles/classes/privacy/provider.php 0000644 00000043772 15152013467 0021700 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Privacy Subsystem implementation for core_role. * * @package core_role * @copyright 2018 Carlos Escobedo <carlos@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_role\privacy; defined('MOODLE_INTERNAL') || die(); use \core_privacy\local\metadata\collection; use \core_privacy\local\request\contextlist; use \core_privacy\local\request\approved_contextlist; use \core_privacy\local\request\transform; use \core_privacy\local\request\writer; use \core_privacy\local\request\userlist; use \core_privacy\local\request\approved_userlist; /** * Privacy provider for core_role. * * @copyright 2018 Carlos Escobedo <carlos@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\subsystem\provider, \core_privacy\local\request\subsystem\plugin_provider, \core_privacy\local\request\user_preference_provider, \core_privacy\local\request\core_userlist_provider { /** * Get information about the user data stored by this plugin. * * @param collection $collection An object for storing metadata. * @return collection The metadata. */ public static function get_metadata(collection $collection) : collection { $rolecapabilities = [ 'roleid' => 'privacy:metadata:role_capabilities:roleid', 'capability' => 'privacy:metadata:role_capabilities:capability', 'permission' => 'privacy:metadata:role_capabilities:permission', 'timemodified' => 'privacy:metadata:role_capabilities:timemodified', 'modifierid' => 'privacy:metadata:role_capabilities:modifierid' ]; $roleassignments = [ 'roleid' => 'privacy:metadata:role_assignments:roleid', 'userid' => 'privacy:metadata:role_assignments:userid', 'timemodified' => 'privacy:metadata:role_assignments:timemodified', 'modifierid' => 'privacy:metadata:role_assignments:modifierid', 'component' => 'privacy:metadata:role_assignments:component', 'itemid' => 'privacy:metadata:role_assignments:itemid' ]; $collection->add_database_table('role_capabilities', $rolecapabilities, 'privacy:metadata:role_capabilities:tableexplanation'); $collection->add_database_table('role_assignments', $roleassignments, 'privacy:metadata:role_assignments:tableexplanation'); $collection->add_user_preference('definerole_showadvanced', 'privacy:metadata:preference:showadvanced'); return $collection; } /** * Export all user preferences for the plugin. * * @param int $userid The userid of the user whose data is to be exported. */ public static function export_user_preferences(int $userid) { $showadvanced = get_user_preferences('definerole_showadvanced', null, $userid); if ($showadvanced !== null) { writer::export_user_preference('core_role', 'definerole_showadvanced', transform::yesno($showadvanced), get_string('privacy:metadata:preference:showadvanced', 'core_role') ); } } /** * Return all contexts for this userid. * * @param int $userid The user ID. * @return contextlist The list of context IDs. */ public static function get_contexts_for_userid(int $userid) : contextlist { global $DB; $contextlist = new contextlist(); // The role_capabilities table contains user data. $contexts = [ CONTEXT_SYSTEM, CONTEXT_USER, CONTEXT_COURSECAT, CONTEXT_COURSE, CONTEXT_MODULE, CONTEXT_BLOCK ]; list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED); $sql = "SELECT ctx.id FROM {context} ctx JOIN {role_capabilities} rc ON rc.contextid = ctx.id AND ((ctx.contextlevel {$insql} AND rc.modifierid = :modifierid) OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid))"; $params = [ 'modifierid' => $userid, 'contextlevel' => CONTEXT_USER, 'userid' => $userid ]; $params += $inparams; $contextlist->add_from_sql($sql, $params); // The role_assignments table contains user data. $contexts = [ CONTEXT_SYSTEM, CONTEXT_USER, CONTEXT_COURSECAT, CONTEXT_COURSE, CONTEXT_MODULE, CONTEXT_BLOCK ]; list($insql, $inparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED); $params = [ 'userid' => $userid, 'modifierid' => $userid ]; $params += $inparams; $sql = "SELECT ctx.id FROM {role_assignments} ra JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel {$insql} WHERE (ra.userid = :userid OR ra.modifierid = :modifierid) AND ra.component != 'tool_cohortroles'"; $contextlist->add_from_sql($sql, $params); return $contextlist; } /** * Get the list of users within a specific context. * * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. */ public static function get_users_in_context(userlist $userlist) { if (empty($userlist)) { return; } $context = $userlist->get_context(); // Include users who created or modified role capabilities. $sql = "SELECT modifierid as userid FROM {role_capabilities} WHERE contextid = :contextid"; $params = [ 'contextid' => $context->id ]; $userlist->add_from_sql('userid', $sql, $params); // Include users that have a role assigned to them. $sql = "SELECT userid FROM {role_assignments} WHERE contextid = :contextid"; $userlist->add_from_sql('userid', $sql, $params); // Include users who created or modified the role assignment. // Differentiate and exclude special cases where tool_cohortroles adds records through the // "Assign user roles to cohort" feature into the role_assignments table. // These records should be separately processed in tool_cohortroles. $sql = "SELECT modifierid as userid FROM {role_assignments} WHERE contextid = :contextid AND component != 'tool_cohortroles'"; $userlist->add_from_sql('userid', $sql, $params); } /** * Export all user data for the specified user, in the specified contexts. * * @param approved_contextlist $contextlist The list of approved contexts for a user. */ public static function export_user_data(approved_contextlist $contextlist) { global $DB; if (empty($contextlist)) { return; } $rolesnames = self::get_roles_name(); $userid = $contextlist->get_user()->id; $ctxfields = \context_helper::get_preload_record_columns_sql('ctx'); list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED); // Role Assignments export data. $contexts = [ CONTEXT_SYSTEM, CONTEXT_USER, CONTEXT_COURSECAT, CONTEXT_COURSE, CONTEXT_MODULE, CONTEXT_BLOCK ]; list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED); $sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, $ctxfields FROM {role_assignments} ra JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel {$inctxsql} AND (ra.userid = :userid OR ra.modifierid = :modifierid) AND ra.component != 'tool_cohortroles' JOIN {role} r ON r.id = ra.roleid WHERE ctx.id {$insql}"; $params = ['userid' => $userid, 'modifierid' => $userid]; $params += $inparams; $params += $ctxparams; $assignments = $DB->get_recordset_sql($sql, $params); foreach ($assignments as $assignment) { \context_helper::preload_from_record($assignment); $alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[ 'timemodified' => transform::datetime($assignment->timemodified), 'userid' => transform::user($assignment->userid), 'modifierid' => transform::user($assignment->modifierid) ]; } $assignments->close(); if (!empty($alldata)) { array_walk($alldata, function($roledata, $contextid) { $context = \context::instance_by_id($contextid); array_walk($roledata, function($data, $rolename) use ($context) { writer::with_context($context)->export_data( [get_string('privacy:metadata:role_assignments', 'core_role'), $rolename], (object)$data); }); }); unset($alldata); } // Role Capabilities export data. $strpermissions = self::get_permissions_name(); $contexts = [ CONTEXT_SYSTEM, CONTEXT_USER, CONTEXT_COURSECAT, CONTEXT_COURSE, CONTEXT_MODULE, CONTEXT_BLOCK ]; list($inctxsql, $ctxparams) = $DB->get_in_or_equal($contexts, SQL_PARAMS_NAMED); $sql = "SELECT rc.id, rc.contextid, rc.capability, rc.permission, rc.timemodified, rc.roleid, $ctxfields FROM {context} ctx JOIN {role_capabilities} rc ON rc.contextid = ctx.id AND ((ctx.contextlevel {$inctxsql} AND rc.modifierid = :modifierid) OR (ctx.contextlevel = :contextlevel AND ctx.instanceid = :userid)) WHERE ctx.id {$insql}"; $params = [ 'modifierid' => $userid, 'contextlevel' => CONTEXT_USER, 'userid' => $userid ]; $params += $inparams; $params += $ctxparams; $capabilities = $DB->get_recordset_sql($sql, $params); foreach ($capabilities as $capability) { \context_helper::preload_from_record($capability); $alldata[$capability->contextid][$rolesnames[$capability->roleid]][] = (object)[ 'timemodified' => transform::datetime($capability->timemodified), 'capability' => $capability->capability, 'permission' => $strpermissions[$capability->permission] ]; } $capabilities->close(); if (!empty($alldata)) { array_walk($alldata, function($capdata, $contextid) { $context = \context::instance_by_id($contextid); array_walk($capdata, function($data, $rolename) use ($context) { writer::with_context($context)->export_data( [get_string('privacy:metadata:role_capabilities', 'core_role'), $rolename], (object)$data); }); }); } } /** * Exports the data relating to tool_cohortroles component on role assignments by * Assign user roles to cohort feature. * * @param int $userid The user ID. */ public static function export_user_role_to_cohort(int $userid) { global $DB; $rolesnames = self::get_roles_name(); $sql = "SELECT ra.id, ra.contextid, ra.roleid, ra.userid, ra.timemodified, ra.modifierid, r.id as roleid FROM {role_assignments} ra JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = :contextlevel AND ra.component = 'tool_cohortroles' JOIN {role} r ON r.id = ra.roleid WHERE ctx.instanceid = :instanceid OR ra.userid = :userid"; $params = ['userid' => $userid, 'instanceid' => $userid, 'contextlevel' => CONTEXT_USER]; $assignments = $DB->get_recordset_sql($sql, $params); foreach ($assignments as $assignment) { $alldata[$assignment->contextid][$rolesnames[$assignment->roleid]][] = (object)[ 'timemodified' => transform::datetime($assignment->timemodified), 'userid' => transform::user($assignment->userid), 'modifierid' => transform::user($assignment->modifierid) ]; } $assignments->close(); if (!empty($alldata)) { array_walk($alldata, function($roledata, $contextid) { $context = \context::instance_by_id($contextid); array_walk($roledata, function($data, $rolename) use ($context) { writer::with_context($context)->export_related_data( [get_string('privacy:metadata:role_cohortroles', 'core_role'), $rolename], 'cohortroles', (object)$data); }); }); } } /** * Delete all user data for this context. * * @param \context $context The context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { global $DB; // Don't remove data from role_capabilities. // Because this data affects the whole Moodle, there are override capabilities. // Don't belong to the modifier user. // Remove data from role_assignments. $DB->delete_records('role_assignments', ['contextid' => $context->id]); } /** * Delete multiple users within a single context. * * @param approved_userlist $userlist The approved context and user information to delete information for. */ public static function delete_data_for_users(approved_userlist $userlist) { global $DB; // Don't remove data from role_capabilities. // Because this data affects the whole Moodle, there are override capabilities. // Don't belong to the modifier user. $context = $userlist->get_context(); $userids = $userlist->get_userids(); if (empty($userids)) { return; } list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); $params = ['contextid' => $context->id] + $userparams; // Remove data from role_assignments. $DB->delete_records_select('role_assignments', "contextid = :contextid AND userid {$usersql}", $params); } /** * Delete all user data for this user only. * * @param approved_contextlist $contextlist The list of approved contexts for a user. */ public static function delete_data_for_user(approved_contextlist $contextlist) { global $DB; // Don't remove data from role_capabilities. // Because this data affects the whole Moodle, there are override capabilities. // Don't belong to the modifier user. // Remove data from role_assignments. if (empty($contextlist->count())) { return; } $userid = $contextlist->get_user()->id; $contextids = $contextlist->get_contextids(); list($contextsql, $contextparams) = $DB->get_in_or_equal($contextids, SQL_PARAMS_NAMED); $params = ['userid' => $userid] + $contextparams; // Only delete the roles assignments where the user is assigned in all contexts. $DB->delete_records_select('role_assignments', "userid = :userid AND contextid {$contextsql}", $params); } /** * Delete user entries in role_assignments related to the feature * Assign user roles to cohort feature. * * @param int $userid The user ID. */ public static function delete_user_role_to_cohort(int $userid) { global $DB; // Delete entries where userid is a mentor by tool_cohortroles. $DB->delete_records('role_assignments', ['userid' => $userid, 'component' => 'tool_cohortroles']); } /** * Get all the localised roles name in a simple array. * * @return array Array of name of the roles by roleid. */ protected static function get_roles_name() { $roles = role_fix_names(get_all_roles(), \context_system::instance(), ROLENAME_ORIGINAL); $rolesnames = array(); foreach ($roles as $role) { $rolesnames[$role->id] = $role->localname; } return $rolesnames; } /** * Get all the permissions name in a simple array. * * @return array Array of permissions name. */ protected static function get_permissions_name() { $strpermissions = array( CAP_INHERIT => get_string('inherit', 'role'), CAP_ALLOW => get_string('allow', 'role'), CAP_PREVENT => get_string('prevent', 'role'), CAP_PROHIBIT => get_string('prohibit', 'role') ); return $strpermissions; } } home3/cpr76684/public_html/Aem/auth/none/classes/privacy/provider.php 0000644 00000002745 15152067040 0021353 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Privacy Subsystem implementation for auth_none. * * @package auth_none * @copyright 2018 Carlos Escobedo <carlos@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace auth_none\privacy; defined('MOODLE_INTERNAL') || die(); /** * Privacy Subsystem for auth_none implementing null_provider. * * @copyright 2018 Carlos Escobedo <carlos@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\null_provider { /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. * * @return string */ public static function get_reason() : string { return 'privacy:metadata'; } } home3/cpr76684/public_html/Aem/user/classes/privacy/provider.php 0000644 00000060700 15152101277 0020425 0 ustar 00 <?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Privacy class for requesting user data. * * @package core_user * @copyright 2018 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_user\privacy; defined('MOODLE_INTERNAL') || die(); use \core_privacy\local\metadata\collection; use \core_privacy\local\request\transform; use \core_privacy\local\request\contextlist; use \core_privacy\local\request\approved_contextlist; use \core_privacy\local\request\writer; use core_privacy\local\request\userlist; use \core_privacy\local\request\approved_userlist; /** * Privacy class for requesting user data. * * @package core_comment * @copyright 2018 Adrian Greeve <adrian@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\provider, \core_privacy\local\request\core_userlist_provider, \core_privacy\local\request\subsystem\provider, \core_privacy\local\request\user_preference_provider { /** * Returns information about the user data stored in this component. * * @param collection $collection A list of information about this component * @return collection The collection object filled out with information about this component. */ public static function get_metadata(collection $collection) : collection { $userfields = [ 'id' => 'privacy:metadata:id', 'auth' => 'privacy:metadata:auth', 'confirmed' => 'privacy:metadata:confirmed', 'policyagreed' => 'privacy:metadata:policyagreed', 'deleted' => 'privacy:metadata:deleted', 'suspended' => 'privacy:metadata:suspended', 'mnethostid' => 'privacy:metadata:mnethostid', 'username' => 'privacy:metadata:username', 'password' => 'privacy:metadata:password', 'idnumber' => 'privacy:metadata:idnumber', 'firstname' => 'privacy:metadata:firstname', 'lastname' => 'privacy:metadata:lastname', 'email' => 'privacy:metadata:email', 'emailstop' => 'privacy:metadata:emailstop', 'phone1' => 'privacy:metadata:phone', 'phone2' => 'privacy:metadata:phone', 'institution' => 'privacy:metadata:institution', 'department' => 'privacy:metadata:department', 'address' => 'privacy:metadata:address', 'city' => 'privacy:metadata:city', 'country' => 'privacy:metadata:country', 'lang' => 'privacy:metadata:lang', 'calendartype' => 'privacy:metadata:calendartype', 'theme' => 'privacy:metadata:theme', 'timezone' => 'privacy:metadata:timezone', 'firstaccess' => 'privacy:metadata:firstaccess', 'lastaccess' => 'privacy:metadata:lastaccess', 'lastlogin' => 'privacy:metadata:lastlogin', 'currentlogin' => 'privacy:metadata:currentlogin', 'lastip' => 'privacy:metadata:lastip', 'secret' => 'privacy:metadata:secret', 'picture' => 'privacy:metadata:picture', 'description' => 'privacy:metadata:description', 'maildigest' => 'privacy:metadata:maildigest', 'maildisplay' => 'privacy:metadata:maildisplay', 'autosubscribe' => 'privacy:metadata:autosubscribe', 'trackforums' => 'privacy:metadata:trackforums', 'timecreated' => 'privacy:metadata:timecreated', 'timemodified' => 'privacy:metadata:timemodified', 'trustbitmask' => 'privacy:metadata:trustbitmask', 'imagealt' => 'privacy:metadata:imagealt', 'lastnamephonetic' => 'privacy:metadata:lastnamephonetic', 'firstnamephonetic' => 'privacy:metadata:firstnamephonetic', 'middlename' => 'privacy:metadata:middlename', 'alternatename' => 'privacy:metadata:alternatename', 'moodlenetprofile' => 'privacy:metadata:moodlenetprofile' ]; $passwordhistory = [ 'userid' => 'privacy:metadata:userid', 'hash' => 'privacy:metadata:hash', 'timecreated' => 'privacy:metadata:timecreated' ]; $lastaccess = [ 'userid' => 'privacy:metadata:userid', 'courseid' => 'privacy:metadata:courseid', 'timeaccess' => 'privacy:metadata:timeaccess' ]; $userpasswordresets = [ 'userid' => 'privacy:metadata:userid', 'timerequested' => 'privacy:metadata:timerequested', 'timererequested' => 'privacy:metadata:timererequested', 'token' => 'privacy:metadata:token' ]; $userdevices = [ 'userid' => 'privacy:metadata:userid', 'appid' => 'privacy:metadata:appid', 'name' => 'privacy:metadata:devicename', 'model' => 'privacy:metadata:model', 'platform' => 'privacy:metadata:platform', 'version' => 'privacy:metadata:version', 'pushid' => 'privacy:metadata:pushid', 'uuid' => 'privacy:metadata:uuid', 'timecreated' => 'privacy:metadata:timecreated', 'timemodified' => 'privacy:metadata:timemodified' ]; $usersessions = [ 'state' => 'privacy:metadata:state', 'sid' => 'privacy:metadata:sid', 'userid' => 'privacy:metadata:userid', 'sessdata' => 'privacy:metadata:sessdata', 'timecreated' => 'privacy:metadata:timecreated', 'timemodified' => 'privacy:metadata:timemodified', 'firstip' => 'privacy:metadata:firstip', 'lastip' => 'privacy:metadata:lastip' ]; $courserequest = [ 'fullname' => 'privacy:metadata:fullname', 'shortname' => 'privacy:metadata:shortname', 'summary' => 'privacy:metadata:summary', 'category' => 'privacy:metadata:category', 'reason' => 'privacy:metadata:reason', 'requester' => 'privacy:metadata:requester' ]; $mypages = [ 'userid' => 'privacy:metadata:my_pages:userid', 'name' => 'privacy:metadata:my_pages:name', 'private' => 'privacy:metadata:my_pages:private', ]; $userpreferences = [ 'userid' => 'privacy:metadata:user_preferences:userid', 'name' => 'privacy:metadata:user_preferences:name', 'value' => 'privacy:metadata:user_preferences:value' ]; $collection->add_database_table('user', $userfields, 'privacy:metadata:usertablesummary'); $collection->add_database_table('user_password_history', $passwordhistory, 'privacy:metadata:passwordtablesummary'); $collection->add_database_table('user_password_resets', $userpasswordresets, 'privacy:metadata:passwordresettablesummary'); $collection->add_database_table('user_lastaccess', $lastaccess, 'privacy:metadata:lastaccesstablesummary'); $collection->add_database_table('user_devices', $userdevices, 'privacy:metadata:devicetablesummary'); $collection->add_database_table('course_request', $courserequest, 'privacy:metadata:requestsummary'); $collection->add_database_table('sessions', $usersessions, 'privacy:metadata:sessiontablesummary'); $collection->add_database_table('my_pages', $mypages, 'privacy:metadata:my_pages'); $collection->add_database_table('user_preferences', $userpreferences, 'privacy:metadata:user_preferences'); $collection->add_subsystem_link('core_files', [], 'privacy:metadata:filelink'); $collection->add_user_preference( 'core_user_welcome', 'privacy:metadata:user_preference:core_user_welcome' ); return $collection; } /** * Get the list of contexts that contain user information for the specified user. * * @param int $userid The user to search. * @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin. */ public static function get_contexts_for_userid(int $userid) : contextlist { $params = ['userid' => $userid, 'contextuser' => CONTEXT_USER]; $sql = "SELECT id FROM {context} WHERE instanceid = :userid and contextlevel = :contextuser"; $contextlist = new contextlist(); $contextlist->add_from_sql($sql, $params); return $contextlist; } /** * Get the list of users within a specific context. * * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. */ public static function get_users_in_context(userlist $userlist) { $context = $userlist->get_context(); if (!$context instanceof \context_user) { return; } $userlist->add_user($context->instanceid); } /** * Export all user data for the specified user, in the specified contexts. * * @param approved_contextlist $contextlist The approved contexts to export information for. */ 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); } /** * Delete all data for all users in the specified context. * * @param context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { // Only delete data for a user context. if ($context->contextlevel == CONTEXT_USER) { static::delete_user_data($context->instanceid, $context); } } /** * Delete multiple users within a single context. * * @param approved_userlist $userlist The approved context and user information to delete information for. */ public static function delete_data_for_users(approved_userlist $userlist) { $context = $userlist->get_context(); if ($context instanceof \context_user) { static::delete_user_data($context->instanceid, $context); } } /** * 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. */ 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()); } } } /** * Deletes non vital information about a user. * * @param int $userid The user ID to delete * @param \context $context The user context */ protected static function delete_user_data(int $userid, \context $context) { global $DB; // Delete password history. $DB->delete_records('user_password_history', ['userid' => $userid]); // Delete last access. $DB->delete_records('user_lastaccess', ['userid' => $userid]); // Delete password resets. $DB->delete_records('user_password_resets', ['userid' => $userid]); // Delete user devices. $DB->delete_records('user_devices', ['userid' => $userid]); // Delete user course requests. $DB->delete_records('course_request', ['requester' => $userid]); // Delete sessions. $DB->delete_records('sessions', ['userid' => $userid]); // Do I delete user preferences? Seems like the right place to do it. $DB->delete_records('user_preferences', ['userid' => $userid]); // Delete all of the files for this user. $fs = get_file_storage(); $fs->delete_area_files($context->id, 'user'); // For the user record itself we only want to remove unnecessary data. We still need the core data to keep as a record // that we actually did follow the request to be forgotten. $user = \core_user::get_user($userid); // Update fields we wish to change to nothing. $user->deleted = 1; $user->idnumber = ''; $user->emailstop = 0; $user->phone1 = ''; $user->phone2 = ''; $user->institution = ''; $user->department = ''; $user->address = ''; $user->city = ''; $user->country = ''; $user->lang = ''; $user->calendartype = ''; $user->theme = ''; $user->timezone = ''; $user->firstaccess = 0; $user->lastaccess = 0; $user->lastlogin = 0; $user->currentlogin = 0; $user->lastip = 0; $user->secret = ''; $user->picture = ''; $user->description = ''; $user->descriptionformat = 0; $user->mailformat = 0; $user->maildigest = 0; $user->maildisplay = 0; $user->autosubscribe = 0; $user->trackforums = 0; $user->timecreated = 0; $user->timemodified = 0; $user->trustbitmask = 0; $user->imagealt = ''; $user->lastnamephonetic = ''; $user->firstnamephonetic = ''; $user->middlename = ''; $user->alternatename = ''; $DB->update_record('user', $user); } /** * Export core user data. * * @param \stdClass $user The user object. * @param \context $context The user context. */ protected static function export_user(\stdClass $user, \context $context) { $data = (object) [ 'auth' => $user->auth, 'confirmed' => transform::yesno($user->confirmed), 'policyagreed' => transform::yesno($user->policyagreed), 'deleted' => transform::yesno($user->deleted), 'suspended' => transform::yesno($user->suspended), 'username' => $user->username, 'idnumber' => $user->idnumber, 'firstname' => format_string($user->firstname, true, ['context' => $context]), 'lastname' => format_string($user->lastname, true, ['context' => $context]), 'email' => $user->email, 'emailstop' => transform::yesno($user->emailstop), 'phone1' => format_string($user->phone1, true, ['context' => $context]), 'phone2' => format_string($user->phone2, true, ['context' => $context]), 'institution' => format_string($user->institution, true, ['context' => $context]), 'department' => format_string($user->department, true, ['context' => $context]), 'address' => format_string($user->address, true, ['context' => $context]), 'city' => format_string($user->city, true, ['context' => $context]), 'country' => format_string($user->country, true, ['context' => $context]), 'lang' => $user->lang, 'calendartype' => $user->calendartype, 'theme' => $user->theme, 'timezone' => $user->timezone, 'firstaccess' => $user->firstaccess ? transform::datetime($user->firstaccess) : null, 'lastaccess' => $user->lastaccess ? transform::datetime($user->lastaccess) : null, 'lastlogin' => $user->lastlogin ? transform::datetime($user->lastlogin) : null, 'currentlogin' => $user->currentlogin ? transform::datetime($user->currentlogin) : null, 'lastip' => $user->lastip, 'secret' => $user->secret, 'picture' => $user->picture, 'description' => format_text( writer::with_context($context)->rewrite_pluginfile_urls( [], 'user', 'profile', '', $user->description ), $user->descriptionformat, ['context' => $context]), 'maildigest' => transform::yesno($user->maildigest), 'maildisplay' => $user->maildisplay, 'autosubscribe' => transform::yesno($user->autosubscribe), 'trackforums' => transform::yesno($user->trackforums), 'timecreated' => transform::datetime($user->timecreated), 'timemodified' => transform::datetime($user->timemodified), 'imagealt' => format_string($user->imagealt, true, ['context' => $context]), 'lastnamephonetic' => format_string($user->lastnamephonetic, true, ['context' => $context]), 'firstnamephonetic' => format_string($user->firstnamephonetic, true, ['context' => $context]), 'middlename' => format_string($user->middlename, true, ['context' => $context]), 'alternatename' => format_string($user->alternatename, true, ['context' => $context]) ]; writer::with_context($context)->export_area_files([], 'user', 'profile', 0) ->export_data([], $data); // Export profile images. writer::with_context($context)->export_area_files([get_string('privacy:profileimagespath', 'user')], 'user', 'icon', 0); // Export private files. writer::with_context($context)->export_area_files([get_string('privacy:privatefilespath', 'user')], 'user', 'private', 0); // Export draft files. writer::with_context($context)->export_area_files([get_string('privacy:draftfilespath', 'user')], 'user', 'draft', false); } /** * Export information about the last time a user accessed a course. * * @param int $userid The user ID. * @param \context $context The user context. */ protected static function export_lastaccess(int $userid, \context $context) { global $DB; $sql = "SELECT c.id, c.fullname, ul.timeaccess FROM {user_lastaccess} ul JOIN {course} c ON c.id = ul.courseid WHERE ul.userid = :userid"; $params = ['userid' => $userid]; $records = $DB->get_records_sql($sql, $params); if (!empty($records)) { $lastaccess = (object) array_map(function($record) use ($context) { return [ 'course_name' => format_string($record->fullname, true, ['context' => $context]), 'timeaccess' => transform::datetime($record->timeaccess) ]; }, $records); writer::with_context($context)->export_data([get_string('privacy:lastaccesspath', 'user')], $lastaccess); } } /** * Exports information about password resets. * * @param int $userid The user ID * @param \context $context Context for this user. */ protected static function export_password_resets(int $userid, \context $context) { global $DB; $records = $DB->get_records('user_password_resets', ['userid' => $userid]); if (!empty($records)) { $passwordresets = (object) array_map(function($record) { return [ 'timerequested' => transform::datetime($record->timerequested), 'timererequested' => transform::datetime($record->timererequested) ]; }, $records); writer::with_context($context)->export_data([get_string('privacy:passwordresetpath', 'user')], $passwordresets); } } /** * Exports information about the user's mobile devices. * * @param int $userid The user ID. * @param \context $context Context for this user. */ protected static function export_user_devices(int $userid, \context $context) { global $DB; $records = $DB->get_records('user_devices', ['userid' => $userid]); if (!empty($records)) { $userdevices = (object) array_map(function($record) { return [ 'appid' => $record->appid, 'name' => $record->name, 'model' => $record->model, 'platform' => $record->platform, 'version' => $record->version, 'timecreated' => transform::datetime($record->timecreated), 'timemodified' => transform::datetime($record->timemodified) ]; }, $records); writer::with_context($context)->export_data([get_string('privacy:devicespath', 'user')], $userdevices); } } /** * Exports information about course requests this user made. * * @param int $userid The user ID. * @param \context $context The context object */ protected static function export_course_requests(int $userid, \context $context) { global $DB; $sql = "SELECT cr.shortname, cr.fullname, cr.summary, cc.name AS category, cr.reason FROM {course_request} cr JOIN {course_categories} cc ON cr.category = cc.id WHERE cr.requester = :userid"; $params = ['userid' => $userid]; $records = $DB->get_records_sql($sql, $params); if ($records) { writer::with_context($context)->export_data([get_string('privacy:courserequestpath', 'user')], (object) $records); } } /** * Get details about the user's password history. * * @param int $userid The user ID that we are getting the password history for. * @param \context $context the user context. */ protected static function export_password_history(int $userid, \context $context) { global $DB; // Just provide a count of how many entries we have. $recordcount = $DB->count_records('user_password_history', ['userid' => $userid]); if ($recordcount) { $passwordhistory = (object) ['password_history_count' => $recordcount]; writer::with_context($context)->export_data([get_string('privacy:passwordhistorypath', 'user')], $passwordhistory); } } /** * Exports information about the user's session. * * @param int $userid The user ID. * @param \context $context The context for this user. */ protected static function export_user_session_data(int $userid, \context $context) { global $DB, $SESSION; $records = $DB->get_records('sessions', ['userid' => $userid]); if (!empty($records)) { $sessiondata = (object) array_map(function($record) { return [ 'state' => $record->state, 'sessdata' => base64_decode($record->sessdata), 'timecreated' => transform::datetime($record->timecreated), 'timemodified' => transform::datetime($record->timemodified), 'firstip' => $record->firstip, 'lastip' => $record->lastip ]; }, $records); writer::with_context($context)->export_data([get_string('privacy:sessionpath', 'user')], $sessiondata); } } /** * Export all user preferences for the plugin. * * @param int $userid The userid of the user whose data is to be exported. */ public static function export_user_preferences(int $userid) { $userwelcomepreference = get_user_preferences('core_user_welcome', null, $userid); if ($userwelcomepreference !== null) { writer::export_user_preference( 'core_user', 'core_user_welcome', $userwelcomepreference, get_string('privacy:metadata:user_preference:core_user_welcome', 'core_user') ); } } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�