diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 14bccca..df92590 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -35,6 +35,7 @@ use core_privacy\local\request\transform; use tool_dataprivacy\context_instance; use context; use local_treestudyplan\studyline; +use local_treestudyplan\studyplan; /** * Privacy provider @@ -297,53 +298,103 @@ class provider implements \core_privacy\local\metadata\provider, public static function delete_data_for_all_users_in_context(context $context) { global $DB; // Find studyplans in context. - if ($context->contextlevel == CONTEXT_COURSECAT) { // The system context (probably) never be triggered like this, so limit code to Categories - $sql = "SELECT s.id FROM {local_treestudyplan} WHERE ( a.user_id = :userid AND s.context_id = :contextid)"; + if ($context->contextlevel == CONTEXT_COURSECAT) { // The system context (probably) never be triggered like this, so limit code to Categories. + $sql = "SELECT s.id FROM {local_treestudyplan} WHERE (s.context_id = :contextid)"; $planids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id]); + // Remove all associated users to the studyplan. foreach ($planids as $planid) { $DB->delete_records("local_treestudyplan_user", ["studyplan_id" => $planid]); + $DB->delete_records("local_treestudyplan_cohort", ["studyplan_id" => $planid]); + $DB->delete_records("local_treestudyplan_teachers", ["studyplan_id" => $planid]); + $DB->delete_records("local_treestudyplan_coach", ["studyplan_id" => $planid]); } + + // Remove all line enrolment associations. + $sql = "SELECT l.id FROM {local_treestudyplan_line} l + INNER JOIN {local_treestudyplan_page} p ON l.page_id = p.id + INNER JOIN {local_treestudyplan} s ON p.studyplan_id = s.id + WHERE (s.context_id = :contextid)"; + $lineids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id]); + foreach ($lineids as $lineid) { + $DB->delete_records("local_treestudyplan_lineuser", ["line_id" => $lineid]); + } + } - // TODO: REMOVE INVITATIONS FOR THE RELEVANT STUDYPLANS AS WELL - // TODO: REMOVE LINE ENROLLMENTS FOR THESE STUDYPLANS - // TODO: REMOVE COACHES FOR THESE STUDYPLANS } + /** + * Removes all user data for one user in one specific context + * @param context $context The context in which to remove the user + * @param int $userid The userid of the user to remove + */ + private static function delete_user_in_context(\context $context, int $userid) { + global $DB; + if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT) { + if ($context->contextlevel == CONTEXT_SYSTEM) { + // Also delete all invitations for this user. + $DB->delete_records("local_treestudyplan_invit", ["user_id" => $userid]); + + // Retrieve all studyplans in system context. + $sql = "SELECT s.id FROM {local_treestudyplan} INNER JOIN {local_treestudyplan_user} a ON a.studyplan_id = s.id + WHERE (s.context_id <= 1)"; + $planids = $DB->get_fieldset_sql($sql); + + // Find all lineids in system context. + $sql = "SELECT l.id FROM {local_treestudyplan_line} l + INNER JOIN {local_treestudyplan_page} p ON l.page_id = p.id + INNER JOIN {local_treestudyplan} s ON p.studyplan_id = s.id + WHERE (s.context_id <= 1)"; + $lineids = $DB->get_fieldset_sql($sql); + + } else { // if ($context->contextlevel == CONTEXT_COURSECAT) { + // Retrieve all studyplans in this category. + $sql = "SELECT s.id FROM {local_treestudyplan} INNER JOIN {local_treestudyplan_user} a ON a.studyplan_id = s.id + WHERE (s.context_id = :contextid)"; + $planids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id]); + + // Find all lineids in this context. + $sql = "SELECT l.id FROM {local_treestudyplan_line} l + INNER JOIN {local_treestudyplan_page} p ON l.page_id = p.id + INNER JOIN {local_treestudyplan} s ON p.studyplan_id = s.id + WHERE (s.context_id = :contextid)"; + $lineids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id]); + } + + foreach ($planids as $planid) { + // Remove all associated users to the studyplan. + $DB->delete_records("local_treestudyplan_user", ["studyplan_id" => $planid, "user_id" => $userid]); + $DB->delete_records("local_treestudyplan_cohort", ["studyplan_id" => $planid, "user_id" => $userid]); + $DB->delete_records("local_treestudyplan_teachers", ["studyplan_id" => $planid, "teacher_id" => $userid]); + $DB->delete_records("local_treestudyplan_coach", ["studyplan_id" => $planid, "user_id" => $userid]); + } + foreach ($lineids as $lineid) { + // Remove all line enrollments for this user. + $DB->delete_records("local_treestudyplan_lineuser", ["line_id" => $lineid, "user_id" => $userid]); + + // Replace all enrolledby references with the admin user (2). + $records = $DB->get_records("local_treestudyplan_lineuser",["line_id" => $lineid, "enrolledby" => $userid]); + foreach ($records as $r) { + $r->enrolledby = 2; // Replace by admin user. + $DB->update_record("local_treestudyplan_lineuser",$r); + } + } + } + } + + /** * 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; $user = $contextlist->get_user(); foreach ($contextlist->get_contexts() as $context) { - - if ($context->contextlevel == CONTEXT_SYSTEM) { - // Delete all associations for this user if the system context is included. - $DB->delete_records("local_treestudyplan_user", ["user_id" => $user->id]); - - // Also delete all invitations for this user. - $DB->delete_records("local_treestudyplan_invit", ["user_id" => $user->id]); - - } else if ($context->contextlevel == CONTEXT_COURSECAT) { - $sql = "SELECT s.id FROM {local_treestudyplan} INNER JOIN {local_treestudyplan_user} a ON a.studyplan_id = s.id - WHERE ( a.user_id = :userid AND s.context_id = :contextid)"; - $planids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id, "userid" => $user->id]); - - foreach ($planids as $planid) { - $DB->delete_records("local_treestudyplan_user", ["studyplan_id" => $planid, "user_id" => $user->id]); - } - } + static::delete_user_in_context($context, $user->id); } - - // TODO: REMOVE LINE ENROLLMENTS - // TODO: Replace ENROLLEDBY by id 2 (ADMIN user) - // TODO: REMOVE COACHES - // TODO: REMOVE TEACHING CACHE } /** @@ -351,32 +402,73 @@ class provider implements \core_privacy\local\metadata\provider, * @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) { + global $DB; $context = $userlist->get_context(); - if ($context instanceof \context_system) { - // Add all invitations. - $sql = "SELECT i.user_id as userid - FROM {local_treestudyplan_invit} i;"; - $userlist->add_from_sql('userid', $sql, []); + // Studyplan contexts are only System and Categories. + if ($context->contextlevel == CONTEXT_SYSTEM || $context->contextlevel == CONTEXT_COURSECAT) { + if ($context->contextlevel == CONTEXT_SYSTEM) { + // Add all invitations. + $sql = "SELECT i.user_id as userid + FROM {local_treestudyplan_invit} i"; + $userlist->add_from_sql('userid', $sql, []); - // Also add "contextless studyplans, they are considered in system context". - $sql = "SELECT a.user_id as userid FROM {local_treestudyplan_user} a - INNER JOIN {local_treestudyplan} s ON a.studyplan_id = s.id - WHERE ( a.context_id is NULL or a.context_id < 1) - "; - $userlist->add_from_sql('userid', $sql, []); + // Add directly associated users. + $sql = "SELECT a.user_id as userid FROM {local_treestudyplan_user} a + INNER JOIN {local_treestudyplan} s ON a.studyplan_id = s.id + WHERE ( s.context_id is NULL or s.context_id <= 1)"; + $userlist->add_from_sql('userid', $sql, []); + // Add coaching users. + $sql = "SELECT a.user_id as userid FROM {local_treestudyplan_coach} a + INNER JOIN {local_treestudyplan} s ON a.studyplan_id = s.id + WHERE ( s.context_id is NULL or s.context_id <= 1)"; + $userlist->add_from_sql('userid', $sql, []); + + // Do not add teaching users, since this is simply a cache of data elsewhere in the system. + + // Find all lineids in this context to process in next step + $sql = "SELECT l.id FROM {local_treestudyplan_line} l + INNER JOIN {local_treestudyplan_page} p ON l.page_id = p.id + INNER JOIN {local_treestudyplan} s ON p.studyplan_id = s.id + WHERE (sa.context_id is NULL or a.context_id <= 1)"; + $lineids = $DB->get_fieldset_sql($sql, []); + + } else { + // Add directly associated users. + $sql = "SELECT a.user_id as userid FROM {local_treestudyplan_user} a + INNER JOIN {local_treestudyplan} s ON a.studyplan_id = s.id + WHERE ( s.context_id = :contextid )"; + $userlist->add_from_sql('userid', $sql, ["contextid" => $context->id]); + + // Add coaching users. + $sql = "SELECT a.user_id as userid FROM {local_treestudyplan_coach} a + INNER JOIN {local_treestudyplan} s ON a.studyplan_id = s.id + WHERE ( s.context_id = :contextid )"; + $userlist->add_from_sql('userid', $sql, ["contextid" => $context->id]); + + // Do not add teaching users, since this is simply a cache of data elsewhere in the system. + + // Find all lineids in this context to process in next step. + $sql = "SELECT l.id FROM {local_treestudyplan_line} l + INNER JOIN {local_treestudyplan_page} p ON l.page_id = p.id + INNER JOIN {local_treestudyplan} s ON p.studyplan_id = s.id + WHERE (s.context_id = :contextid)"; + $lineids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id]); + } + + foreach ($lineids as $lineid) { + // List directly enrolled users. + $sql = "SELECT e.user_id as userid FROM {local_treestudyplan_lineuser} e + WHERE ( e.line_id = :lineid )"; + $userlist->add_from_sql('userid',$sql, ["lineid" => $lineid]); + + // And list enrolledby users. + $sql = "SELECT e.enrolledby as userid FROM {local_treestudyplan_lineuser} e + WHERE ( e.line_id = :lineid AND e.enrolledby IS NOT NULL)"; + $userlist->add_from_sql('userid',$sql, ["lineid" => $lineid]); + } } - - // Add the links to all study plans in this context. - $sql = "SELECT a.user_id as userid FROM {local_treestudyplan_user} a - INNER JOIN {local_treestudyplan} s ON a.studyplan_id = s.id - WHERE ( a.context_id = :contextid ) - "; - $userlist->add_from_sql('userid', $sql, ["contextid" => $context->id]); - - // TODO: FIX THIS WITH ALL OF THE ABOVE TODOS - } /** @@ -384,41 +476,12 @@ class provider implements \core_privacy\local\metadata\provider, * @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; - $context = $userlist->get_context(); $users = $userlist->get_userids(); - list($userinsql, $userinparams) = $DB->get_in_or_equal($users, SQL_PARAMS_NAMED, 'user'); - $planids = []; - if ($context->contextlevel == CONTEXT_SYSTEM) { - // Determine the relevant plan_ids for this context. - $sql = "SELECT s.id FROM {local_treestudyplan} - WHERE ( s.context_id IS NULL OR s.context_id == 0 OR s.context_id = :contextid)) "; - $planids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id ]); - // If plan ids not empty, they will be processed later. - - // Also delete all invitations for these users. - $sql = "user_id {$userinsql}"; - $DB->delete_records_select("local_treestudyplan_invit", $sql, $userinparams); - - } else if ($context->contextlevel == CONTEXT_COURSECAT) { - $sql = "SELECT s.id FROM {local_treestudyplan} - WHERE (s.context_id = :contextid)"; - $planids = $DB->get_fieldset_sql($sql, ["contextid" => $context->id ]); - // If plan ids not empty, they will be processed later. + foreach ($users as $userid) { + static::delete_user_in_context($context,$userid); } - - // Now delete the studyplan associations if relevant. - if (count($planids) > 0 && count($users) > 0) { - - list($planinsql, $planinputparams) = $DB->get_in_or_equal($planids, SQL_PARAMS_NAMED, 'plan'); - $params = $userinparams + $planinputparams; - $sql = "user_id {$userinsql} and studyplan_id {$planinsql}"; - $DB->delete_records_select('local_treestudyplan_user', $sql, $params); - } - - // TODO: FIX THIS WITH ALL OF THE ABOVE TODOS } }