Skip to content

Commit

Permalink
Merge branch 'MDL-63712-master' of git://github.com/mickhawkins/moodle
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewnicols committed Nov 5, 2018
2 parents 65c8a8a + b8bbef0 commit e4384a6
Show file tree
Hide file tree
Showing 2 changed files with 687 additions and 65 deletions.
148 changes: 117 additions & 31 deletions message/classes/privacy/provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@
* Privacy Subsystem implementation for core_message.
*
* @package core_message
* @category privacy
* @copyright 2018 Mark Nelson <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_message\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();
Expand All @@ -40,7 +43,8 @@
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\subsystem\provider,
\core_privacy\local\request\user_preference_provider {
\core_privacy\local\request\user_preference_provider,
\core_privacy\local\request\core_userlist_provider {

/**
* Return the fields which contain personal data.
Expand Down Expand Up @@ -175,13 +179,72 @@ public static function export_user_preferences(int $userid) {
* @return contextlist the list of contexts containing user info for the user.
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
// Messages are in the system context.
global $DB;

$contextlist = new contextlist();
$contextlist->add_system_context();

// Messages are in the user context.
// For the sake of performance, there is no need to call add_from_sql for each of the below cases.
// It is enough to add the user's context as soon as we come to the conclusion that the user has some data.
// Also, the order of checking is sorted by the probability of occurrence (just by guess).
// There is no need to check the message_user_actions table, as there needs to be a message in order to be a message action.
// So, checking messages table would suffice.

$hasdata = false;
$hasdata = $hasdata || $DB->record_exists_select('notifications', 'useridfrom = ? OR useridto = ?', [$userid, $userid]);
$hasdata = $hasdata || $DB->record_exists('message_conversation_members', ['userid' => $userid]);
$hasdata = $hasdata || $DB->record_exists('messages', ['useridfrom' => $userid]);
$hasdata = $hasdata || $DB->record_exists_select('message_contacts', 'userid = ? OR contactid = ?', [$userid, $userid]);
$hasdata = $hasdata || $DB->record_exists_select('message_users_blocked', 'userid = ? OR blockeduserid = ?',
[$userid, $userid]);
$hasdata = $hasdata || $DB->record_exists_select('message_contact_requests', 'userid = ? OR requesteduserid = ?',
[$userid, $userid]);

if ($hasdata) {
$contextlist->add_user_context($userid);
}

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) {
global $DB;

$context = $userlist->get_context();

if (!$context instanceof \context_user) {
return;
}

$userid = $context->instanceid;

// Messages are in the user context.
// For the sake of performance, there is no need to call add_from_sql for each of the below cases.
// It is enough to add the user's context as soon as we come to the conclusion that the user has some data.
// Also, the order of checking is sorted by the probability of occurrence (just by guess).
// There is no need to check the message_user_actions table, as there needs to be a message in order to be a message action.
// So, checking messages table would suffice.

$hasdata = false;
$hasdata = $hasdata || $DB->record_exists_select('notifications', 'useridfrom = ? OR useridto = ?', [$userid, $userid]);
$hasdata = $hasdata || $DB->record_exists('message_conversation_members', ['userid' => $userid]);
$hasdata = $hasdata || $DB->record_exists('messages', ['useridfrom' => $userid]);
$hasdata = $hasdata || $DB->record_exists_select('message_contacts', 'userid = ? OR contactid = ?', [$userid, $userid]);
$hasdata = $hasdata || $DB->record_exists_select('message_users_blocked', 'userid = ? OR blockeduserid = ?',
[$userid, $userid]);
$hasdata = $hasdata || $DB->record_exists_select('message_contact_requests', 'userid = ? OR requesteduserid = ?',
[$userid, $userid]);

if ($hasdata) {
$userlist->add_user($userid);
}
}

/**
* Export personal data for the given approved_contextlist. User and context information is contained within the contextlist.
*
Expand All @@ -192,17 +255,17 @@ public static function export_user_data(approved_contextlist $contextlist) {
return;
}

// Remove non-system contexts. If it ends up empty then early return.
$contexts = array_filter($contextlist->get_contexts(), function($context) {
return $context->contextlevel == CONTEXT_SYSTEM;
$userid = $contextlist->get_user()->id;

// Remove non-user and invalid contexts. If it ends up empty then early return.
$contexts = array_filter($contextlist->get_contexts(), function($context) use($userid) {
return $context->contextlevel == CONTEXT_USER && $context->instanceid == $userid;
});

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

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

// Export the contacts.
self::export_user_data_contacts($userid);

Expand All @@ -225,19 +288,9 @@ public static function export_user_data(approved_contextlist $contextlist) {
* @param \context $context the context to delete in.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
global $DB;

if (!$context instanceof \context_system) {
return;
if ($context instanceof \context_user) {
static::delete_user_data($context->instanceid);
}

$DB->delete_records('messages');
$DB->delete_records('message_user_actions');
$DB->delete_records('message_conversation_members');
$DB->delete_records('message_contacts');
$DB->delete_records('message_contact_requests');
$DB->delete_records('message_users_blocked');
$DB->delete_records('notifications');
}

/**
Expand All @@ -246,22 +299,55 @@ public static function delete_data_for_all_users_in_context(\context $context) {
* @param approved_contextlist $contextlist a list of contexts approved for deletion.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
global $DB;

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

// Remove non-system contexts. If it ends up empty then early return.
$contexts = array_filter($contextlist->get_contexts(), function($context) {
return $context->contextlevel == CONTEXT_SYSTEM;
$userid = $contextlist->get_user()->id;

// Remove non-user and invalid contexts. If it ends up empty then early return.
$contexts = array_filter($contextlist->get_contexts(), function($context) use($userid) {
return $context->contextlevel == CONTEXT_USER && $context->instanceid == $userid;
});

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

$userid = $contextlist->get_user()->id;
static::delete_user_data($userid);
}

/**
* 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) {
return;
}

// Remove invalid users. If it ends up empty then early return.
$userids = array_filter($userlist->get_userids(), function($userid) use($context) {
return $context->instanceid == $userid;
});

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

static::delete_user_data($context->instanceid);
}

/**
* Delete all user data for the specified user.
*
* @param int $userid The user id
*/
protected static function delete_user_data(int $userid) {
global $DB;

$DB->delete_records('messages', ['useridfrom' => $userid]);
$DB->delete_records('message_user_actions', ['userid' => $userid]);
Expand All @@ -280,7 +366,7 @@ public static function delete_data_for_user(approved_contextlist $contextlist) {
protected static function export_user_data_contacts(int $userid) {
global $DB;

$context = \context_system::instance();
$context = \context_user::instance($userid);

// Get the user's contacts.
if ($contacts = $DB->get_records_select('message_contacts', 'userid = ? OR contactid = ?', [$userid, $userid], 'id ASC')) {
Expand All @@ -302,7 +388,7 @@ protected static function export_user_data_contacts(int $userid) {
protected static function export_user_data_contact_requests(int $userid) {
global $DB;

$context = \context_system::instance();
$context = \context_user::instance($userid);

if ($contactrequests = $DB->get_records_select('message_contact_requests', 'userid = ? OR requesteduserid = ?',
[$userid, $userid], 'id ASC')) {
Expand Down Expand Up @@ -334,7 +420,7 @@ protected static function export_user_data_contact_requests(int $userid) {
protected static function export_user_data_blocked_users(int $userid) {
global $DB;

$context = \context_system::instance();
$context = \context_user::instance($userid);

if ($blockedusers = $DB->get_records('message_users_blocked', ['userid' => $userid], 'id ASC')) {
$blockedusersdata = [];
Expand All @@ -355,7 +441,7 @@ protected static function export_user_data_blocked_users(int $userid) {
protected static function export_user_data_messages(int $userid) {
global $DB;

$context = \context_system::instance();
$context = \context_user::instance($userid);

$sql = "SELECT DISTINCT mcm.conversationid as id
FROM {message_conversation_members} mcm
Expand Down Expand Up @@ -427,7 +513,7 @@ protected static function export_user_data_messages(int $userid) {
protected static function export_user_data_notifications(int $userid) {
global $DB;

$context = \context_system::instance();
$context = \context_user::instance($userid);

$notificationdata = [];
$select = "useridfrom = ? OR useridto = ?";
Expand Down
Loading

0 comments on commit e4384a6

Please sign in to comment.