MDL-63501 mod_scorm: Add support for removal of context users

This issue is a part of the MDL-62560 Epic.
This commit is contained in:
Michael Hawkins 2018-10-03 10:15:37 +08:00 committed by David Monllao
parent 630a05c2aa
commit 6d6e4b7a51
2 changed files with 141 additions and 1 deletions

View File

@ -28,9 +28,11 @@ defined('MOODLE_INTERNAL') || die();
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\helper;
use core_privacy\local\request\transform;
use core_privacy\local\request\userlist;
use core_privacy\local\request\writer;
/**
@ -41,6 +43,7 @@ use core_privacy\local\request\writer;
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\core_userlist_provider,
\core_privacy\local\request\plugin\provider {
/**
@ -103,6 +106,36 @@ 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) {
$context = $userlist->get_context();
if (!is_a($context, \context_module::class)) {
return;
}
$sql = "SELECT ss.userid
FROM {%s} ss
JOIN {modules} m
ON m.name = 'scorm'
JOIN {course_modules} cm
ON cm.instance = ss.scormid
AND cm.module = m.id
JOIN {context} ctx
ON ctx.instanceid = cm.id
AND ctx.contextlevel = :modlevel
WHERE ctx.id = :contextid";
$params = ['modlevel' => CONTEXT_MODULE, 'contextid' => $context->id];
$userlist->add_from_sql('userid', sprintf($sql, 'scorm_scoes_track'), $params);
$userlist->add_from_sql('userid', sprintf($sql, 'scorm_aicc_session'), $params);
}
/**
* Export all user data for the specified user, in the specified contexts.
*
@ -290,6 +323,40 @@ class provider implements
static::delete_data('scorm_aicc_session', $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();
if (!is_a($context, \context_module::class)) {
return;
}
// Prepare SQL to gather all completed IDs.
$userids = $userlist->get_userids();
list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$sql = "SELECT ss.id
FROM {%s} ss
JOIN {modules} m
ON m.name = 'scorm'
JOIN {course_modules} cm
ON cm.instance = ss.scormid
AND cm.module = m.id
JOIN {context} ctx
ON ctx.instanceid = cm.id
WHERE ctx.id = :contextid
AND ss.userid $insql";
$params = array_merge($inparams, ['contextid' => $context->id]);
static::delete_data('scorm_scoes_track', $sql, $params);
static::delete_data('scorm_aicc_session', $sql, $params);
}
/**
* Delete data from $tablename with the IDs returned by $sql query.
*

View File

@ -27,6 +27,7 @@ defined('MOODLE_INTERNAL') || die();
use mod_scorm\privacy\provider;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\writer;
use core_privacy\tests\provider_testcase;
@ -68,6 +69,28 @@ class mod_scorm_testcase extends provider_testcase {
$this->assertContains($this->context->id, $contextlist->get_contextids());
}
/**
* Test getting the user IDs for the context related to this plugin.
*/
public function test_get_users_in_context() {
$this->resetAfterTest(true);
$this->setAdminUser();
$this->scorm_setup_test_scenario_data();
$component = 'mod_scorm';
$userlist = new \core_privacy\local\request\userlist($this->context, $component);
provider::get_users_in_context($userlist);
// Students 1 and 2 have attempts in the SCORM context, student 0 does not.
$this->assertCount(2, $userlist);
$expected = [$this->student1->id, $this->student2->id];
$actual = $userlist->get_userids();
sort($expected);
sort($actual);
$this->assertEquals($expected, $actual);
}
/**
* Test that data is exported correctly for this plugin.
*/
@ -196,9 +219,59 @@ class mod_scorm_testcase extends provider_testcase {
$this->assertEquals(2, $count);
}
/**
* Test for provider::delete_data_for_users().
*/
public function test_delete_data_for_users() {
global $DB;
$component = 'mod_scorm';
$this->resetAfterTest(true);
$this->setAdminUser();
$this->scorm_setup_test_scenario_data();
// Before deletion, we should have 8 entries in the scorm_scoes_track table.
$count = $DB->count_records('scorm_scoes_track');
$this->assertEquals(8, $count);
// Before deletion, we should have 4 entries in the scorm_aicc_session table.
$count = $DB->count_records('scorm_aicc_session');
$this->assertEquals(4, $count);
// Delete only student 1's data, retain student 2's data.
$approveduserids = [$this->student1->id];
$approvedlist = new approved_userlist($this->context, $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
// After deletion, the scorm_scoes_track entries for the first student should have been deleted.
$count = $DB->count_records('scorm_scoes_track', ['userid' => $this->student1->id]);
$this->assertEquals(0, $count);
$count = $DB->count_records('scorm_scoes_track');
$this->assertEquals(4, $count);
// After deletion, the scorm_aicc_session entries for the first student should have been deleted.
$count = $DB->count_records('scorm_aicc_session', ['userid' => $this->student1->id]);
$this->assertEquals(0, $count);
$count = $DB->count_records('scorm_aicc_session');
$this->assertEquals(2, $count);
// Confirm that the SCORM hasn't been removed.
$scormcount = $DB->get_records('scorm');
$this->assertCount(1, (array) $scormcount);
// Delete scoes_track for student0 (nothing has to be removed).
$approveduserids = [$this->student0->id];
$approvedlist = new approved_userlist($this->context, $component, $approveduserids);
provider::delete_data_for_users($approvedlist);
$count = $DB->count_records('scorm_scoes_track');
$this->assertEquals(4, $count);
$count = $DB->count_records('scorm_aicc_session');
$this->assertEquals(2, $count);
}
/**
* Helper function to setup 3 users and 2 SCORM attempts for student1 and student2.
* $this->student0 is always created withot any attempt.
* $this->student0 is always created without any attempt.
*/
protected function scorm_setup_test_scenario_data() {
global $DB;