Merge branch 'MDL-63632-master' of git://github.com/andrewnicols/moodle
authorEloy Lafuente (stronk7) <stronk7@moodle.org>
Thu, 18 Oct 2018 00:38:57 +0000 (02:38 +0200)
committerEloy Lafuente (stronk7) <stronk7@moodle.org>
Thu, 18 Oct 2018 00:38:57 +0000 (02:38 +0200)
mod/forum/classes/privacy/provider.php
mod/forum/tests/privacy_provider_test.php

index c26c307..8c9b416 100644 (file)
@@ -771,6 +771,7 @@ class provider implements
         $DB->delete_records('forum_track_prefs', ['forumid' => $forumid]);
         $DB->delete_records('forum_subscriptions', ['forum' => $forumid]);
         $DB->delete_records('forum_read', ['forumid' => $forumid]);
+        $DB->delete_records('forum_digests', ['forum' => $forumid]);
 
         // Delete all discussion items.
         $DB->delete_records_select(
@@ -831,6 +832,11 @@ class provider implements
                 'userid' => $userid,
             ]);
 
+            $DB->delete_records('forum_digests', [
+                'forum' => $forum->id,
+                'userid' => $userid,
+            ]);
+
             // Delete all discussion items.
             $DB->delete_records_select(
                 'forum_queue',
@@ -846,48 +852,39 @@ class provider implements
                 'userid' => $userid,
             ]);
 
-            $uniquediscussions = $DB->get_recordset('forum_discussions', [
-                    'forum' => $forum->id,
-                    'userid' => $userid,
-                ]);
-
-            foreach ($uniquediscussions as $discussion) {
-                // Do not delete discussion or forum posts.
-                // Instead update them to reflect that the content has been deleted.
-                $postsql = "userid = :userid AND discussion IN (SELECT id FROM {forum_discussions} WHERE forum = :forum)";
-                $postidsql = "SELECT fp.id FROM {forum_posts} fp WHERE {$postsql}";
-                $postparams = [
-                    'forum' => $forum->id,
-                    'userid' => $userid,
-                ];
-
-                // Update the subject.
-                $DB->set_field_select('forum_posts', 'subject', '', $postsql, $postparams);
+            // Do not delete discussion or forum posts.
+            // Instead update them to reflect that the content has been deleted.
+            $postsql = "userid = :userid AND discussion IN (SELECT id FROM {forum_discussions} WHERE forum = :forum)";
+            $postidsql = "SELECT fp.id FROM {forum_posts} fp WHERE {$postsql}";
+            $postparams = [
+                'forum' => $forum->id,
+                'userid' => $userid,
+            ];
 
-                // Update the subject and its format.
-                $DB->set_field_select('forum_posts', 'message', '', $postsql, $postparams);
-                $DB->set_field_select('forum_posts', 'messageformat', FORMAT_PLAIN, $postsql, $postparams);
+            // Update the subject.
+            $DB->set_field_select('forum_posts', 'subject', '', $postsql, $postparams);
 
-                // Mark the post as deleted.
-                $DB->set_field_select('forum_posts', 'deleted', 1, $postsql, $postparams);
+            // Update the message and its format.
+            $DB->set_field_select('forum_posts', 'message', '', $postsql, $postparams);
+            $DB->set_field_select('forum_posts', 'messageformat', FORMAT_PLAIN, $postsql, $postparams);
 
-                // Note: Do _not_ delete ratings of other users. Only delete ratings on the users own posts.
-                // Ratings are aggregate fields and deleting the rating of this post will have an effect on the rating
-                // of any post.
-                \core_rating\privacy\provider::delete_ratings_select($context, 'mod_forum', 'post',
-                        "IN ($postidsql)", $postparams);
+            // Mark the post as deleted.
+            $DB->set_field_select('forum_posts', 'deleted', 1, $postsql, $postparams);
 
-                // Delete all Tags.
-                \core_tag\privacy\provider::delete_item_tags_select($context, 'mod_forum', 'forum_posts',
-                        "IN ($postidsql)", $postparams);
+            // Note: Do _not_ delete ratings of other users. Only delete ratings on the users own posts.
+            // Ratings are aggregate fields and deleting the rating of this post will have an effect on the rating
+            // of any post.
+            \core_rating\privacy\provider::delete_ratings_select($context, 'mod_forum', 'post',
+                    "IN ($postidsql)", $postparams);
 
-                // Delete all files from the posts.
-                $fs = get_file_storage();
-                $fs->delete_area_files_select($context->id, 'mod_forum', 'post', "IN ($postidsql)", $postparams);
-                $fs->delete_area_files_select($context->id, 'mod_forum', 'attachment', "IN ($postidsql)", $postparams);
-            }
+            // Delete all Tags.
+            \core_tag\privacy\provider::delete_item_tags_select($context, 'mod_forum', 'forum_posts',
+                    "IN ($postidsql)", $postparams);
 
-            $uniquediscussions->close();
+            // Delete all files from the posts.
+            $fs = get_file_storage();
+            $fs->delete_area_files_select($context->id, 'mod_forum', 'post', "IN ($postidsql)", $postparams);
+            $fs->delete_area_files_select($context->id, 'mod_forum', 'attachment', "IN ($postidsql)", $postparams);
         }
     }
 }
index d9a0add..9be037a 100644 (file)
@@ -165,6 +165,8 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
      * information returned.
      */
     public function test_user_has_never_posted_subscribed_to_forum() {
+        global $DB;
+
         // Create a course, with a forum, our user under test, another user, and a discussion + post from the other user.
         $course = $this->getDataGenerator()->create_course();
         $this->getDataGenerator()->create_module('forum', ['course' => $course->id]);
@@ -199,6 +201,17 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
 
         // There should be data about the forum itself.
         $this->assertNotEmpty($writer->get_data($subcontext));
+
+        // Delete the data now.
+        // Only the post by the user under test will be removed.
+        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
+            \core_user::get_user($user->id),
+            'mod_forum',
+            [$context->id]
+        );
+        $this->assertCount(1, $DB->get_records('forum_subscriptions', ['userid' => $user->id]));
+        provider::delete_data_for_user($approvedcontextlist);
+        $this->assertCount(0, $DB->get_records('forum_subscriptions', ['userid' => $user->id]));
     }
 
     /**
@@ -207,6 +220,8 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
      * information returned.
      */
     public function test_user_has_never_posted_subscribed_to_discussion() {
+        global $DB;
+
         // Create a course, with a forum, our user under test, another user, and a discussion + post from the other user.
         $course = $this->getDataGenerator()->create_course();
         $this->getDataGenerator()->create_module('forum', ['course' => $course->id]);
@@ -256,6 +271,17 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
         // Post content is not exported unless the user participated.
         $postsubcontext = $this->get_subcontext($forum, $discussion, $post);
         $this->assertCount(0, $writer->get_data($postsubcontext));
+
+        // Delete the data now.
+        // Only the post by the user under test will be removed.
+        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
+            \core_user::get_user($user->id),
+            'mod_forum',
+            [$context->id]
+        );
+        $this->assertCount(1, $DB->get_records('forum_discussion_subs', ['userid' => $user->id]));
+        provider::delete_data_for_user($approvedcontextlist);
+        $this->assertCount(0, $DB->get_records('forum_discussion_subs', ['userid' => $user->id]));
     }
 
     /**
@@ -296,8 +322,8 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
     }
 
     /**
-     * Test that a user who has posted a reply to another users discussion
-     * will have all content returned.
+     * Test that a user who has posted a reply to another users discussion will have all content returned, and
+     * appropriate content removed.
      */
     public function test_user_has_posted_reply() {
         global $DB;
@@ -347,6 +373,25 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
 
         // The reply will be included.
         $this->assert_post_data($reply, $writer->get_data($this->get_subcontext($forum, $discussion, $reply)), $writer);
+
+        // Delete the data now.
+        // Only the post by the user under test will be removed.
+        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
+            \core_user::get_user($user->id),
+            'mod_forum',
+            [$context->id]
+        );
+        provider::delete_data_for_user($approvedcontextlist);
+
+        $reply = $DB->get_record('forum_posts', ['id' => $reply->id]);
+        $this->assertEmpty($reply->subject);
+        $this->assertEmpty($reply->message);
+        $this->assertEquals(1, $reply->deleted);
+
+        $post = $DB->get_record('forum_posts', ['id' => $post->id]);
+        $this->assertNotEmpty($post->subject);
+        $this->assertNotEmpty($post->message);
+        $this->assertEquals(0, $post->deleted);
     }
 
     /**
@@ -354,6 +399,8 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
      * rater's information returned.
      */
     public function test_user_has_rated_others() {
+        global $DB;
+
         $course = $this->getDataGenerator()->create_course();
         $forum = $this->getDataGenerator()->create_module('forum', [
             'course' => $course->id,
@@ -404,12 +451,26 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
 
         // The original post will not be included.
         $this->assert_post_data($post, $writer->get_data($this->get_subcontext($forum, $discussion, $post)), $writer);
+
+        // Delete the data of the user who rated the other user.
+        // The rating should not be deleted as it the rating is considered grading data.
+        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
+            \core_user::get_user($user->id),
+            'mod_forum',
+            [$context->id]
+        );
+        provider::delete_data_for_user($approvedcontextlist);
+
+        // Ratings should remain as they are of another user's content.
+        $this->assertCount(1, $DB->get_records('rating', ['itemid' => $post->id]));
     }
 
     /**
      * Test that ratings of a users own content will all be returned.
      */
     public function test_user_has_been_rated() {
+        global $DB;
+
         $course = $this->getDataGenerator()->create_course();
         $forum = $this->getDataGenerator()->create_module('forum', [
             'course' => $course->id,
@@ -457,12 +518,26 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
             'post',
             $post->id
         );
+
+        // Delete the data of the user who was rated.
+        // The rating should now be deleted.
+        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
+            \core_user::get_user($user->id),
+            'mod_forum',
+            [$context->id]
+        );
+        provider::delete_data_for_user($approvedcontextlist);
+
+        // Ratings should remain as they are of another user's content.
+        $this->assertCount(0, $DB->get_records('rating', ['itemid' => $post->id]));
     }
 
     /**
      * Test that per-user daily digest settings are included correctly.
      */
     public function test_user_forum_digest() {
+        global $DB;
+
         $course = $this->getDataGenerator()->create_course();
 
         $forum0 = $this->getDataGenerator()->create_module('forum', ['course' => $course->id]);
@@ -514,12 +589,30 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
 
         $this->export_context_data_for_user($user->id, $context2, 'mod_forum');
         $this->assertEquals(2, \core_privacy\local\request\writer::with_context($context2)->get_metadata([], 'digestpreference'));
+
+        // Delete the data for one of the users in one of the forums.
+        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
+            \core_user::get_user($user->id),
+            'mod_forum',
+            [$context1->id]
+        );
+
+        $this->assertEquals(0, $DB->get_field('forum_digests', 'maildigest', ['userid' => $user->id, 'forum' => $forum0->id]));
+        $this->assertEquals(1, $DB->get_field('forum_digests', 'maildigest', ['userid' => $user->id, 'forum' => $forum1->id]));
+        $this->assertEquals(2, $DB->get_field('forum_digests', 'maildigest', ['userid' => $user->id, 'forum' => $forum2->id]));
+        provider::delete_data_for_user($approvedcontextlist);
+        $this->assertEquals(0, $DB->get_field('forum_digests', 'maildigest', ['userid' => $user->id, 'forum' => $forum0->id]));
+        $this->assertFalse($DB->get_field('forum_digests', 'maildigest', ['userid' => $user->id, 'forum' => $forum1->id]));
+        $this->assertEquals(2, $DB->get_field('forum_digests', 'maildigest', ['userid' => $user->id, 'forum' => $forum2->id]));
+
     }
 
     /**
      * Test that the per-user, per-forum user tracking data is exported.
      */
     public function test_user_tracking_data() {
+        global $DB;
+
         $course = $this->getDataGenerator()->create_course();
 
         $forumoff = $this->getDataGenerator()->create_module('forum', ['course' => $course->id]);
@@ -548,6 +641,33 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
         $this->export_context_data_for_user($user->id, $contextoff, 'mod_forum');
         $this->assertEquals(0,
                 \core_privacy\local\request\writer::with_context($contextoff)->get_metadata([], 'trackreadpreference'));
+
+        // Delete the data for one of the users in the 'on' forum.
+        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
+            \core_user::get_user($user->id),
+            'mod_forum',
+            [$contexton->id]
+        );
+
+        $this->assertTrue($DB->record_exists('forum_track_prefs', ['userid' => $user->id, 'forumid' => $forumoff->id]));
+        $this->assertFalse($DB->record_exists('forum_track_prefs', ['userid' => $user->id, 'forumid' => $forumon->id]));
+
+        provider::delete_data_for_user($approvedcontextlist);
+
+        $this->assertTrue($DB->record_exists('forum_track_prefs', ['userid' => $user->id, 'forumid' => $forumoff->id]));
+        $this->assertFalse($DB->record_exists('forum_track_prefs', ['userid' => $user->id, 'forumid' => $forumon->id]));
+
+        // Delete the data for one of the users in the 'off' forum.
+        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
+            \core_user::get_user($user->id),
+            'mod_forum',
+            [$contextoff->id]
+        );
+
+        provider::delete_data_for_user($approvedcontextlist);
+
+        $this->assertFalse($DB->record_exists('forum_track_prefs', ['userid' => $user->id, 'forumid' => $forumoff->id]));
+        $this->assertFalse($DB->record_exists('forum_track_prefs', ['userid' => $user->id, 'forumid' => $forumon->id]));
     }
 
     /**
@@ -708,6 +828,23 @@ class mod_forum_privacy_provider_testcase extends \core_privacy\tests\provider_t
         $this->assertNotEmpty($readdata);
         $this->assertTrue(isset($readdata->firstread));
         $this->assertTrue(isset($readdata->lastread));
+
+        // Delete all data for one of the users in one of the forums.
+        $approvedcontextlist = new \core_privacy\tests\request\approved_contextlist(
+            \core_user::get_user($user->id),
+            'mod_forum',
+            [$context3->id]
+        );
+
+        $this->assertTrue($DB->record_exists('forum_read', ['userid' => $user->id, 'forumid' => $forum1->id]));
+        $this->assertTrue($DB->record_exists('forum_read', ['userid' => $user->id, 'forumid' => $forum2->id]));
+        $this->assertTrue($DB->record_exists('forum_read', ['userid' => $user->id, 'forumid' => $forum3->id]));
+
+        provider::delete_data_for_user($approvedcontextlist);
+
+        $this->assertTrue($DB->record_exists('forum_read', ['userid' => $user->id, 'forumid' => $forum1->id]));
+        $this->assertTrue($DB->record_exists('forum_read', ['userid' => $user->id, 'forumid' => $forum2->id]));
+        $this->assertFalse($DB->record_exists('forum_read', ['userid' => $user->id, 'forumid' => $forum3->id]));
     }
 
     /**