Merge branch 'MDL-64652-master' of git://github.com/andrewnicols/moodle

This commit is contained in:
Jun Pataleta
2019-03-05 11:14:04 +08:00
6 changed files with 362 additions and 92 deletions
+4
View File
@@ -11,6 +11,10 @@ attribute on forms to avoid collisions in forms loaded in AJAX requests.
to be updated or queued as required. This new functionality can be found in \core\task\manager::reschedule_or_queue_adhoc_task.
* Icons are displayed for screen readers unless they have empty alt text (aria-hidden). Do not provide an icon with alt text immediately beside an element with exactly the same text.
* admin_settingpage has a new function hide_if(), modeled after the same functionality in the forms library. This allows admin settings to be dynamically hidden based on the values of other settings.
* The \core_rating provider's get_sql_join function now accepts an optional $innerjoin parameter.
It is recommended that privacy providers using this function call rewrite any long query into a number of separate
calls to add_from_sql for improved performance, and that the new argument is used.
This will allow queries to remain backwards-compatible with older versions of Moodle but will have significantly better performance in version supporting the innerjoin parameter.
=== 3.6 ===
+44 -16
View File
@@ -103,29 +103,57 @@ class provider implements
* @return contextlist the list of contexts containing user info for the user.
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
// Fetch all data records.
$contextlist = new contextlist();
// Fetch all data records that the user rote.
$sql = "SELECT c.id
FROM {context} c
INNER JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
INNER JOIN {modules} m ON m.id = cm.module AND m.name = :modname
INNER JOIN {data} d ON d.id = cm.instance
INNER JOIN {data_records} dr ON dr.dataid = d.id
LEFT JOIN {comments} com ON com.commentarea=:commentarea and com.itemid = dr.id AND com.userid = :userid1
LEFT JOIN {rating} r ON r.contextid = c.id AND r.itemid = dr.id AND r.component = :moddata
AND r.ratingarea = :ratingarea AND r.userid = :userid2
WHERE dr.userid = :userid OR com.id IS NOT NULL OR r.id IS NOT NULL";
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {data} d ON d.id = cm.instance
JOIN {data_records} dr ON dr.dataid = d.id
WHERE dr.userid = :userid";
$params = [
'modname' => 'data',
'contextlevel' => CONTEXT_MODULE,
'modname' => 'data',
'userid' => $userid,
'userid1' => $userid,
'userid2' => $userid,
'commentarea' => 'database_entry',
'moddata' => 'mod_data',
'ratingarea' => 'entry',
];
$contextlist = new contextlist();
$contextlist->add_from_sql($sql, $params);
// Fetch contexts where the user commented.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {data} d ON d.id = cm.instance
JOIN {data_records} dr ON dr.dataid = d.id
JOIN {comments} com ON com.commentarea = :commentarea and com.itemid = dr.id
WHERE com.userid = :userid";
$params = [
'contextlevel' => CONTEXT_MODULE,
'modname' => 'data',
'commentarea' => 'database_entry',
'userid' => $userid,
];
$contextlist->add_from_sql($sql, $params);
// Fetch all data records.
$ratingquery = \core_rating\privacy\provider::get_sql_join('r', 'mod_data', 'entry', 'dr.id', $userid, true);
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {data} d ON d.id = cm.instance
JOIN {data_records} dr ON dr.dataid = d.id
{$ratingquery->join}
WHERE {$ratingquery->userwhere}";
$params = [
'contextlevel' => CONTEXT_MODULE,
'modname' => 'data',
] + $ratingquery->params;
$contextlist->add_from_sql($sql, $params);
return $contextlist;
+162 -56
View File
@@ -152,46 +152,105 @@ class provider implements
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid(int $userid) : \core_privacy\local\request\contextlist {
$ratingsql = \core_rating\privacy\provider::get_sql_join('rat', 'mod_forum', 'post', 'p.id', $userid);
// Fetch all forum discussions, and forum posts.
$contextlist = new \core_privacy\local\request\contextlist();
$params = [
'modname' => 'forum',
'contextlevel' => CONTEXT_MODULE,
'userid' => $userid,
];
// Discussion creators.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {forum} f ON f.id = cm.instance
LEFT JOIN {forum_discussions} d ON d.forum = f.id
LEFT JOIN {forum_posts} p ON p.discussion = d.id
LEFT JOIN {forum_digests} dig ON dig.forum = f.id AND dig.userid = :digestuserid
LEFT JOIN {forum_subscriptions} sub ON sub.forum = f.id AND sub.userid = :subuserid
LEFT JOIN {forum_track_prefs} pref ON pref.forumid = f.id AND pref.userid = :prefuserid
LEFT JOIN {forum_read} hasread ON hasread.forumid = f.id AND hasread.userid = :hasreaduserid
LEFT JOIN {forum_discussion_subs} dsub ON dsub.forum = f.id AND dsub.userid = :dsubuserid
{$ratingsql->join}
WHERE (
p.userid = :postuserid OR
d.userid = :discussionuserid OR
dig.id IS NOT NULL OR
sub.id IS NOT NULL OR
pref.id IS NOT NULL OR
hasread.id IS NOT NULL OR
dsub.id IS NOT NULL OR
{$ratingsql->userwhere}
)
JOIN {forum_discussions} d ON d.forum = f.id
WHERE d.userid = :userid
";
$params = [
'modname' => 'forum',
'contextlevel' => CONTEXT_MODULE,
'postuserid' => $userid,
'discussionuserid' => $userid,
'digestuserid' => $userid,
'subuserid' => $userid,
'prefuserid' => $userid,
'hasreaduserid' => $userid,
'dsubuserid' => $userid,
];
$params += $ratingsql->params;
$contextlist->add_from_sql($sql, $params);
$contextlist = new \core_privacy\local\request\contextlist();
// Post authors.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_discussions} d ON d.forum = f.id
JOIN {forum_posts} p ON p.discussion = d.id
WHERE p.userid = :userid
";
$contextlist->add_from_sql($sql, $params);
// Forum digest records.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_digests} dig ON dig.forum = f.id
WHERE dig.userid = :userid
";
$contextlist->add_from_sql($sql, $params);
// Forum subscriptions.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_subscriptions} sub ON sub.forum = f.id
WHERE sub.userid = :userid
";
$contextlist->add_from_sql($sql, $params);
// Discussion subscriptions.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_discussion_subs} dsub ON dsub.forum = f.id
WHERE dsub.userid = :userid
";
$contextlist->add_from_sql($sql, $params);
// Discussion tracking preferences.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_track_prefs} pref ON pref.forumid = f.id
WHERE pref.userid = :userid
";
$contextlist->add_from_sql($sql, $params);
// Discussion read records.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_read} hasread ON hasread.forumid = f.id
WHERE hasread.userid = :userid
";
$contextlist->add_from_sql($sql, $params);
// Rating authors.
$ratingsql = \core_rating\privacy\provider::get_sql_join('rat', 'mod_forum', 'post', 'p.id', $userid, true);
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_discussions} d ON d.forum = f.id
JOIN {forum_posts} p ON p.discussion = d.id
{$ratingsql->join}
WHERE {$ratingsql->userwhere}
";
$params += $ratingsql->params;
$contextlist->add_from_sql($sql, $params);
return $contextlist;
@@ -365,30 +424,68 @@ class provider implements
$userid = $user->id;
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
$params = $contextparams;
// Digested forums.
$sql = "SELECT
c.id AS contextid,
dig.maildigest AS maildigest
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_digests} dig ON dig.forum = f.id
WHERE (
dig.userid = :userid AND
c.id {$contextsql}
)
";
$params['userid'] = $userid;
$digests = $DB->get_records_sql_menu($sql, $params);
// Forum subscriptions.
$sql = "SELECT
c.id AS contextid,
sub.userid AS subscribed
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid
JOIN {forum} f ON f.id = cm.instance
JOIN {forum_subscriptions} sub ON sub.forum = f.id
WHERE (
sub.userid = :userid AND
c.id {$contextsql}
)
";
$params['userid'] = $userid;
$subscriptions = $DB->get_records_sql_menu($sql, $params);
// Tracked forums.
$sql = "SELECT
c.id AS contextid,
f.*,
cm.id AS cmid,
dig.maildigest,
sub.userid AS subscribed,
pref.userid AS tracked
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid
JOIN {forum} f ON f.id = cm.instance
LEFT JOIN {forum_digests} dig ON dig.forum = f.id AND dig.userid = :digestuserid
LEFT JOIN {forum_subscriptions} sub ON sub.forum = f.id AND sub.userid = :subuserid
LEFT JOIN {forum_track_prefs} pref ON pref.forumid = f.id AND pref.userid = :prefuserid
JOIN {forum_track_prefs} pref ON pref.forumid = f.id
WHERE (
pref.userid = :userid AND
c.id {$contextsql}
)
";
$params['userid'] = $userid;
$tracked = $DB->get_records_sql_menu($sql, $params);
$sql = "SELECT
c.id AS contextid,
f.*,
cm.id AS cmid
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid
JOIN {forum} f ON f.id = cm.instance
WHERE (
c.id {$contextsql}
)
";
$params = [
'digestuserid' => $userid,
'subuserid' => $userid,
'prefuserid' => $userid,
];
$params += $contextparams;
// Keep a mapping of forumid to contextid.
@@ -407,9 +504,15 @@ class provider implements
request_helper::export_context_files($context, $user);
// Store relevant metadata about this forum instance.
static::export_digest_data($userid, $forum);
static::export_subscription_data($userid, $forum);
static::export_tracking_data($userid, $forum);
if (isset($digests[$forum->contextid])) {
static::export_digest_data($userid, $forum, $digests[$forum->contextid]);
}
if (isset($subscriptions[$forum->contextid])) {
static::export_subscription_data($userid, $forum, $subscriptions[$forum->contextid]);
}
if (isset($tracked[$forum->contextid])) {
static::export_tracking_data($userid, $forum, $tracked[$forum->contextid]);
}
}
$forums->close();
@@ -704,16 +807,17 @@ class provider implements
*
* @param int $userid The userid of the user whose data is to be exported.
* @param \stdClass $forum The forum whose data is being exported.
* @param int $maildigest The mail digest setting for this forum.
* @return bool Whether any data was stored.
*/
protected static function export_digest_data(int $userid, \stdClass $forum) {
if (null !== $forum->maildigest) {
protected static function export_digest_data(int $userid, \stdClass $forum, int $maildigest) {
if (null !== $maildigest) {
// The user has a specific maildigest preference for this forum.
$a = (object) [
'forum' => format_string($forum->name, true),
];
switch ($forum->maildigest) {
switch ($maildigest) {
case 0:
$a->type = get_string('emaildigestoffshort', 'mod_forum');
break;
@@ -726,7 +830,7 @@ class provider implements
}
writer::with_context(\context_module::instance($forum->cmid))
->export_metadata([], 'digestpreference', $forum->maildigest,
->export_metadata([], 'digestpreference', $maildigest,
get_string('privacy:digesttypepreference', 'mod_forum', $a));
return true;
@@ -740,10 +844,11 @@ class provider implements
*
* @param int $userid The userid of the user whose data is to be exported.
* @param \stdClass $forum The forum whose data is being exported.
* @param int $subscribed if the user is subscribed
* @return bool Whether any data was stored.
*/
protected static function export_subscription_data(int $userid, \stdClass $forum) {
if (null !== $forum->subscribed) {
protected static function export_subscription_data(int $userid, \stdClass $forum, int $subscribed) {
if (null !== $subscribed) {
// The user is subscribed to this forum.
writer::with_context(\context_module::instance($forum->cmid))
->export_metadata([], 'subscriptionpreference', 1, get_string('privacy:subscribedtoforum', 'mod_forum'));
@@ -798,10 +903,11 @@ class provider implements
*
* @param int $userid The userid of the user whose data is to be exported.
* @param \stdClass $forum The forum whose data is being exported.
* @param int $tracke if the user is subscribed
* @return bool Whether any data was stored.
*/
protected static function export_tracking_data(int $userid, \stdClass $forum) {
if (null !== $forum->tracked) {
protected static function export_tracking_data(int $userid, \stdClass $forum, int $tracked) {
if (null !== $tracked) {
// The user has a main preference to track all forums, but has opted out of this one.
writer::with_context(\context_module::instance($forum->cmid))
->export_metadata([], 'trackreadpreference', 0, get_string('privacy:readtrackingdisabled', 'mod_forum'));
+40 -11
View File
@@ -80,26 +80,55 @@ class provider implements
* @return contextlist the list of contexts containing user info for the user.
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
$ratingquery = \core_rating\privacy\provider::get_sql_join('r', 'mod_glossary', 'entry', 'ge.id', $userid);
$contextlist = new contextlist();
// Glossary entries.
$sql = "SELECT c.id
FROM {context} c
INNER JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
INNER JOIN {modules} m ON m.id = cm.module AND m.name = :modname
INNER JOIN {glossary} g ON g.id = cm.instance
INNER JOIN {glossary_entries} ge ON ge.glossaryid = g.id
LEFT JOIN {comments} com ON com.commentarea =:commentarea AND com.itemid = ge.id
{$ratingquery->join}
WHERE ge.userid = :glossaryentryuserid OR com.userid = :commentuserid OR {$ratingquery->userwhere}";
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {glossary} g ON g.id = cm.instance
JOIN {glossary_entries} ge ON ge.glossaryid = g.id
WHERE ge.userid = :glossaryentryuserid";
$params = [
'contextlevel' => CONTEXT_MODULE,
'modname' => 'glossary',
'commentarea' => 'glossary_entry',
'glossaryentryuserid' => $userid,
'commentuserid' => $userid,
] + $ratingquery->params;
];
$contextlist->add_from_sql($sql, $params);
$contextlist = new contextlist();
// Where the user has rated something.
$ratingquery = \core_rating\privacy\provider::get_sql_join('r', 'mod_glossary', 'entry', 'ge.id', $userid, true);
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {glossary} g ON g.id = cm.instance
JOIN {glossary_entries} ge ON ge.glossaryid = g.id
{$ratingquery->join}
WHERE {$ratingquery->userwhere}";
$params = [
'contextlevel' => CONTEXT_MODULE,
'modname' => 'glossary',
] + $ratingquery->params;
$contextlist->add_from_sql($sql, $params);
// Comments.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {glossary} g ON g.id = cm.instance
JOIN {glossary_entries} ge ON ge.glossaryid = g.id
JOIN {comments} com ON com.commentarea =:commentarea AND com.itemid = ge.id
WHERE com.userid = :commentuserid";
$params = [
'contextlevel' => CONTEXT_MODULE,
'modname' => 'glossary',
'commentarea' => 'glossary_entry',
'commentuserid' => $userid,
];
$contextlist->add_from_sql($sql, $params);
return $contextlist;
+24 -9
View File
@@ -129,26 +129,41 @@ class provider implements
/**
* Get the SQL required to find all submission items where this user has had any involvements.
*
* If possible an inner join should be used.
*
* @param string $alias The name of the table alias to use.
* @param string $component The na eof the component to fetch ratings for.
* @param string $ratingarea The rating area to fetch results for.
* @param string $itemidjoin The right-hand-side of the JOIN ON clause.
* @param int $userid The ID of the user being stored.
* @param bool $innerjoin Whether to use an inner join (preferred)
* @return \stdClass
*/
public static function get_sql_join($alias, $component, $ratingarea, $itemidjoin, $userid) {
public static function get_sql_join($alias, $component, $ratingarea, $itemidjoin, $userid, $innerjoin = false) {
static $count = 0;
$count++;
// Join the rating table with the specified alias and the relevant join params.
$join = "LEFT JOIN {rating} {$alias} ON ";
$join .= "{$alias}.userid = :ratinguserid{$count} AND ";
$join .= "{$alias}.component = :ratingcomponent{$count} AND ";
$join .= "{$alias}.ratingarea = :ratingarea{$count} AND ";
$join .= "{$alias}.itemid = {$itemidjoin}";
$userwhere = '';
// Match against the specified user.
$userwhere = "{$alias}.id IS NOT NULL";
if ($innerjoin) {
// Join the rating table with the specified alias and the relevant join params.
$join = "JOIN {rating} {$alias} ON ";
$join .= "{$alias}.itemid = {$itemidjoin}";
$userwhere .= "{$alias}.userid = :ratinguserid{$count} AND ";
$userwhere .= "{$alias}.component = :ratingcomponent{$count} AND ";
$userwhere .= "{$alias}.ratingarea = :ratingarea{$count}";
} else {
// Join the rating table with the specified alias and the relevant join params.
$join = "LEFT JOIN {rating} {$alias} ON ";
$join .= "{$alias}.userid = :ratinguserid{$count} AND ";
$join .= "{$alias}.component = :ratingcomponent{$count} AND ";
$join .= "{$alias}.ratingarea = :ratingarea{$count} AND ";
$join .= "{$alias}.itemid = {$itemidjoin}";
// Match against the specified user.
$userwhere = "{$alias}.id IS NOT NULL";
}
$params = [
'ratingcomponent' . $count => $component,
+88
View File
@@ -153,6 +153,94 @@ class core_rating_privacy_testcase extends \core_privacy\tests\provider_testcase
$this->assertFalse(isset($courses[$course3->id]));
}
/**
* Ensure that the get_sql_join function returns valid SQL which returns the correct list of rated itemids.
* This makes use of the optional inner join argument.
*/
public function test_get_sql_join_inner() {
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 the courses.
$rm = new rating_manager();
$ratingoptions = (object) [
'component' => 'core_course',
'ratingarea' => 'course',
'scaleid' => 100,
];
// 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);
// 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, 'user', 'user', $u3->id, \context_user::instance($u3->id), 10);
// Return any course which the u1 has rated.
// u1 rated all three courses.
$ratingquery = provider::get_sql_join('r', 'core_course', 'course', 'c.id', $u1->id, true);
$sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}";
$courses = $DB->get_records_sql($sql, $ratingquery->params);
$this->assertCount(3, $courses);
$this->assertTrue(isset($courses[$course1->id]));
$this->assertTrue(isset($courses[$course2->id]));
$this->assertTrue(isset($courses[$course3->id]));
// User u1 rated files in course 3 only.
$ratingquery = provider::get_sql_join('r', 'core_course', 'files', 'c.id', $u1->id, true);
$sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}";
$courses = $DB->get_records_sql($sql, $ratingquery->params);
$this->assertCount(1, $courses);
$this->assertFalse(isset($courses[$course1->id]));
$this->assertFalse(isset($courses[$course2->id]));
$this->assertTrue(isset($courses[$course3->id]));
// Return any course which the u2 has rated.
// User u2 rated only course 2.
$ratingquery = provider::get_sql_join('r', 'core_course', 'course', 'c.id', $u2->id, true);
$sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}";
$courses = $DB->get_records_sql($sql, $ratingquery->params);
$this->assertCount(1, $courses);
$this->assertFalse(isset($courses[$course1->id]));
$this->assertTrue(isset($courses[$course2->id]));
$this->assertFalse(isset($courses[$course3->id]));
// User u2 rated u3.
$ratingquery = provider::get_sql_join('r', 'user', 'user', 'u.id', $u2->id, true);
$sql = "SELECT u.id FROM {user} u {$ratingquery->join} WHERE {$ratingquery->userwhere}";
$users = $DB->get_records_sql($sql, $ratingquery->params);
$this->assertCount(1, $users);
$this->assertFalse(isset($users[$u1->id]));
$this->assertFalse(isset($users[$u2->id]));
$this->assertTrue(isset($users[$u3->id]));
// Return any course which the u3 has rated.
// User u3 did not rate anything.
$ratingquery = provider::get_sql_join('r', 'core_course', 'course', 'c.id', $u3->id, true);
$sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}";
$courses = $DB->get_records_sql($sql, $ratingquery->params);
$this->assertCount(0, $courses);
$this->assertFalse(isset($courses[$course1->id]));
$this->assertFalse(isset($courses[$course2->id]));
$this->assertFalse(isset($courses[$course3->id]));
}
/**
* Ensure that export_area_ratings exports all ratings that a user has made, and all ratings for a users own content.
*/