*/
class provider implements
\core_privacy\local\metadata\provider,
- \core_privacy\local\request\subsystem\provider {
+ \core_privacy\local\request\subsystem\provider,
+ \core_privacy\local\request\core_userlist_provider {
/**
* Returns metadata.
return $contextlist;
}
+ /**
+ * Get the list of contexts that contain user information for the specified user.
+ *
+ * @param \core_privacy\local\request\userlist $userlist The userlist containing the list of users who have
+ * data in this context/plugin combination.
+ */
+ public static function get_users_in_context(\core_privacy\local\request\userlist $userlist) {
+ global $DB;
+ $context = $userlist->get_context();
+ if ($context->contextlevel == CONTEXT_COURSE || $context->contextlevel == CONTEXT_MODULE) {
+
+ $params = ['contextid' => $context->id];
+
+ $sql = "SELECT p.id, p.userid
+ FROM {post} p
+ JOIN {blog_association} ba ON ba.blogid = p.id AND ba.contextid = :contextid";
+
+ $posts = $DB->get_records_sql($sql, $params);
+ $userids = array_map(function($post) {
+ return $post->userid;
+ }, $posts);
+ $userlist->add_users($userids);
+
+ // Add any user's who posted on the blog.
+ list($insql, $inparams) = $DB->get_in_or_equal(array_keys($posts), SQL_PARAMS_NAMED);
+ \core_comment\privacy\provider::get_users_in_context_from_sql($userlist, 'c', 'blog', 'format_blog', null, $insql,
+ $inparams);
+ } else if ($context->contextlevel == CONTEXT_USER) {
+ $params = ['userid' => $context->instanceid];
+
+ $sql = "SELECT userid
+ FROM {blog_external}
+ WHERE userid = :userid";
+ $userlist->add_from_sql('userid', $sql, $params);
+
+ $sql = "SELECT userid
+ FROM {post}
+ WHERE userid = :userid";
+ $userlist->add_from_sql('userid', $sql, $params);
+
+ // Add any user's who posted on the blog.
+ \core_comment\privacy\provider::get_users_in_context_from_sql($userlist, 'c', 'blog', 'format_blog', $context->id);
+ }
+ }
+
/**
* Export all user data for the specified user, in the specified contexts.
*
}
}
+ /**
+ * 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(\core_privacy\local\request\approved_userlist $userlist) {
+ global $DB;
+
+ $context = $userlist->get_context();
+ $userids = $userlist->get_userids();
+
+ if ($context->contextlevel == CONTEXT_USER) {
+ // If one of the listed users matches this context then delete the blog, associations, and comments.
+ if (array_search($context->instanceid, $userids) !== false) {
+ self::delete_all_user_data($context);
+ \core_comment\privacy\provider::delete_comments_for_all_users($context, 'blog', 'format_blog');
+ return;
+ }
+ \core_comment\privacy\provider::delete_comments_for_users($userlist, 'blog', 'format_blog');
+ } else {
+ list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
+ $sql = "SELECT ba.id
+ FROM {blog_association} ba
+ JOIN {post} p ON p.id = ba.blogid
+ WHERE ba.contextid = :contextid
+ AND p.userid $insql";
+ $inparams['contextid'] = $context->id;
+ $associds = $DB->get_fieldset_sql($sql, $inparams);
+
+ if (!empty($associds)) {
+ list($insql, $inparams) = $DB->get_in_or_equal($associds, SQL_PARAMS_NAMED, 'param', true);
+ $DB->delete_records_select('blog_association', "id $insql", $inparams);
+ }
+ }
+ }
+
/**
* Helper method to delete all user data.
*
$this->assertTrue(in_array(context_course::instance($c1->id)->id, $contextids));
}
+ /**
+ * Test that user IDs are returned for a specificed course or module context.
+ */
+ public function test_get_users_in_context_course_and_module() {
+ $user1 = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $course = $this->getDataGenerator()->create_course();
+ $c1ctx = context_course::instance($course->id);
+
+ $post = $this->create_post(['userid' => $user1->id, 'courseid' => $course->id]);
+ $entry = new blog_entry($post->id);
+ $entry->add_association($c1ctx->id);
+
+ // Add a comment from user 2.
+ $comment = $this->get_comment_object(context_user::instance($user1->id), $entry->id);
+ $this->setUser($user2);
+ $comment->add('Nice blog post');
+
+ $userlist = new \core_privacy\local\request\userlist($c1ctx, 'core_blog');
+ provider::get_users_in_context($userlist);
+ $userids = $userlist->get_userids();
+ $this->assertCount(2, $userids);
+
+ // Add an association for a module.
+ $cm1a = $this->getDataGenerator()->create_module('page', ['course' => $course]);
+ $cm1ctx = context_module::instance($cm1a->cmid);
+
+ $post2 = $this->create_post(['userid' => $user2->id, 'courseid' => $course->id]);
+ $entry2 = new blog_entry($post2->id);
+ $entry2->add_association($cm1ctx->id);
+
+ $userlist = new \core_privacy\local\request\userlist($cm1ctx, 'core_blog');
+ provider::get_users_in_context($userlist);
+ $userids = $userlist->get_userids();
+ $this->assertCount(1, $userids);
+ }
+
+ /**
+ * Test that user IDs are returned for a specificed user context.
+ */
+ public function test_get_users_in_context_user_context() {
+ $user1 = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $u1ctx = context_user::instance($user1->id);
+
+ $post = $this->create_post(['userid' => $user1->id]);
+ $entry = new blog_entry($post->id);
+
+ // Add a comment from user 2.
+ $comment = $this->get_comment_object($u1ctx, $entry->id);
+ $this->setUser($user2);
+ $comment->add('Another nice blog post');
+
+ $userlist = new \core_privacy\local\request\userlist($u1ctx, 'core_blog');
+ provider::get_users_in_context($userlist);
+ $userids = $userlist->get_userids();
+ $this->assertCount(2, $userids);
+ }
+
+ /**
+ * Test that user IDs are returned for a specificed user context for an external blog.
+ */
+ public function test_get_users_in_context_external_blog() {
+ $user1 = $this->getDataGenerator()->create_user();
+ $u1ctx = context_user::instance($user1->id);
+ $extu1 = $this->create_external_blog(['userid' => $user1->id]);
+
+ $userlist = new \core_privacy\local\request\userlist($u1ctx, 'core_blog');
+ provider::get_users_in_context($userlist);
+ $userids = $userlist->get_userids();
+ $this->assertCount(1, $userids);
+ }
+
public function test_delete_data_for_user() {
global $DB;
}
+ /**
+ * Test that deleting of blog information in a user context works as desired.
+ */
+ public function test_delete_data_for_users_user_context() {
+ global $DB;
+
+ $u1 = $this->getDataGenerator()->create_user();
+ $u2 = $this->getDataGenerator()->create_user();
+ $u3 = $this->getDataGenerator()->create_user();
+ $u4 = $this->getDataGenerator()->create_user();
+ $u5 = $this->getDataGenerator()->create_user();
+
+ $u1ctx = context_user::instance($u1->id);
+
+ $post = $this->create_post(['userid' => $u1->id]);
+ $entry = new blog_entry($post->id);
+
+ $comment = $this->get_comment_object($u1ctx, $entry->id);
+ $this->setUser($u1);
+ $comment->add('Hello, I created the blog');
+ $this->setUser($u2);
+ $comment->add('User 2 making a comment.');
+ $this->setUser($u3);
+ $comment->add('User 3 here.');
+ $this->setUser($u4);
+ $comment->add('User 4 is nice.');
+ $this->setUser($u5);
+ $comment->add('User 5 for the win.');
+
+ // This will only delete the comments made by user 4 and 5.
+ $this->assertCount(5, $DB->get_records('comments', ['contextid' => $u1ctx->id]));
+ $userlist = new \core_privacy\local\request\approved_userlist($u1ctx, 'core_blog', [$u4->id, $u5->id]);
+ provider::delete_data_for_users($userlist);
+ $this->assertCount(3, $DB->get_records('comments', ['contextid' => $u1ctx->id]));
+ $this->assertCount(1, $DB->get_records('post', ['userid' => $u1->id]));
+
+ // As the owner of the post is here everything will be deleted.
+ $userlist = new \core_privacy\local\request\approved_userlist($u1ctx, 'core_blog', [$u1->id, $u2->id]);
+ provider::delete_data_for_users($userlist);
+ $this->assertEmpty($DB->get_records('comments', ['contextid' => $u1ctx->id]));
+ $this->assertEmpty($DB->get_records('post', ['userid' => $u1->id]));
+ }
+
+ /**
+ * Test that deleting of an external blog in a user context works as desired.
+ */
+ public function test_delete_data_for_users_external_blog() {
+ global $DB;
+
+ $u1 = $this->getDataGenerator()->create_user();
+ $u2 = $this->getDataGenerator()->create_user();
+
+ $u1ctx = context_user::instance($u1->id);
+ $u2ctx = context_user::instance($u2->id);
+
+ $post = $this->create_external_blog(['userid' => $u1->id, 'url' => 'https://moodle.org', 'name' => 'Moodle RSS']);
+ $post2 = $this->create_external_blog(['userid' => $u2->id, 'url' => 'https://moodle.com', 'name' => 'Some other thing']);
+
+ // Check that we have two external blogs created.
+ $this->assertCount(2, $DB->get_records('blog_external'));
+ // This will only delete the external blog for user 1.
+ $userlist = new \core_privacy\local\request\approved_userlist($u1ctx, 'core_blog', [$u1->id, $u2->id]);
+ provider::delete_data_for_users($userlist);
+ $this->assertCount(1, $DB->get_records('blog_external'));
+ }
+
+ public function test_delete_data_for_users_course_and_module_context() {
+ global $DB;
+
+ $u1 = $this->getDataGenerator()->create_user();
+ $u2 = $this->getDataGenerator()->create_user();
+ $u3 = $this->getDataGenerator()->create_user();
+ $u4 = $this->getDataGenerator()->create_user();
+ $u5 = $this->getDataGenerator()->create_user();
+
+ $course = $this->getDataGenerator()->create_course();
+ $module = $this->getDataGenerator()->create_module('page', ['course' => $course]);
+
+ $u1ctx = context_user::instance($u1->id);
+ $u3ctx = context_user::instance($u3->id);
+ $c1ctx = context_course::instance($course->id);
+ $cm1ctx = context_module::instance($module->cmid);
+
+ // Blog with course association.
+ $post1 = $this->create_post(['userid' => $u1->id, 'courseid' => $course->id]);
+ $entry1 = new blog_entry($post1->id);
+ $entry1->add_association($c1ctx->id);
+
+ // Blog with module association.
+ $post2 = $this->create_post(['userid' => $u3->id, 'courseid' => $course->id]);
+ $entry2 = new blog_entry($post2->id);
+ $entry2->add_association($cm1ctx->id);
+
+ $comment = $this->get_comment_object($u1ctx, $entry1->id);
+ $this->setUser($u1);
+ $comment->add('Hello, I created the blog');
+ $this->setUser($u2);
+ $comment->add('comment on first course blog');
+ $this->setUser($u4);
+ $comment->add('user 4 on course blog');
+
+ $comment = $this->get_comment_object($u3ctx, $entry2->id);
+ $this->setUser($u3);
+ $comment->add('Hello, I created the module blog');
+ $this->setUser($u2);
+ $comment->add('I am commenting on both');
+ $this->setUser($u5);
+ $comment->add('User 5 for modules');
+
+ $this->assertCount(6, $DB->get_records('comments', ['component' => 'blog']));
+ $this->assertCount(2, $DB->get_records('post', ['courseid' => $course->id]));
+ $this->assertCount(2, $DB->get_records('blog_association'));
+
+ // When using the course or module context we are only removing the blog associations and the comments.
+ $userlist = new \core_privacy\local\request\approved_userlist($c1ctx, 'core_blog', [$u2->id, $u1->id, $u5->id]);
+ provider::delete_data_for_users($userlist);
+ // Only one of the blog_associations should be removed. Everything else should be as before.
+ $this->assertCount(6, $DB->get_records('comments', ['component' => 'blog']));
+ $this->assertCount(2, $DB->get_records('post', ['courseid' => $course->id]));
+ $this->assertCount(1, $DB->get_records('blog_association'));
+
+ $userlist = new \core_privacy\local\request\approved_userlist($cm1ctx, 'core_blog', [$u2->id, $u1->id, $u3->id]);
+ provider::delete_data_for_users($userlist);
+ // Now we've removed the other association.
+ $this->assertCount(6, $DB->get_records('comments', ['component' => 'blog']));
+ $this->assertCount(2, $DB->get_records('post', ['courseid' => $course->id]));
+ $this->assertEmpty($DB->get_records('blog_association'));
+ }
+
/**
* Create a blog post.
*