From e5ec530a4438d6fac2d6179a96df2bea044cbc0d Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Wed, 2 May 2018 10:26:52 +0800 Subject: [PATCH] MDL-61937 rating: delete method in privacy provider --- rating/classes/privacy/provider.php | 54 +++++++++++++++++ rating/tests/privacy_provider_test.php | 82 ++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) diff --git a/rating/classes/privacy/provider.php b/rating/classes/privacy/provider.php index 2bb3c0349fe..1bab73b54d9 100644 --- a/rating/classes/privacy/provider.php +++ b/rating/classes/privacy/provider.php @@ -159,4 +159,58 @@ class provider implements ]; return $return; } + + /** + * Deletes all ratings for a specified context, component, ratingarea and itemid. + * + * Only delete ratings when the item itself was deleted. + * + * We never delete ratings for one user but not others - this may affect grades, therefore ratings + * made by particular user are not considered personal information. + * + * @param \context $context Details about which context to delete ratings for. + * @param string $component Component to delete. + * @param string $ratingarea Rating area to delete. + * @param int $itemid The item ID for use with deletion. + */ + public static function delete_ratings(\context $context, string $component = null, + string $ratingarea = null, int $itemid = null) { + global $DB; + + $options = ['contextid' => $context->id]; + if ($component) { + $options['component'] = $component; + } + if ($ratingarea) { + $options['ratingarea'] = $ratingarea; + } + if ($itemid) { + $options['itemid'] = $itemid; + } + + $DB->delete_records('rating', $options); + } + + /** + * Deletes all tag instances for given context, component, itemtype using subquery for itemids + * + * In most situations you will want to specify $userid as null. Per-user tag instances + * are possible in Tags API, however there are no components or standard plugins that actually use them. + * + * @param \context $context Details about which context to delete ratings for. + * @param string $component Component to delete. + * @param string $ratingarea Rating area to delete. + * @param string $itemidstest an SQL fragment that the itemid must match. Used + * in the query like WHERE itemid $itemidstest. Must use named parameters, + * and may not use named parameters called contextid, component or ratingarea. + * @param array $params any query params used by $itemidstest. + */ + public static function delete_ratings_select(\context $context, string $component, + string $ratingarea, $itemidstest, $params = []) { + global $DB; + $params += ['contextid' => $context->id, 'component' => $component, 'ratingarea' => $ratingarea]; + $DB->delete_records_select('rating', + 'contextid = :contextid AND component = :component AND ratingarea = :ratingarea AND itemid ' . $itemidstest, + $params); + } } diff --git a/rating/tests/privacy_provider_test.php b/rating/tests/privacy_provider_test.php index e68e855683a..7f0fb179331 100644 --- a/rating/tests/privacy_provider_test.php +++ b/rating/tests/privacy_provider_test.php @@ -246,6 +246,88 @@ class core_rating_privacy_testcase extends \core_privacy\tests\provider_testcase $this->assert_has_rating($u2, 20, $result); } + /** + * Test delete_ratings() method. + */ + public function test_delete_ratings() { + global $DB; + $this->resetAfterTest(); + + $course1 = $this->getDataGenerator()->create_course(); + $course2 = $this->getDataGenerator()->create_course(); + $course3 = $this->getDataGenerator()->create_course(); + + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + + // Rate all courses as u1, and something else in the same context. + $this->rate_as_user($u1->id, 'core_course', 'course', $course1->id, \context_course::instance($course1->id), 25); + $this->rate_as_user($u1->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 50); + $this->rate_as_user($u1->id, 'core_course', 'course', $course3->id, \context_course::instance($course3->id), 75); + $this->rate_as_user($u1->id, 'core_course', 'files', $course3->id, \context_course::instance($course3->id), 99); + $this->rate_as_user($u1->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 10); + + // Rate course2 as u2, and something else in a different context/component.. + $this->rate_as_user($u2->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 90); + $this->rate_as_user($u2->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 20); + + // Delete all ratings in course1. + $expectedratingscount = $DB->count_records('rating'); + core_rating\privacy\provider::delete_ratings(\context_course::instance($course1->id)); + $expectedratingscount -= 1; + $this->assertEquals($expectedratingscount, $DB->count_records('rating')); + + // Delete ratings in course2 specifying wrong component. + core_rating\privacy\provider::delete_ratings(\context_course::instance($course2->id), 'other_component'); + $this->assertEquals($expectedratingscount, $DB->count_records('rating')); + + // Delete ratings in course2 specifying correct component. + core_rating\privacy\provider::delete_ratings(\context_course::instance($course2->id), 'core_course'); + $expectedratingscount -= 2; + $this->assertEquals($expectedratingscount, $DB->count_records('rating')); + + // Delete user ratings specifyng all attributes. + core_rating\privacy\provider::delete_ratings(\context_user::instance($u3->id), 'core_user', 'user', $u3->id); + $expectedratingscount -= 2; + $this->assertEquals($expectedratingscount, $DB->count_records('rating')); + } + + /** + * Test delete_ratings_select() method. + */ + public function test_delete_ratings_select() { + global $DB; + $this->resetAfterTest(); + + $course1 = $this->getDataGenerator()->create_course(); + $course2 = $this->getDataGenerator()->create_course(); + $course3 = $this->getDataGenerator()->create_course(); + + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + + // Rate all courses as u1, and something else in the same context. + $this->rate_as_user($u1->id, 'core_course', 'course', $course1->id, \context_course::instance($course1->id), 25); + $this->rate_as_user($u1->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 50); + $this->rate_as_user($u1->id, 'core_course', 'course', $course3->id, \context_course::instance($course3->id), 75); + $this->rate_as_user($u1->id, 'core_course', 'files', $course3->id, \context_course::instance($course3->id), 99); + $this->rate_as_user($u1->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 10); + + // Rate course2 as u2, and something else in a different context/component.. + $this->rate_as_user($u2->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 90); + $this->rate_as_user($u2->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 20); + + // Delete ratings in course1. + list($sql, $params) = $DB->get_in_or_equal([$course1->id, $course2->id], SQL_PARAMS_NAMED); + $expectedratingscount = $DB->count_records('rating'); + core_rating\privacy\provider::delete_ratings_select(\context_course::instance($course1->id), + 'core_course', 'course', $sql, $params); + $expectedratingscount -= 1; + $this->assertEquals($expectedratingscount, $DB->count_records('rating')); + } + /** * Assert that a user has the correct rating. *