MDL-63712 core_message: support removal of multiple users in a context
This issue is a part of the MDL-62560 Epic.
This commit is contained in:
committed by
Michael Hawkins
parent
734d9f403b
commit
23d4767f8c
@@ -18,6 +18,7 @@
|
||||
* 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
|
||||
*/
|
||||
@@ -25,8 +26,10 @@ 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();
|
||||
@@ -40,7 +43,8 @@ defined('MOODLE_INTERNAL') || die();
|
||||
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.
|
||||
@@ -163,6 +167,39 @@ class provider implements
|
||||
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 bellow 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).
|
||||
|
||||
$hasdata = false;
|
||||
$hasdata = $hasdata || $DB->record_exists_select('message', 'useridfrom = ? OR ( notification = 1 AND useridto = ?)',
|
||||
[$userid, $userid]);
|
||||
$hasdata = $hasdata || $DB->record_exists_select('message_read', 'useridfrom = ? OR ( notification = 1 AND useridto = ?)',
|
||||
[$userid, $userid]);
|
||||
$hasdata = $hasdata || $DB->record_exists_select('message_contacts', 'userid = ? OR contactid = ?', [$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.
|
||||
*
|
||||
@@ -229,6 +266,30 @@ class provider implements
|
||||
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.
|
||||
*
|
||||
|
||||
@@ -582,6 +582,165 @@ class core_message_privacy_provider_testcase extends \core_privacy\tests\provide
|
||||
$this->assertEquals($n4, $notificationsread->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::get_users_in_context() when there is no message or notification.
|
||||
*/
|
||||
public function test_get_users_in_context_no_data() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$usercontext = context_user::instance($user->id);
|
||||
|
||||
$userlist = new \core_privacy\local\request\userlist($usercontext, 'core_message');
|
||||
\core_message\privacy\provider::get_users_in_context($userlist);
|
||||
|
||||
$this->assertEmpty($userlist->get_userids());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::get_users_in_context() when there is a message between users.
|
||||
*/
|
||||
public function test_get_users_in_context_with_message() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
|
||||
$user1context = context_user::instance($user1->id);
|
||||
$user2context = context_user::instance($user2->id);
|
||||
|
||||
$this->create_message_or_notification($user1->id, $user2->id, time() - (9 * DAYSECS));
|
||||
|
||||
// Test for the sender.
|
||||
$userlist = new \core_privacy\local\request\userlist($user1context, 'core_message');
|
||||
\core_message\privacy\provider::get_users_in_context($userlist);
|
||||
$this->assertCount(1, $userlist);
|
||||
$userincontext = $userlist->current();
|
||||
$this->assertEquals($user1->id, $userincontext->id);
|
||||
|
||||
// Test for the receiver.
|
||||
$userlist = new \core_privacy\local\request\userlist($user2context, 'core_message');
|
||||
\core_message\privacy\provider::get_users_in_context($userlist);
|
||||
$this->assertCount(0, $userlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::get_users_in_context() when there is a notification between users.
|
||||
*/
|
||||
public function test_get_users_in_context_with_notification() {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
|
||||
$user1context = context_user::instance($user1->id);
|
||||
$user2context = context_user::instance($user2->id);
|
||||
|
||||
$this->create_message_or_notification($user1->id, $user2->id, time() - (9 * DAYSECS), true);
|
||||
|
||||
// Test for the sender.
|
||||
$userlist = new \core_privacy\local\request\userlist($user1context, 'core_message');
|
||||
\core_message\privacy\provider::get_users_in_context($userlist);
|
||||
$this->assertCount(1, $userlist);
|
||||
$userincontext = $userlist->current();
|
||||
$this->assertEquals($user1->id, $userincontext->id);
|
||||
|
||||
// Test for the receiver.
|
||||
$userlist = new \core_privacy\local\request\userlist($user2context, 'core_message');
|
||||
\core_message\privacy\provider::get_users_in_context($userlist);
|
||||
$this->assertCount(1, $userlist);
|
||||
$userincontext = $userlist->current();
|
||||
$this->assertEquals($user2->id, $userincontext->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for provider::delete_data_for_users().
|
||||
*/
|
||||
public function test_delete_data_for_users() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest();
|
||||
|
||||
// Create users to test with.
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
$user3 = $this->getDataGenerator()->create_user();
|
||||
|
||||
$now = time();
|
||||
$timeread = $now - DAYSECS;
|
||||
|
||||
// Create contacts.
|
||||
message_add_contact($user1->id, 0, $user2->id);
|
||||
message_add_contact($user2->id, 0, $user1->id);
|
||||
message_add_contact($user2->id, 0, $user3->id);
|
||||
|
||||
// Create messages.
|
||||
$m1 = $this->create_message_or_notification($user1->id, $user2->id, $now + (9 * DAYSECS), false, $timeread);
|
||||
$m2 = $this->create_message_or_notification($user2->id, $user1->id, $now + (8 * DAYSECS));
|
||||
$m3 = $this->create_message_or_notification($user2->id, $user1->id, $now + (7 * DAYSECS), false, $timeread);
|
||||
$m4 = $this->create_message_or_notification($user1->id, $user2->id, $now + (6 * DAYSECS));
|
||||
|
||||
// Create notifications.
|
||||
$n1 = $this->create_message_or_notification($user1->id, $user2->id, $now + (9 * DAYSECS), true, $timeread);
|
||||
$n2 = $this->create_message_or_notification($user2->id, $user1->id, $now + (8 * DAYSECS), true);
|
||||
$n3 = $this->create_message_or_notification($user2->id, $user3->id, $now + (8 * DAYSECS), true);
|
||||
$n4 = $this->create_message_or_notification($user3->id, $user2->id, $now + (8 * DAYSECS), true, $timeread);
|
||||
|
||||
// Delete one of the messages.
|
||||
$dbm2 = $DB->get_record('message', ['id' => $m2]);
|
||||
message_delete_message($dbm2, $user1->id);
|
||||
|
||||
// There should be three contacts.
|
||||
$this->assertEquals(3, $DB->count_records('message_contacts'));
|
||||
|
||||
// There should be two unread messages.
|
||||
$this->assertEquals(2, $DB->count_records('message', ['notification' => 0]));
|
||||
|
||||
// There should be two read messages.
|
||||
$this->assertEquals(2, $DB->count_records('message_read', ['notification' => 0]));
|
||||
|
||||
// There should be two unread notifications.
|
||||
$this->assertEquals(2, $DB->count_records('message', ['notification' => 1]));
|
||||
|
||||
// There should be two read notifications.
|
||||
$this->assertEquals(2, $DB->count_records('message_read', ['notification' => 1]));
|
||||
|
||||
$user1context = context_user::instance($user1->id);
|
||||
$approveduserlist = new \core_privacy\local\request\approved_userlist($user1context, 'core_message',
|
||||
[$user1->id, $user2->id]);
|
||||
provider::delete_data_for_users($approveduserlist);
|
||||
|
||||
// Only user1's data should be deleted. User2 should be skipped as user2 is an invalid user for user1context.
|
||||
|
||||
// Confirm the user 2 data still exists.
|
||||
$contacts = $DB->get_records('message_contacts');
|
||||
$messages = $DB->get_records('message', ['notification' => 0]);
|
||||
$messagesread = $DB->get_records('message_read', ['notification' => 0]);
|
||||
$notifications = $DB->get_records('message', ['notification' => 1]);
|
||||
$notificationsread = $DB->get_records('message_read', ['notification' => 1]);
|
||||
|
||||
$this->assertCount(1, $contacts);
|
||||
$contact = reset($contacts);
|
||||
$this->assertEquals($user3->id, $contact->userid);
|
||||
$this->assertEquals($user2->id, $contact->contactid);
|
||||
|
||||
$this->assertCount(1, $messages);
|
||||
$message = reset($messages);
|
||||
$this->assertEquals($m2, $message->id);
|
||||
|
||||
$this->assertCount(1, $messagesread);
|
||||
$messagesread = reset($messagesread);
|
||||
$this->assertEquals($m3, $messagesread->id);
|
||||
|
||||
$this->assertCount(1, $notifications);
|
||||
$notifications = reset($notifications);
|
||||
$this->assertEquals($n3, $notifications->id);
|
||||
|
||||
$this->assertCount(1, $notificationsread);
|
||||
$notificationsread = reset($notificationsread);
|
||||
$this->assertEquals($n4, $notificationsread->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a message or notification to be used for testing.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user