mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
MDL-63606 core_badges: Add support for removal of context users
This issue is part of the MDL-62560 Epic.
This commit is contained in:
parent
448bd578d8
commit
541982c01e
@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
namespace core_badges\privacy;
|
namespace core_badges\privacy;
|
||||||
|
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
use badge;
|
use badge;
|
||||||
@ -37,6 +38,8 @@ 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\transform;
|
use core_privacy\local\request\transform;
|
||||||
use core_privacy\local\request\writer;
|
use core_privacy\local\request\writer;
|
||||||
|
use core_privacy\local\request\userlist;
|
||||||
|
use core_privacy\local\request\approved_userlist;
|
||||||
|
|
||||||
require_once($CFG->libdir . '/badgeslib.php');
|
require_once($CFG->libdir . '/badgeslib.php');
|
||||||
|
|
||||||
@ -50,6 +53,7 @@ require_once($CFG->libdir . '/badgeslib.php');
|
|||||||
*/
|
*/
|
||||||
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\subsystem\provider {
|
\core_privacy\local\request\subsystem\provider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -173,6 +177,78 @@ class provider implements
|
|||||||
return $contextlist;
|
return $contextlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of users within a specific 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();
|
||||||
|
|
||||||
|
$allowedcontexts = [
|
||||||
|
CONTEXT_COURSE,
|
||||||
|
CONTEXT_SYSTEM,
|
||||||
|
CONTEXT_USER
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!in_array($context->contextlevel, $allowedcontexts)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($context->contextlevel == CONTEXT_COURSE || $context->contextlevel == CONTEXT_SYSTEM) {
|
||||||
|
// Find the modifications we made on badges (course & system).
|
||||||
|
$params = [
|
||||||
|
'courselevel' => CONTEXT_COURSE,
|
||||||
|
'syscontextid' => SYSCONTEXTID,
|
||||||
|
'typecourse' => BADGE_TYPE_COURSE,
|
||||||
|
'typesite' => BADGE_TYPE_SITE,
|
||||||
|
'contextid' => $context->id,
|
||||||
|
];
|
||||||
|
|
||||||
|
$sql = "SELECT b.usermodified, b.usercreated
|
||||||
|
FROM {badge} b
|
||||||
|
JOIN {context} ctx
|
||||||
|
ON (b.type = :typecourse AND b.courseid = ctx.instanceid AND ctx.contextlevel = :courselevel)
|
||||||
|
OR (b.type = :typesite AND ctx.id = :syscontextid)
|
||||||
|
WHERE ctx.id = :contextid";
|
||||||
|
|
||||||
|
$userlist->add_from_sql('usermodified', $sql, $params);
|
||||||
|
$userlist->add_from_sql('usercreated', $sql, $params);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($context->contextlevel == CONTEXT_USER) {
|
||||||
|
// Find where we've manually awarded a badge (recipient user context).
|
||||||
|
$params = [
|
||||||
|
'instanceid' => $context->instanceid
|
||||||
|
];
|
||||||
|
|
||||||
|
$sql = "SELECT issuerid, recipientid
|
||||||
|
FROM {badge_manual_award}
|
||||||
|
WHERE recipientid = :instanceid";
|
||||||
|
|
||||||
|
$userlist->add_from_sql('issuerid', $sql, $params);
|
||||||
|
$userlist->add_from_sql('recipientid', $sql, $params);
|
||||||
|
|
||||||
|
$sql = "SELECT userid
|
||||||
|
FROM {badge_issued}
|
||||||
|
WHERE userid = :instanceid";
|
||||||
|
|
||||||
|
$userlist->add_from_sql('userid', $sql, $params);
|
||||||
|
|
||||||
|
$sql = "SELECT userid
|
||||||
|
FROM {badge_criteria_met}
|
||||||
|
WHERE userid = :instanceid";
|
||||||
|
|
||||||
|
$userlist->add_from_sql('userid', $sql, $params);
|
||||||
|
|
||||||
|
$sql = "SELECT userid
|
||||||
|
FROM {badge_backpack}
|
||||||
|
WHERE userid = :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.
|
||||||
*
|
*
|
||||||
@ -439,6 +515,24 @@ class provider implements
|
|||||||
static::delete_user_data($context->instanceid);
|
static::delete_user_data($context->instanceid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 (!in_array($context->instanceid, $userlist->get_userids())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($context->contextlevel == CONTEXT_USER) {
|
||||||
|
// We can only delete our own data in the user context, nothing in course or system.
|
||||||
|
static::delete_user_data($context->instanceid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete all user data for the specified user, in the specified contexts.
|
* Delete all user data for the specified user, in the specified contexts.
|
||||||
*
|
*
|
||||||
|
@ -32,6 +32,7 @@ use core_privacy\local\request\approved_contextlist;
|
|||||||
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 core_badges\privacy\provider;
|
use core_badges\privacy\provider;
|
||||||
|
use core_privacy\local\request\approved_userlist;
|
||||||
|
|
||||||
require_once($CFG->libdir . '/badgeslib.php');
|
require_once($CFG->libdir . '/badgeslib.php');
|
||||||
|
|
||||||
@ -399,6 +400,177 @@ class core_badges_privacy_testcase extends provider_testcase {
|
|||||||
$this->assertEquals('Manager', $data->badges[0]['issuer_role']);
|
$this->assertEquals('Manager', $data->badges[0]['issuer_role']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that only users within a user, system and course context are fetched.
|
||||||
|
*/
|
||||||
|
public function test_get_users_in_context() {
|
||||||
|
$component = 'core_badges';
|
||||||
|
|
||||||
|
// Create course1.
|
||||||
|
$course1 = $this->getDataGenerator()->create_course();
|
||||||
|
$coursecontext1 = context_course::instance($course1->id);
|
||||||
|
// Create course2.
|
||||||
|
$course2 = $this->getDataGenerator()->create_course();
|
||||||
|
$coursecontext2 = context_course::instance($course2->id);
|
||||||
|
// Create user1.
|
||||||
|
$user1 = $this->getDataGenerator()->create_user();
|
||||||
|
$usercontext1 = context_user::instance($user1->id);
|
||||||
|
// Create user2.
|
||||||
|
$user2 = $this->getDataGenerator()->create_user();
|
||||||
|
$usercontext2 = context_user::instance($user2->id);
|
||||||
|
// Create user3.
|
||||||
|
$user3 = $this->getDataGenerator()->create_user();
|
||||||
|
$usercontext3 = context_user::instance($user3->id);
|
||||||
|
|
||||||
|
// The list of users in usercontext1 should not return anything yet (related data still haven't been created).
|
||||||
|
$userlist1 = new \core_privacy\local\request\userlist($usercontext1, $component);
|
||||||
|
provider::get_users_in_context($userlist1);
|
||||||
|
$this->assertCount(0, $userlist1);
|
||||||
|
// The list of users in coursecontext1 should not return anything yet (related data still haven't been created).
|
||||||
|
$userlist2 = new \core_privacy\local\request\userlist($coursecontext1, $component);
|
||||||
|
provider::get_users_in_context($userlist2);
|
||||||
|
$this->assertCount(0, $userlist2);
|
||||||
|
// The list of users in systemcontext should not return anything yet (related data still haven't been created).
|
||||||
|
$systemcontext = context_system::instance();
|
||||||
|
$userlist3 = new \core_privacy\local\request\userlist($systemcontext, $component);
|
||||||
|
provider::get_users_in_context($userlist3);
|
||||||
|
$this->assertCount(0, $userlist3);
|
||||||
|
|
||||||
|
// Assert that we find contexts where we created/modified a badge.
|
||||||
|
$this->create_badge(['usercreated' => $user1->id, 'usermodified' => $user2->id]);
|
||||||
|
$badge1 = $this->create_badge(['usercreated' => $user2->id, 'type' => BADGE_TYPE_COURSE, 'courseid' => $course1->id]);
|
||||||
|
$badge2 = $this->create_badge(['usercreated' => $user3->id, 'usermodified' => $user1->id]);
|
||||||
|
|
||||||
|
$this->create_manual_award(['recipientid' => $user2->id, 'issuerid' => $user1->id, 'badgeid' => $badge1->id]);
|
||||||
|
$this->create_manual_award(['recipientid' => $user3->id, 'issuerid' => $user2->id, 'badgeid' => $badge1->id]);
|
||||||
|
$this->create_manual_award(['recipientid' => $user1->id, 'issuerid' => $user2->id, 'badgeid' => $badge2->id]);
|
||||||
|
|
||||||
|
$this->create_backpack(['userid' => $user2->id]);
|
||||||
|
$this->create_issued(['badgeid' => $badge2->id, 'userid' => $user3->id]);
|
||||||
|
|
||||||
|
$crit = $this->create_criteria_manual($badge1->id);
|
||||||
|
$crit->mark_complete($user3->id);
|
||||||
|
|
||||||
|
// The list of users for user context should return user1 and user2.
|
||||||
|
provider::get_users_in_context($userlist1);
|
||||||
|
$this->assertCount(2, $userlist1);
|
||||||
|
$this->assertTrue(in_array($user1->id, $userlist1->get_userids()));
|
||||||
|
$this->assertTrue(in_array($user2->id, $userlist1->get_userids()));
|
||||||
|
|
||||||
|
// The list of users for course context should return user2.
|
||||||
|
provider::get_users_in_context($userlist2);
|
||||||
|
$this->assertCount(1, $userlist2);
|
||||||
|
$this->assertTrue(in_array($user2->id, $userlist2->get_userids()));
|
||||||
|
|
||||||
|
// The list of users for system context should return user1, user2 and user3.
|
||||||
|
provider::get_users_in_context($userlist3);
|
||||||
|
$this->assertCount(3, $userlist3);
|
||||||
|
$this->assertTrue(in_array($user1->id, $userlist3->get_userids()));
|
||||||
|
$this->assertTrue(in_array($user2->id, $userlist3->get_userids()));
|
||||||
|
$this->assertTrue(in_array($user3->id, $userlist3->get_userids()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that data for users in approved userlist is deleted.
|
||||||
|
*/
|
||||||
|
public function test_delete_data_for_users() {
|
||||||
|
$component = 'core_badges';
|
||||||
|
|
||||||
|
// Create course1.
|
||||||
|
$course1 = $this->getDataGenerator()->create_course();
|
||||||
|
$coursecontext1 = context_course::instance($course1->id);
|
||||||
|
// Create course2.
|
||||||
|
$course2 = $this->getDataGenerator()->create_course();
|
||||||
|
$coursecontext2 = context_course::instance($course2->id);
|
||||||
|
// Create user1.
|
||||||
|
$user1 = $this->getDataGenerator()->create_user();
|
||||||
|
$usercontext1 = context_user::instance($user1->id);
|
||||||
|
// Create user2.
|
||||||
|
$user2 = $this->getDataGenerator()->create_user();
|
||||||
|
$usercontext2 = context_user::instance($user2->id);
|
||||||
|
// Create user3.
|
||||||
|
$user3 = $this->getDataGenerator()->create_user();
|
||||||
|
$usercontext3 = context_user::instance($user3->id);
|
||||||
|
|
||||||
|
$this->create_badge(['usercreated' => $user1->id, 'usermodified' => $user2->id]);
|
||||||
|
$badge1 = $this->create_badge(['usercreated' => $user2->id, 'type' => BADGE_TYPE_COURSE, 'courseid' => $course1->id]);
|
||||||
|
$badge2 = $this->create_badge(['usercreated' => $user3->id, 'type' => BADGE_TYPE_COURSE, 'courseid' => $course2->id,
|
||||||
|
'usermodified' => $user1->id]);
|
||||||
|
|
||||||
|
$this->create_manual_award(['recipientid' => $user2->id, 'issuerid' => $user1->id, 'badgeid' => $badge1->id]);
|
||||||
|
$this->create_manual_award(['recipientid' => $user3->id, 'issuerid' => $user2->id, 'badgeid' => $badge1->id]);
|
||||||
|
$this->create_manual_award(['recipientid' => $user1->id, 'issuerid' => $user2->id, 'badgeid' => $badge2->id]);
|
||||||
|
|
||||||
|
$this->create_backpack(['userid' => $user2->id]);
|
||||||
|
$this->create_issued(['badgeid' => $badge2->id, 'userid' => $user3->id]);
|
||||||
|
|
||||||
|
$crit = $this->create_criteria_manual($badge1->id);
|
||||||
|
$crit->mark_complete($user3->id);
|
||||||
|
|
||||||
|
// The list of users for usercontext2 context should return users.
|
||||||
|
$userlist1 = new \core_privacy\local\request\userlist($usercontext2, $component);
|
||||||
|
provider::get_users_in_context($userlist1);
|
||||||
|
$this->assertCount(2, $userlist1);
|
||||||
|
$this->assertTrue(in_array($user1->id, $userlist1->get_userids()));
|
||||||
|
$this->assertTrue(in_array($user2->id, $userlist1->get_userids()));
|
||||||
|
|
||||||
|
// The list of users for coursecontext2 context should return users.
|
||||||
|
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
|
||||||
|
provider::get_users_in_context($userlist2);
|
||||||
|
$this->assertCount(2, $userlist2);
|
||||||
|
$this->assertTrue(in_array($user1->id, $userlist2->get_userids()));
|
||||||
|
$this->assertTrue(in_array($user3->id, $userlist2->get_userids()));
|
||||||
|
|
||||||
|
// The list of users for system context should return users.
|
||||||
|
$systemcontext = context_system::instance();
|
||||||
|
$userlist3 = new \core_privacy\local\request\userlist($systemcontext, $component);
|
||||||
|
provider::get_users_in_context($userlist3);
|
||||||
|
$this->assertCount(2, $userlist3);
|
||||||
|
$this->assertTrue(in_array($user1->id, $userlist3->get_userids()));
|
||||||
|
$this->assertTrue(in_array($user2->id, $userlist3->get_userids()));
|
||||||
|
|
||||||
|
// Delete the data for user1 in usercontext2.
|
||||||
|
$approvedlist = new approved_userlist($usercontext2, $component, [$user1->id]);
|
||||||
|
// Delete using delete_data_for_user. No data for users in usercontext2 should be removed.
|
||||||
|
provider::delete_data_for_users($approvedlist);
|
||||||
|
// The list of users for usercontext2 context should still return user1, user2.
|
||||||
|
$userlist1 = new \core_privacy\local\request\userlist($usercontext2, $component);
|
||||||
|
provider::get_users_in_context($userlist1);
|
||||||
|
$this->assertCount(2, $userlist1);
|
||||||
|
$this->assertTrue(in_array($user1->id, $userlist1->get_userids()));
|
||||||
|
$this->assertTrue(in_array($user2->id, $userlist1->get_userids()));
|
||||||
|
|
||||||
|
// Delete the data for user2 in usercontext2.
|
||||||
|
$approvedlist = new approved_userlist($usercontext2, $component, [$user2->id]);
|
||||||
|
// Delete using delete_data_for_user. The user data in usercontext2 should be removed.
|
||||||
|
provider::delete_data_for_users($approvedlist);
|
||||||
|
// The list of users for usercontext2 context should not return any users.
|
||||||
|
$userlist1 = new \core_privacy\local\request\userlist($usercontext2, $component);
|
||||||
|
provider::get_users_in_context($userlist1);
|
||||||
|
$this->assertCount(0, $userlist1);
|
||||||
|
|
||||||
|
// The list of users for coursecontext2 context should return the previous users.
|
||||||
|
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
|
||||||
|
provider::get_users_in_context($userlist2);
|
||||||
|
$this->assertCount(2, $userlist2);
|
||||||
|
|
||||||
|
// The list of users for system context should return the previous users.
|
||||||
|
$systemcontext = context_system::instance();
|
||||||
|
$userlist3 = new \core_privacy\local\request\userlist($systemcontext, $component);
|
||||||
|
provider::get_users_in_context($userlist3);
|
||||||
|
$this->assertCount(2, $userlist3);
|
||||||
|
|
||||||
|
// Make sure data is only deleted in the user context, nothing in course or system.
|
||||||
|
// Convert $userlist2 into an approved_contextlist.
|
||||||
|
$approvedlist = new approved_userlist($coursecontext2, $component, $userlist2->get_userids());
|
||||||
|
provider::delete_data_for_users($approvedlist);
|
||||||
|
|
||||||
|
// The list of users for coursecontext2 context should still return the user data.
|
||||||
|
$userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
|
||||||
|
provider::get_users_in_context($userlist2);
|
||||||
|
$this->assertCount(2, $userlist2);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a badge.
|
* Create a badge.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user