MDL-63564 core_question: support removal of multiple users in a context

This issue is a part of the MDL-62560 Epic.
This commit is contained in:
Shamim Rezaie 2018-10-09 16:33:05 +11:00 committed by Mihail Geshoski
parent 8b019fb709
commit c8aff683cb
2 changed files with 179 additions and 6 deletions

View File

@ -18,17 +18,20 @@
* Privacy Subsystem implementation for core_question.
*
* @package core_question
* @category privacy
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_question\privacy;
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\writer;
use \core_privacy\local\request\transform;
use \core_privacy\local\request\contextlist;
use \core_privacy\local\request\approved_contextlist;
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();
@ -55,7 +58,10 @@ class provider implements
\core_privacy\local\request\subsystem\provider,
// This is a subsysytem which provides information to plugins.
\core_privacy\local\request\subsystem\plugin_provider
\core_privacy\local\request\subsystem\plugin_provider,
// This plugin is capable of determining which users have data within it.
\core_privacy\local\request\core_userlist_provider
{
/**
@ -344,6 +350,33 @@ 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();
// A user may have created or updated a question.
// Questions are linked against a question category, which has a contextid field.
$sql = "SELECT q.createdby AS userid
FROM {question} q
JOIN {question_categories} cat ON cat.id = q.category
WHERE cat.contextid = :contextid
UNION
SELECT q.modifiedby AS userid
FROM {question} q
JOIN {question_categories} cat ON cat.id = q.category
WHERE cat.contextid = :contextidagain";
$params = [
'contextid' => $context->id,
'contextidagain' => $context->id,
];
$userlist->add_from_sql('userid', $sql, $params);
}
/**
* Determine related question usages for a user.
*
@ -476,4 +509,33 @@ class provider implements
category IN (SELECT id FROM {question_categories} WHERE contextid {$contextsql})
AND modifiedby = :modifiedby", $contextparams);
}
/**
* 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;
// Questions are considered to be 'owned' by the institution, even if they were originally written by a specific
// user. They are still exported in the list of a users data, but they are not removed.
// The userid is instead anonymised.
$context = $userlist->get_context();
$userids = $userlist->get_userids();
list($createdbysql, $createdbyparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
list($modifiedbysql, $modifiedbyparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$params = ['contextid' => $context->id];
$DB->set_field_select('question', 'createdby', 0, "
category IN (SELECT id FROM {question_categories} WHERE contextid = :contextid)
AND createdby {$createdbysql}", $params + $createdbyparams);
$DB->set_field_select('question', 'modifiedby', 0, "
category IN (SELECT id FROM {question_categories} WHERE contextid = :contextid)
AND modifiedby {$modifiedbysql}", $params + $modifiedbyparams);
}
}

View File

@ -425,4 +425,115 @@ class core_question_privacy_provider_testcase extends \core_privacy\tests\provid
$this->assertEquals($user->id, $qrecord->createdby);
$this->assertEquals($user->id, $qrecord->modifiedby);
}
/**
* Test for provider::get_users_in_context().
*/
public function test_get_users_in_context() {
$this->resetAfterTest();
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
// Create three test users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
// Create one question as each user in different contexts.
$this->setUser($user1);
$user1data = $questiongenerator->setup_course_and_questions();
$this->setUser($user2);
$user2data = $questiongenerator->setup_course_and_questions();
$course1context = \context_course::instance($user1data[1]->id);
$course1questions = $user1data[3];
// Log in as user3 and update the questions in course1.
$this->setUser($user3);
foreach ($course1questions as $question) {
$questiongenerator->update_question($question);
}
$userlist = new \core_privacy\local\request\userlist($course1context, 'core_question');
provider::get_users_in_context($userlist);
// User1 has created questions and user3 has edited them.
$this->assertCount(2, $userlist);
$this->assertEquals(
[$user1->id, $user3->id],
$userlist->get_userids(),
'', 0.0, 10, true);
}
/**
* Test for provider::delete_data_for_users().
*/
public function test_delete_data_for_users() {
global $DB;
$this->resetAfterTest();
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
// Create three test users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
// Create one question as each user in different contexts.
$this->setUser($user1);
$course1data = $questiongenerator->setup_course_and_questions();
$course1 = $course1data[1];
$course1qcat = $course1data[2];
$course1questions = $course1data[3];
$course1context = \context_course::instance($course1->id);
// Log in as user2 and update the questions in course1.
$this->setUser($user2);
foreach ($course1questions as $question) {
$questiongenerator->update_question($question);
}
// Add 2 more questions to course1 by user3.
$this->setUser($user3);
$questiongenerator->create_question('shortanswer', null, ['category' => $course1qcat->id]);
$questiongenerator->create_question('shortanswer', null, ['category' => $course1qcat->id]);
// Now, log in as user1 again, and then create a new course and add questions to that.
$this->setUser($user1);
$questiongenerator->setup_course_and_questions();
$approveduserlist = new \core_privacy\local\request\approved_userlist($course1context, 'core_question',
[$user1->id, $user2->id]);
provider::delete_data_for_users($approveduserlist);
// Now, there should be no question related to user1 or user2 in course1.
$this->assertEquals(
0,
$DB->count_records_sql("SELECT COUNT(q.id)
FROM {question} q
JOIN {question_categories} qc ON q.category = qc.id
WHERE qc.contextid = ?
AND (q.createdby = ? OR q.modifiedby = ? OR q.createdby = ? OR q.modifiedby = ?)",
[$course1context->id, $user1->id, $user1->id, $user2->id, $user2->id])
);
// User3 data in course1 should not change.
$this->assertEquals(
2,
$DB->count_records_sql("SELECT COUNT(q.id)
FROM {question} q
JOIN {question_categories} qc ON q.category = qc.id
WHERE qc.contextid = ? AND (q.createdby = ? OR q.modifiedby = ?)",
[$course1context->id, $user3->id, $user3->id])
);
// User1 has authored 2 questions in another course.
$this->assertEquals(
2,
$DB->count_records_select('question', "createdby = ? OR modifiedby = ?", [$user1->id, $user1->id])
);
}
}