* @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;
}
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);
* @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');
}
/**
* @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 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]);
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')) {
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')) {
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 = [];
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
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 = ?";
}
/**
- * Test for provider::get_contexts_for_userid().
+ * Test for provider::get_contexts_for_userid() when there is no message or notification.
*/
- public function test_get_contexts_for_userid() {
+ public function test_get_contexts_for_userid_no_data() {
$this->resetAfterTest();
$user = $this->getDataGenerator()->create_user();
$contextlist = provider::get_contexts_for_userid($user->id);
+ $this->assertEmpty($contextlist);
+ }
+
+ /**
+ * Test for provider::get_contexts_for_userid() when there is a message between users.
+ */
+ public function test_get_contexts_for_userid_with_message() {
+ $this->resetAfterTest();
+
+ $user1 = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+
+ $this->create_message($user1->id, $user2->id, time() - (9 * DAYSECS));
+
+ // Test for the sender.
+ $contextlist = provider::get_contexts_for_userid($user1->id);
+ $this->assertCount(1, $contextlist);
+ $contextforuser = $contextlist->current();
+ $this->assertEquals(
+ context_user::instance($user1->id)->id,
+ $contextforuser->id);
+
+ // Test for the receiver.
+ $contextlist = provider::get_contexts_for_userid($user2->id);
+ $this->assertCount(1, $contextlist);
+ $contextforuser = $contextlist->current();
+ $this->assertEquals(
+ context_user::instance($user2->id)->id,
+ $contextforuser->id);
+ }
+
+ /**
+ * Test for provider::get_contexts_for_userid() when there is a notification between users.
+ */
+ public function test_get_contexts_for_userid_with_notification() {
+ $this->resetAfterTest();
+
+ $user1 = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+
+ $this->create_notification($user1->id, $user2->id, time() - (9 * DAYSECS));
+
+ // Test for the sender.
+ $contextlist = provider::get_contexts_for_userid($user1->id);
+ $this->assertCount(1, $contextlist);
+ $contextforuser = $contextlist->current();
+ $this->assertEquals(
+ context_user::instance($user1->id)->id,
+ $contextforuser->id);
+
+ // Test for the receiver.
+ $contextlist = provider::get_contexts_for_userid($user2->id);
$this->assertCount(1, $contextlist);
$contextforuser = $contextlist->current();
- $this->assertEquals(SYSCONTEXTID, $contextforuser->id);
+ $this->assertEquals(
+ context_user::instance($user2->id)->id,
+ $contextforuser->id);
}
/**
\core_message\api::add_contact($user1->id, $user3->id);
\core_message\api::add_contact($user1->id, $user4->id);
- $this->export_context_data_for_user($user1->id, \context_system::instance(), 'core_message');
+ $user1context = context_user::instance($user1->id);
- $writer = writer::with_context(\context_system::instance());
+ $this->export_context_data_for_user($user1->id, $user1context, 'core_message');
+
+ $writer = writer::with_context($user1context);
$contacts = (array) $writer->get_data([get_string('contacts', 'core_message')]);
usort($contacts, ['static', 'sort_contacts']);
\core_message\api::create_contact_request($user3->id, $user1->id);
\core_message\api::create_contact_request($user1->id, $user4->id);
- $this->export_context_data_for_user($user1->id, \context_system::instance(), 'core_message');
+ $user1context = context_user::instance($user1->id);
- $writer = writer::with_context(\context_system::instance());
+ $this->export_context_data_for_user($user1->id, $user1context, 'core_message');
+
+ $writer = writer::with_context($user1context);
$contactrequests = (array) $writer->get_data([get_string('contactrequests', 'core_message')]);
\core_message\api::block_user($user1->id, $user3->id);
\core_message\api::block_user($user1->id, $user4->id);
- $this->export_context_data_for_user($user1->id, \context_system::instance(), 'core_message');
+ $user1context = context_user::instance($user1->id);
- $writer = writer::with_context(\context_system::instance());
+ $this->export_context_data_for_user($user1->id, $user1context, 'core_message');
+
+ $writer = writer::with_context($user1context);
$blockedusers = (array) $writer->get_data([get_string('blockedusers', 'core_message')]);
\core_message\api::delete_message($user1->id, $m2);
\core_message\api::delete_message($user1->id, $m5);
- $this->export_context_data_for_user($user1->id, \context_system::instance(), 'core_message');
+ $user1context = context_user::instance($user1->id);
- $writer = writer::with_context(\context_system::instance());
+ $this->export_context_data_for_user($user1->id, $user1context, 'core_message');
+
+ $writer = writer::with_context($user1context);
$this->assertTrue($writer->has_any_data());
$this->create_notification($user2->id, $user3->id, $now + (2 * DAYSECS));
$this->create_notification($user3->id, $user2->id, $now + (1 * DAYSECS));
- $this->export_context_data_for_user($user1->id, \context_system::instance(), 'core_message');
+ $user1context = context_user::instance($user1->id);
- $writer = writer::with_context(\context_system::instance());
+ $this->export_context_data_for_user($user1->id, $user1context, 'core_message');
+
+ $writer = writer::with_context($user1context);
$this->assertTrue($writer->has_any_data());
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
+ $user5 = $this->getDataGenerator()->create_user();
$now = time();
$timeread = $now - DAYSECS;
- $systemcontext = \context_system::instance();
+ $user1context = context_user::instance($user1->id);
// Create contacts.
\core_message\api::add_contact($user1->id, $user2->id);
+ \core_message\api::add_contact($user2->id, $user3->id);
// Create contact requests.
\core_message\api::create_contact_request($user1->id, $user3->id);
+ \core_message\api::create_contact_request($user2->id, $user4->id);
// Block a user.
\core_message\api::block_user($user1->id, $user3->id);
+ \core_message\api::block_user($user3->id, $user4->id);
// Create messages.
$m1 = $this->create_message($user1->id, $user2->id, $now + (9 * DAYSECS), true);
$m2 = $this->create_message($user2->id, $user1->id, $now + (8 * DAYSECS));
+ $m3 = $this->create_message($user2->id, $user3->id, $now + (7 * DAYSECS));
// Create notifications.
$n1 = $this->create_notification($user1->id, $user2->id, $now + (9 * DAYSECS), $timeread);
$n2 = $this->create_notification($user2->id, $user1->id, $now + (8 * DAYSECS));
+ $n3 = $this->create_notification($user2->id, $user3->id, $now + (7 * DAYSECS));
// Delete one of the messages.
\core_message\api::delete_message($user1->id, $m2);
- // There should be 1 contact.
- $this->assertEquals(1, $DB->count_records('message_contacts'));
+ // There should be 2 contacts.
+ $this->assertEquals(2, $DB->count_records('message_contacts'));
- // There should be 1 contact request.
- $this->assertEquals(1, $DB->count_records('message_contact_requests'));
+ // There should be 2 contact requests.
+ $this->assertEquals(2, $DB->count_records('message_contact_requests'));
- // There should be 1 blocked user.
- $this->assertEquals(1, $DB->count_records('message_users_blocked'));
+ // There should be 2 blocked users.
+ $this->assertEquals(2, $DB->count_records('message_users_blocked'));
- // There should be two messages.
- $this->assertEquals(2, $DB->count_records('messages'));
+ // There should be 3 messages.
+ $this->assertEquals(3, $DB->count_records('messages'));
- // There should be two user actions - one for reading the message, one for deleting.
+ // There should be 2 user actions - one for reading the message, one for deleting.
$this->assertEquals(2, $DB->count_records('message_user_actions'));
- // There should be two conversation members.
- $this->assertEquals(2, $DB->count_records('message_conversation_members'));
+ // There should be 4 conversation members.
+ $this->assertEquals(4, $DB->count_records('message_conversation_members'));
- // There should be two notifications + one for the contact request.
- $this->assertEquals(3, $DB->count_records('notifications'));
+ // There should be 3 notifications + 2 for the contact request.
+ $this->assertEquals(5, $DB->count_records('notifications'));
- provider::delete_data_for_all_users_in_context($systemcontext);
+ provider::delete_data_for_all_users_in_context($user1context);
- // Confirm all has been deleted.
- $this->assertEquals(0, $DB->count_records('message_contacts'));
- $this->assertEquals(0, $DB->count_records('message_contact_requests'));
- $this->assertEquals(0, $DB->count_records('message_users_blocked'));
- $this->assertEquals(0, $DB->count_records('messages'));
- $this->assertEquals(0, $DB->count_records('message_user_actions'));
- $this->assertEquals(0, $DB->count_records('message_conversation_members'));
- $this->assertEquals(0, $DB->count_records('notifications'));
+ // Confirm there is only 1 contact left.
+ $this->assertEquals(1, $DB->count_records('message_contacts'));
+ // And it is not related to user1.
+ $this->assertEquals(0,
+ $DB->count_records_select('message_contacts', 'userid = ? OR contactid = ?', [$user1->id, $user1->id]));
+
+ // Confirm there is only 1 contact request left.
+ $this->assertEquals(1, $DB->count_records('message_contact_requests'));
+ // And it is not related to user1.
+ $this->assertEquals(0,
+ $DB->count_records_select('message_contact_requests', 'userid = ? OR requesteduserid = ?',
+ [$user1->id, $user1->id]));
+
+ // Confirm there is only 1 blocked user left.
+ $this->assertEquals(1, $DB->count_records('message_users_blocked'));
+ // And it is not related to user1.
+ $this->assertEquals(0,
+ $DB->count_records_select('message_users_blocked', 'userid = ? OR blockeduserid = ?', [$user1->id, $user1->id]));
+
+ // Confirm there are only 2 messages left.
+ $this->assertEquals(2, $DB->count_records('messages'));
+ // And none of them are from user1.
+ $this->assertEquals(0, $DB->count_records('messages', ['useridfrom' => $user1->id]));
+
+ // Confirm there is only 1 user action left - the one that is for user2 reading the message.
+ $this->assertEquals(1, $DB->count_records('message_user_actions'));
+ // And it is not for user1.
+ $this->assertEquals(0, $DB->count_records('message_user_actions', ['userid' => $user1->id]));
+
+ // Confirm there are only 3 conversation members left.
+ $this->assertEquals(3, $DB->count_records('message_conversation_members'));
+ // And user1 is not in any conversation.
+ $this->assertEquals(0, $DB->count_records('message_conversation_members', ['userid' => $user1->id]));
+
+ // Confirm there is only 1 notification + 1 for the contact request.
+ $this->assertEquals(2, $DB->count_records('notifications'));
+ // And it is not related to user1.
+ $this->assertEquals(0,
+ $DB->count_records_select('notifications', 'useridfrom = ? OR useridto = ? ', [$user1->id, $user1->id]));
}
/**
// There should be three notifications + two for the contact requests.
$this->assertEquals(5, $DB->count_records('notifications'));
- $systemcontext = \context_system::instance();
+ $user1context = context_user::instance($user1->id);
$contextlist = new \core_privacy\local\request\approved_contextlist($user1, 'core_message',
- [$systemcontext->id]);
+ [$user1context->id]);
provider::delete_data_for_user($contextlist);
// Confirm the user 2 data still exists.