mirror of
https://github.com/moodle/moodle.git
synced 2025-08-11 03:46:42 +02:00
Merge branch 'wip-MDL-62068-34' of git://github.com/marinaglancy/moodle into MOODLE_34_STABLE
This commit is contained in:
commit
763db71ad3
3 changed files with 191 additions and 18 deletions
|
@ -586,11 +586,7 @@ class core_blog_privacy_testcase extends provider_testcase {
|
||||||
$commentpath = array_merge($path, [get_string('commentsubcontext', 'core_comment')]);
|
$commentpath = array_merge($path, [get_string('commentsubcontext', 'core_comment')]);
|
||||||
if ($e->id == $e1->id) {
|
if ($e->id == $e1->id) {
|
||||||
$tagdata = $writer->get_related_data($path, 'tags');
|
$tagdata = $writer->get_related_data($path, 'tags');
|
||||||
$this->assertCount(2, $tagdata);
|
$this->assertEquals(['Beer', 'Golf'], $tagdata, '', 0, 10, true);
|
||||||
$tag = array_shift($tagdata);
|
|
||||||
$this->assertEquals('Beer', $tag->rawname);
|
|
||||||
$tag = array_shift($tagdata);
|
|
||||||
$this->assertEquals('Golf', $tag->rawname);
|
|
||||||
|
|
||||||
$comments = $writer->get_data($commentpath);
|
$comments = $writer->get_data($commentpath);
|
||||||
$this->assertCount(2, $comments->comments);
|
$this->assertCount(2, $comments->comments);
|
||||||
|
|
|
@ -27,6 +27,10 @@ namespace core_tag\privacy;
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
use \core_privacy\local\metadata\collection;
|
use \core_privacy\local\metadata\collection;
|
||||||
|
use core_privacy\local\request\approved_contextlist;
|
||||||
|
use core_privacy\local\request\contextlist;
|
||||||
|
use core_privacy\local\request\transform;
|
||||||
|
use core_privacy\local\request\writer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Privacy Subsystem implementation for core_tag.
|
* Privacy Subsystem implementation for core_tag.
|
||||||
|
@ -39,7 +43,10 @@ class provider implements
|
||||||
\core_privacy\local\metadata\provider,
|
\core_privacy\local\metadata\provider,
|
||||||
|
|
||||||
// The tag subsystem provides data to other components.
|
// The tag subsystem provides data to other components.
|
||||||
\core_privacy\local\request\subsystem\plugin_provider {
|
\core_privacy\local\request\subsystem\plugin_provider,
|
||||||
|
|
||||||
|
// The tag subsystem may have data that belongs to this user.
|
||||||
|
\core_privacy\local\request\plugin\provider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns meta data about this system.
|
* Returns meta data about this system.
|
||||||
|
@ -110,17 +117,9 @@ class provider implements
|
||||||
) {
|
) {
|
||||||
global $DB;
|
global $DB;
|
||||||
|
|
||||||
// Do not include the mdl_tag userid data because of bug with re-using existing tags by other users.
|
// Ignore mdl_tag.userid here because it only reflects the user who originally created the tag.
|
||||||
$sql = "SELECT
|
$sql = "SELECT
|
||||||
t.id,
|
t.rawname
|
||||||
t.tagcollid,
|
|
||||||
t.name,
|
|
||||||
t.rawname,
|
|
||||||
t.isstandard,
|
|
||||||
t.description,
|
|
||||||
t.descriptionformat,
|
|
||||||
t.flag,
|
|
||||||
t.timemodified
|
|
||||||
FROM {tag} t
|
FROM {tag} t
|
||||||
INNER JOIN {tag_instance} ti ON ti.tagid = t.id
|
INNER JOIN {tag_instance} ti ON ti.tagid = t.id
|
||||||
WHERE ti.component = :component
|
WHERE ti.component = :component
|
||||||
|
@ -141,7 +140,7 @@ class provider implements
|
||||||
'userid' => $userid,
|
'userid' => $userid,
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($tags = $DB->get_records_sql($sql, $params)) {
|
if ($tags = $DB->get_fieldset_sql($sql, $params)) {
|
||||||
$writer = \core_privacy\local\request\writer::with_context($context)
|
$writer = \core_privacy\local\request\writer::with_context($context)
|
||||||
->export_related_data($subcontext, 'tags', $tags);
|
->export_related_data($subcontext, 'tags', $tags);
|
||||||
}
|
}
|
||||||
|
@ -194,4 +193,91 @@ class provider implements
|
||||||
'contextid = :contextid AND component = :component AND itemtype = :itemtype AND itemid ' . $itemidstest,
|
'contextid = :contextid AND component = :component AND itemtype = :itemtype AND itemid ' . $itemidstest,
|
||||||
$params);
|
$params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of contexts that contain user information for the specified user.
|
||||||
|
*
|
||||||
|
* @param int $userid The user to search.
|
||||||
|
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
|
||||||
|
*/
|
||||||
|
public static function get_contexts_for_userid(int $userid) : contextlist {
|
||||||
|
$contextlist = new contextlist();
|
||||||
|
$contextlist->add_from_sql("SELECT c.id
|
||||||
|
FROM {context} c
|
||||||
|
JOIN {tag} t ON t.userid = :userid
|
||||||
|
WHERE contextlevel = :contextlevel",
|
||||||
|
['userid' => $userid, 'contextlevel' => CONTEXT_SYSTEM]);
|
||||||
|
return $contextlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export all user data for the specified user, in the specified contexts.
|
||||||
|
*
|
||||||
|
* @param approved_contextlist $contextlist The approved contexts to export information for.
|
||||||
|
*/
|
||||||
|
public static function export_user_data(approved_contextlist $contextlist) {
|
||||||
|
global $DB;
|
||||||
|
$context = \context_system::instance();
|
||||||
|
if (!$contextlist->count() || !in_array($context->id, $contextlist->get_contextids())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $contextlist->get_user();
|
||||||
|
$sql = "SELECT id, userid, tagcollid, name, rawname, isstandard, description, descriptionformat, flag, timemodified
|
||||||
|
FROM {tag} WHERE userid = ?";
|
||||||
|
$rs = $DB->get_recordset_sql($sql, [$user->id]);
|
||||||
|
foreach ($rs as $record) {
|
||||||
|
$subcontext = [get_string('tags', 'tag'), $record->id];
|
||||||
|
$tag = (object)[
|
||||||
|
'id' => $record->id,
|
||||||
|
'userid' => transform::user($record->userid),
|
||||||
|
'name' => $record->name,
|
||||||
|
'rawname' => $record->rawname,
|
||||||
|
'isstandard' => transform::yesno($record->isstandard),
|
||||||
|
'description' => writer::with_context($context)->rewrite_pluginfile_urls($subcontext,
|
||||||
|
'tag', 'description', $record->id, strval($record->description)),
|
||||||
|
'descriptionformat' => $record->descriptionformat,
|
||||||
|
'flag' => $record->flag,
|
||||||
|
'timemodified' => transform::datetime($record->timemodified),
|
||||||
|
|
||||||
|
];
|
||||||
|
writer::with_context($context)->export_data($subcontext, $tag);
|
||||||
|
writer::with_context($context)->export_area_files($subcontext, 'tag', 'description', $record->id);
|
||||||
|
}
|
||||||
|
$rs->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all data for all users in the specified context.
|
||||||
|
*
|
||||||
|
* We do not delete tag instances in this method - this should be done by the components that define tagareas.
|
||||||
|
* We only delete tags themselves in case of system context.
|
||||||
|
*
|
||||||
|
* @param context $context The specific context to delete data for.
|
||||||
|
*/
|
||||||
|
public static function delete_data_for_all_users_in_context(\context $context) {
|
||||||
|
global $DB;
|
||||||
|
// Tags can only be defined in system context.
|
||||||
|
if ($context->id == \context_system::instance()->id) {
|
||||||
|
$DB->delete_records('tag_instance');
|
||||||
|
$DB->delete_records('tag', []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all user data for the specified user, in the specified contexts.
|
||||||
|
*
|
||||||
|
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
|
||||||
|
*/
|
||||||
|
public static function delete_data_for_user(approved_contextlist $contextlist) {
|
||||||
|
global $DB;
|
||||||
|
$context = \context_system::instance();
|
||||||
|
if (!$contextlist->count() || !in_array($context->id, $contextlist->get_contextids())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not delete tags themselves in case they are used by somebody else.
|
||||||
|
// If the user is the only one using the tag, it will be automatically deleted anyway during the next cron cleanup.
|
||||||
|
$DB->set_field_select('tag', 'userid', 0, 'userid = ?', [$contextlist->get_user()->id]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,7 @@ class core_tag_privacy_testcase extends provider_testcase {
|
||||||
|
|
||||||
// Check the exported tag's rawname is found in the initial dummy tags.
|
// Check the exported tag's rawname is found in the initial dummy tags.
|
||||||
foreach ($exportedtags as $exportedtag) {
|
foreach ($exportedtags as $exportedtag) {
|
||||||
$this->assertContains($exportedtag->rawname, $dummytags);
|
$this->assertContains($exportedtag, $dummytags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,4 +151,95 @@ class core_tag_privacy_testcase extends provider_testcase {
|
||||||
$expectedtagcount -= 2;
|
$expectedtagcount -= 2;
|
||||||
$this->assertEquals($expectedtagcount, $DB->count_records('tag_instance'));
|
$this->assertEquals($expectedtagcount, $DB->count_records('tag_instance'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function set_up_tags() {
|
||||||
|
global $CFG;
|
||||||
|
require_once($CFG->dirroot.'/user/editlib.php');
|
||||||
|
|
||||||
|
$this->resetAfterTest(true);
|
||||||
|
|
||||||
|
$user1 = $this->getDataGenerator()->create_user();
|
||||||
|
$user2 = $this->getDataGenerator()->create_user();
|
||||||
|
|
||||||
|
$this->setUser($user1);
|
||||||
|
useredit_update_interests($user1, ['Birdwatching', 'Computers']);
|
||||||
|
|
||||||
|
$this->setUser($user2);
|
||||||
|
useredit_update_interests($user2, ['computers']);
|
||||||
|
|
||||||
|
$this->setAdminUser();
|
||||||
|
|
||||||
|
$tag = core_tag_tag::get_by_name(0, 'computers', '*');
|
||||||
|
$tag->update(['description' => '<img src="@@PLUGINFILE@@/computer.jpg">']);
|
||||||
|
get_file_storage()->create_file_from_string([
|
||||||
|
'contextid' => context_system::instance()->id,
|
||||||
|
'component' => 'tag',
|
||||||
|
'filearea' => 'description',
|
||||||
|
'itemid' => $tag->id,
|
||||||
|
'filepath' => '/',
|
||||||
|
'filename' => 'computer.jpg'
|
||||||
|
], "jpg:image");
|
||||||
|
|
||||||
|
return [$user1, $user2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_export_item_tags() {
|
||||||
|
list($user1, $user2) = $this->set_up_tags();
|
||||||
|
$this->assertEquals([context_system::instance()->id],
|
||||||
|
provider::get_contexts_for_userid($user1->id)->get_contextids());
|
||||||
|
$this->assertEmpty(provider::get_contexts_for_userid($user2->id)->get_contextids());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_delete_data_for_user() {
|
||||||
|
global $DB;
|
||||||
|
list($user1, $user2) = $this->set_up_tags();
|
||||||
|
$context = context_system::instance();
|
||||||
|
$this->assertEquals(2, $DB->count_records('tag', []));
|
||||||
|
$this->assertEquals(0, $DB->count_records('tag', ['userid' => 0]));
|
||||||
|
provider::delete_data_for_user(new \core_privacy\local\request\approved_contextlist($user2, 'core_tag', [$context->id]));
|
||||||
|
$this->assertEquals(2, $DB->count_records('tag', []));
|
||||||
|
$this->assertEquals(0, $DB->count_records('tag', ['userid' => 0]));
|
||||||
|
provider::delete_data_for_user(new \core_privacy\local\request\approved_contextlist($user1, 'core_tag', [$context->id]));
|
||||||
|
$this->assertEquals(2, $DB->count_records('tag', []));
|
||||||
|
$this->assertEquals(2, $DB->count_records('tag', ['userid' => 0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_delete_data_for_all_users_in_context() {
|
||||||
|
global $DB;
|
||||||
|
$course = $this->getDataGenerator()->create_course();
|
||||||
|
list($user1, $user2) = $this->set_up_tags();
|
||||||
|
$this->assertEquals(2, $DB->count_records('tag', []));
|
||||||
|
$this->assertEquals(3, $DB->count_records('tag_instance', []));
|
||||||
|
provider::delete_data_for_all_users_in_context(context_course::instance($course->id));
|
||||||
|
$this->assertEquals(2, $DB->count_records('tag', []));
|
||||||
|
$this->assertEquals(3, $DB->count_records('tag_instance', []));
|
||||||
|
provider::delete_data_for_all_users_in_context(context_system::instance());
|
||||||
|
$this->assertEquals(0, $DB->count_records('tag', []));
|
||||||
|
$this->assertEquals(0, $DB->count_records('tag_instance', []));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_export_data_for_user() {
|
||||||
|
global $DB;
|
||||||
|
list($user1, $user2) = $this->set_up_tags();
|
||||||
|
$context = context_system::instance();
|
||||||
|
provider::export_user_data(new \core_privacy\local\request\approved_contextlist($user2, 'core_tag', [$context->id]));
|
||||||
|
$this->assertFalse(writer::with_context($context)->has_any_data());
|
||||||
|
|
||||||
|
$tagids = array_values(array_map(function($tag) {
|
||||||
|
return $tag->id;
|
||||||
|
}, core_tag_tag::get_by_name_bulk(core_tag_collection::get_default(), ['Birdwatching', 'Computers'])));
|
||||||
|
|
||||||
|
provider::export_user_data(new \core_privacy\local\request\approved_contextlist($user1, 'core_tag', [$context->id]));
|
||||||
|
$writer = writer::with_context($context);
|
||||||
|
|
||||||
|
$data = $writer->get_data(['Tags', $tagids[0]]);
|
||||||
|
$files = $writer->get_files(['Tags', $tagids[0]]);
|
||||||
|
$this->assertEquals('Birdwatching', $data->rawname);
|
||||||
|
$this->assertEmpty($files);
|
||||||
|
|
||||||
|
$data = $writer->get_data(['Tags', $tagids[1]]);
|
||||||
|
$files = $writer->get_files(['Tags', $tagids[1]]);
|
||||||
|
$this->assertEquals('Computers', $data->rawname);
|
||||||
|
$this->assertEquals(['computer.jpg'], array_keys($files));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue