mirror of
https://github.com/moodle/moodle.git
synced 2025-08-04 16:36:37 +02:00
MDL-63497 mod_chat: Add support for removal of context users
This issue is part of the MDL-62560 Epic.
This commit is contained in:
parent
19fc6012cf
commit
464b17b79b
2 changed files with 174 additions and 0 deletions
|
@ -33,9 +33,11 @@ use moodle_recordset;
|
||||||
use stdClass;
|
use stdClass;
|
||||||
use core_privacy\local\metadata\collection;
|
use core_privacy\local\metadata\collection;
|
||||||
use core_privacy\local\request\approved_contextlist;
|
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\contextlist;
|
||||||
use core_privacy\local\request\helper;
|
use core_privacy\local\request\helper;
|
||||||
use core_privacy\local\request\transform;
|
use core_privacy\local\request\transform;
|
||||||
|
use core_privacy\local\request\userlist;
|
||||||
use core_privacy\local\request\writer;
|
use core_privacy\local\request\writer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,6 +50,7 @@ use core_privacy\local\request\writer;
|
||||||
*/
|
*/
|
||||||
class provider implements
|
class provider implements
|
||||||
\core_privacy\local\metadata\provider,
|
\core_privacy\local\metadata\provider,
|
||||||
|
\core_privacy\local\request\core_userlist_provider,
|
||||||
\core_privacy\local\request\plugin\provider {
|
\core_privacy\local\request\plugin\provider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,6 +126,33 @@ class provider implements
|
||||||
return $contextlist;
|
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();
|
||||||
|
|
||||||
|
if (!is_a($context, \context_module::class)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = [
|
||||||
|
'instanceid' => $context->instanceid,
|
||||||
|
'modulename' => 'chat',
|
||||||
|
];
|
||||||
|
|
||||||
|
$sql = "SELECT chm.userid
|
||||||
|
FROM {course_modules} cm
|
||||||
|
JOIN {modules} m ON m.id = cm.module AND m.name = :modulename
|
||||||
|
JOIN {chat} c ON c.id = cm.instance
|
||||||
|
JOIN {chat_messages} chm ON chm.chatid = c.id
|
||||||
|
WHERE cm.id = :instanceid";
|
||||||
|
|
||||||
|
$userlist->add_from_sql('userid', $sql, $params);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export all user data for the specified user, in the specified contexts.
|
* Export all user data for the specified user, in the specified contexts.
|
||||||
*
|
*
|
||||||
|
@ -225,6 +255,28 @@ class provider implements
|
||||||
$DB->delete_records_select('chat_users', $sql, $params);
|
$DB->delete_records_select('chat_users', $sql, $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
$context = $userlist->get_context();
|
||||||
|
$cm = $DB->get_record('course_modules', ['id' => $context->instanceid]);
|
||||||
|
$chat = $DB->get_record('chat', ['id' => $cm->instance]);
|
||||||
|
|
||||||
|
list($userinsql, $userinparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);
|
||||||
|
$params = array_merge(['chatid' => $chat->id], $userinparams);
|
||||||
|
$sql = "chatid = :chatid AND userid {$userinsql}";
|
||||||
|
|
||||||
|
$DB->delete_records_select('chat_messages', $sql, $params);
|
||||||
|
$DB->delete_records_select('chat_messages_current', $sql, $params);
|
||||||
|
$DB->delete_records_select('chat_users', $sql, $params);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a dict of chat IDs mapped to their course module ID.
|
* Return a dict of chat IDs mapped to their course module ID.
|
||||||
*
|
*
|
||||||
|
|
|
@ -29,6 +29,7 @@ global $CFG;
|
||||||
|
|
||||||
use core_privacy\tests\provider_testcase;
|
use core_privacy\tests\provider_testcase;
|
||||||
use core_privacy\local\request\approved_contextlist;
|
use core_privacy\local\request\approved_contextlist;
|
||||||
|
use core_privacy\local\request\approved_userlist;
|
||||||
use core_privacy\local\request\transform;
|
use core_privacy\local\request\transform;
|
||||||
use core_privacy\local\request\writer;
|
use core_privacy\local\request\writer;
|
||||||
use mod_chat\privacy\provider;
|
use mod_chat\privacy\provider;
|
||||||
|
@ -96,6 +97,71 @@ class mod_chat_privacy_testcase extends provider_testcase {
|
||||||
$this->assertTrue(in_array(context_module::instance($chat2a->cmid)->id, $contextids));
|
$this->assertTrue(in_array(context_module::instance($chat2a->cmid)->id, $contextids));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that only users with relevant contexts are fetched.
|
||||||
|
*/
|
||||||
|
public function test_get_users_in_context() {
|
||||||
|
$component = 'mod_chat';
|
||||||
|
$dg = $this->getDataGenerator();
|
||||||
|
$c1 = $dg->create_course();
|
||||||
|
$c2 = $dg->create_course();
|
||||||
|
|
||||||
|
$u1 = $dg->create_user();
|
||||||
|
$u2 = $dg->create_user();
|
||||||
|
|
||||||
|
$chat1a = $dg->create_module('chat', ['course' => $c1]);
|
||||||
|
$chat1b = $dg->create_module('chat', ['course' => $c1]);
|
||||||
|
$chat2a = $dg->create_module('chat', ['course' => $c2]);
|
||||||
|
|
||||||
|
// Logins but no message.
|
||||||
|
$chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1a);
|
||||||
|
|
||||||
|
// Logins and messages.
|
||||||
|
$chatuser = $this->login_user_in_course_chat($u1, $c1, $chat1b);
|
||||||
|
chat_send_chatmessage($chatuser, 'Hello world!');
|
||||||
|
|
||||||
|
// Silent login (no system message).
|
||||||
|
$chatuser = $this->login_user_in_course_chat($u1, $c2, $chat2a, 0, true);
|
||||||
|
|
||||||
|
// Silent login and messages.
|
||||||
|
$chatuser = $this->login_user_in_course_chat($u2, $c1, $chat1b, 0, true);
|
||||||
|
chat_send_chatmessage($chatuser, 'Ça va ?');
|
||||||
|
chat_send_chatmessage($chatuser, 'Moi, ça va.');
|
||||||
|
|
||||||
|
// Silent login and messages.
|
||||||
|
$chatuser = $this->login_user_in_course_chat($u2, $c2, $chat2a);
|
||||||
|
chat_send_chatmessage($chatuser, 'What\'s happening here?');
|
||||||
|
|
||||||
|
$context1a = context_module::instance($chat1a->cmid);
|
||||||
|
$context1b = context_module::instance($chat1b->cmid);
|
||||||
|
$context2a = context_module::instance($chat2a->cmid);
|
||||||
|
|
||||||
|
$userlist1a = new \core_privacy\local\request\userlist($context1a, $component);
|
||||||
|
$userlist1b = new \core_privacy\local\request\userlist($context1b, $component);
|
||||||
|
$userlist2a = new \core_privacy\local\request\userlist($context2a, $component);
|
||||||
|
\mod_chat\privacy\provider::get_users_in_context($userlist1a);
|
||||||
|
\mod_chat\privacy\provider::get_users_in_context($userlist1b);
|
||||||
|
\mod_chat\privacy\provider::get_users_in_context($userlist2a);
|
||||||
|
|
||||||
|
// Ensure correct users are found in relevant contexts.
|
||||||
|
$this->assertCount(1, $userlist1a);
|
||||||
|
$expected = [$u1->id];
|
||||||
|
$actual = $userlist1a->get_userids();
|
||||||
|
$this->assertEquals($expected, $actual);
|
||||||
|
|
||||||
|
$this->assertCount(2, $userlist1b);
|
||||||
|
$expected = [$u1->id, $u2->id];
|
||||||
|
$actual = $userlist1b->get_userids();
|
||||||
|
sort($expected);
|
||||||
|
sort($actual);
|
||||||
|
$this->assertEquals($expected, $actual);
|
||||||
|
|
||||||
|
$this->assertCount(1, $userlist2a);
|
||||||
|
$expected = [$u1->id];
|
||||||
|
$actual = $userlist1a->get_userids();
|
||||||
|
$this->assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_delete_data_for_all_users_in_context() {
|
public function test_delete_data_for_all_users_in_context() {
|
||||||
global $DB;
|
global $DB;
|
||||||
$dg = $this->getDataGenerator();
|
$dg = $this->getDataGenerator();
|
||||||
|
@ -190,6 +256,62 @@ class mod_chat_privacy_testcase extends provider_testcase {
|
||||||
$this->assert_has_no_data_in_chat($u2, $chat1b);
|
$this->assert_has_no_data_in_chat($u2, $chat1b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that data for users in approved userlist is deleted.
|
||||||
|
*/
|
||||||
|
public function test_delete_data_for_users() {
|
||||||
|
global $DB;
|
||||||
|
$component = 'mod_chat';
|
||||||
|
$dg = $this->getDataGenerator();
|
||||||
|
$c1 = $dg->create_course();
|
||||||
|
|
||||||
|
$u1 = $dg->create_user();
|
||||||
|
$u2 = $dg->create_user();
|
||||||
|
$u3 = $dg->create_user();
|
||||||
|
|
||||||
|
$chat1 = $dg->create_module('chat', ['course' => $c1]);
|
||||||
|
$chat1context = context_module::instance($chat1->cmid);
|
||||||
|
|
||||||
|
$u1chat1 = $this->login_user_in_course_chat($u1, $c1, $chat1);
|
||||||
|
$u2chat1 = $this->login_user_in_course_chat($u2, $c1, $chat1);
|
||||||
|
$u3chat1 = $this->login_user_in_course_chat($u3, $c1, $chat1);
|
||||||
|
chat_send_chatmessage($u1chat1, 'Ça va ?');
|
||||||
|
chat_send_chatmessage($u2chat1, 'Oui, et toi ?');
|
||||||
|
chat_send_chatmessage($u1chat1, 'Bien merci.');
|
||||||
|
chat_send_chatmessage($u2chat1, 'Pourquoi ils disent omelette "du" fromage ?!');
|
||||||
|
chat_send_chatmessage($u1chat1, 'Aucune idée');
|
||||||
|
chat_send_chatmessage($u3chat1, 'Je ne comprends pas');
|
||||||
|
$this->assert_has_data_in_chat($u1, $chat1);
|
||||||
|
$this->assert_has_data_in_chat($u2, $chat1);
|
||||||
|
$this->assert_has_data_in_chat($u3, $chat1);
|
||||||
|
|
||||||
|
$chat2 = $dg->create_module('chat', ['course' => $c1]);
|
||||||
|
|
||||||
|
$u1chat2 = $this->login_user_in_course_chat($u1, $c1, $chat2);
|
||||||
|
$u2chat2 = $this->login_user_in_course_chat($u2, $c1, $chat2);
|
||||||
|
$u3chat2 = $this->login_user_in_course_chat($u3, $c1, $chat2);
|
||||||
|
chat_send_chatmessage($u1chat2, 'Why do we have a separate chat?');
|
||||||
|
chat_send_chatmessage($u2chat2, 'I have no idea!');
|
||||||
|
chat_send_chatmessage($u3chat2, 'Me either.');
|
||||||
|
$this->assert_has_data_in_chat($u1, $chat2);
|
||||||
|
$this->assert_has_data_in_chat($u2, $chat2);
|
||||||
|
$this->assert_has_data_in_chat($u3, $chat2);
|
||||||
|
|
||||||
|
// Delete user 1 and 2 data from chat 1 context only.
|
||||||
|
$approveduserids = [$u1->id, $u2->id];
|
||||||
|
$approvedlist = new approved_userlist($chat1context, $component, $approveduserids);
|
||||||
|
provider::delete_data_for_users($approvedlist);
|
||||||
|
|
||||||
|
// Ensure correct chat data is deleted.
|
||||||
|
$this->assert_has_no_data_in_chat($u1, $chat1);
|
||||||
|
$this->assert_has_no_data_in_chat($u2, $chat1);
|
||||||
|
$this->assert_has_data_in_chat($u3, $chat1);
|
||||||
|
|
||||||
|
$this->assert_has_data_in_chat($u1, $chat2);
|
||||||
|
$this->assert_has_data_in_chat($u2, $chat2);
|
||||||
|
$this->assert_has_data_in_chat($u3, $chat2);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_export_data_for_user() {
|
public function test_export_data_for_user() {
|
||||||
global $DB;
|
global $DB;
|
||||||
$dg = $this->getDataGenerator();
|
$dg = $this->getDataGenerator();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue