See Release Notes
Long Term Support Release
Differences Between: [Versions 401 and 402] [Versions 401 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Unit tests for the core_rating implementation of the Privacy API. 19 * 20 * @package core_rating 21 * @category test 22 * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk> 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 namespace core_rating\privacy; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 global $CFG; 30 require_once($CFG->dirroot . '/rating/lib.php'); 31 32 use core_rating\privacy\provider; 33 use core_privacy\local\request\writer; 34 35 /** 36 * Unit tests for the core_rating implementation of the Privacy API. 37 * 38 * @copyright 2018 Andrew Nicols <andrew@nicols.co.uk> 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 class provider_test extends \core_privacy\tests\provider_testcase { 42 43 /** 44 * Rate something as a user. 45 * 46 * @param int $userid 47 * @param string $component 48 * @param string $ratingarea 49 * @param int $itemid 50 * @param \context $context 51 * @param string $score 52 */ 53 protected function rate_as_user($userid, $component, $ratingarea, $itemid, $context, $score) { 54 // Rate the courses. 55 $rm = new \rating_manager(); 56 $ratingoptions = (object) [ 57 'component' => $component, 58 'ratingarea' => $ratingarea, 59 'scaleid' => 100, 60 ]; 61 62 // Rate all courses as u1, and the course category too.. 63 $ratingoptions->itemid = $itemid; 64 $ratingoptions->userid = $userid; 65 $ratingoptions->context = $context; 66 $rating = new \rating($ratingoptions); 67 $rating->update_rating($score); 68 } 69 70 /** 71 * Ensure that the get_sql_join function returns valid SQL which returns the correct list of rated itemids. 72 */ 73 public function test_get_sql_join() { 74 global $DB; 75 $this->resetAfterTest(); 76 77 $course1 = $this->getDataGenerator()->create_course(); 78 $course2 = $this->getDataGenerator()->create_course(); 79 $course3 = $this->getDataGenerator()->create_course(); 80 81 $u1 = $this->getDataGenerator()->create_user(); 82 $u2 = $this->getDataGenerator()->create_user(); 83 $u3 = $this->getDataGenerator()->create_user(); 84 85 // Rate the courses. 86 $rm = new \rating_manager(); 87 $ratingoptions = (object) [ 88 'component' => 'core_course', 89 'ratingarea' => 'course', 90 'scaleid' => 100, 91 ]; 92 93 // Rate all courses as u1, and something else in the same context. 94 $this->rate_as_user($u1->id, 'core_course', 'course', $course1->id, \context_course::instance($course1->id), 25); 95 $this->rate_as_user($u1->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 50); 96 $this->rate_as_user($u1->id, 'core_course', 'course', $course3->id, \context_course::instance($course3->id), 75); 97 $this->rate_as_user($u1->id, 'core_course', 'files', $course3->id, \context_course::instance($course3->id), 99); 98 99 // Rate course2 as u2, and something else in a different context/component.. 100 $this->rate_as_user($u2->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 90); 101 $this->rate_as_user($u2->id, 'user', 'user', $u3->id, \context_user::instance($u3->id), 10); 102 103 // Return any course which the u1 has rated. 104 // u1 rated all three courses. 105 $ratingquery = provider::get_sql_join('r', 'core_course', 'course', 'c.id', $u1->id); 106 $sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 107 $courses = $DB->get_records_sql($sql, $ratingquery->params); 108 109 $this->assertCount(3, $courses); 110 $this->assertTrue(isset($courses[$course1->id])); 111 $this->assertTrue(isset($courses[$course2->id])); 112 $this->assertTrue(isset($courses[$course3->id])); 113 114 // User u1 rated files in course 3 only. 115 $ratingquery = provider::get_sql_join('r', 'core_course', 'files', 'c.id', $u1->id); 116 $sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 117 $courses = $DB->get_records_sql($sql, $ratingquery->params); 118 119 $this->assertCount(1, $courses); 120 $this->assertFalse(isset($courses[$course1->id])); 121 $this->assertFalse(isset($courses[$course2->id])); 122 $this->assertTrue(isset($courses[$course3->id])); 123 124 // Return any course which the u2 has rated. 125 // User u2 rated only course 2. 126 $ratingquery = provider::get_sql_join('r', 'core_course', 'course', 'c.id', $u2->id); 127 $sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 128 $courses = $DB->get_records_sql($sql, $ratingquery->params); 129 130 $this->assertCount(1, $courses); 131 $this->assertFalse(isset($courses[$course1->id])); 132 $this->assertTrue(isset($courses[$course2->id])); 133 $this->assertFalse(isset($courses[$course3->id])); 134 135 // User u2 rated u3. 136 $ratingquery = provider::get_sql_join('r', 'user', 'user', 'u.id', $u2->id); 137 $sql = "SELECT u.id FROM {user} u {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 138 $users = $DB->get_records_sql($sql, $ratingquery->params); 139 140 $this->assertCount(1, $users); 141 $this->assertFalse(isset($users[$u1->id])); 142 $this->assertFalse(isset($users[$u2->id])); 143 $this->assertTrue(isset($users[$u3->id])); 144 145 // Return any course which the u3 has rated. 146 // User u3 did not rate anything. 147 $ratingquery = provider::get_sql_join('r', 'core_course', 'course', 'c.id', $u3->id); 148 $sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 149 $courses = $DB->get_records_sql($sql, $ratingquery->params); 150 151 $this->assertCount(0, $courses); 152 $this->assertFalse(isset($courses[$course1->id])); 153 $this->assertFalse(isset($courses[$course2->id])); 154 $this->assertFalse(isset($courses[$course3->id])); 155 } 156 157 /** 158 * Ensure that the get_sql_join function returns valid SQL which returns the correct list of rated itemids. 159 * This makes use of the optional inner join argument. 160 */ 161 public function test_get_sql_join_inner() { 162 global $DB; 163 $this->resetAfterTest(); 164 165 $course1 = $this->getDataGenerator()->create_course(); 166 $course2 = $this->getDataGenerator()->create_course(); 167 $course3 = $this->getDataGenerator()->create_course(); 168 169 $u1 = $this->getDataGenerator()->create_user(); 170 $u2 = $this->getDataGenerator()->create_user(); 171 $u3 = $this->getDataGenerator()->create_user(); 172 173 // Rate the courses. 174 $rm = new \rating_manager(); 175 $ratingoptions = (object) [ 176 'component' => 'core_course', 177 'ratingarea' => 'course', 178 'scaleid' => 100, 179 ]; 180 181 // Rate all courses as u1, and something else in the same context. 182 $this->rate_as_user($u1->id, 'core_course', 'course', $course1->id, \context_course::instance($course1->id), 25); 183 $this->rate_as_user($u1->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 50); 184 $this->rate_as_user($u1->id, 'core_course', 'course', $course3->id, \context_course::instance($course3->id), 75); 185 $this->rate_as_user($u1->id, 'core_course', 'files', $course3->id, \context_course::instance($course3->id), 99); 186 187 // Rate course2 as u2, and something else in a different context/component.. 188 $this->rate_as_user($u2->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 90); 189 $this->rate_as_user($u2->id, 'user', 'user', $u3->id, \context_user::instance($u3->id), 10); 190 191 // Return any course which the u1 has rated. 192 // u1 rated all three courses. 193 $ratingquery = provider::get_sql_join('r', 'core_course', 'course', 'c.id', $u1->id, true); 194 $sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 195 $courses = $DB->get_records_sql($sql, $ratingquery->params); 196 197 $this->assertCount(3, $courses); 198 $this->assertTrue(isset($courses[$course1->id])); 199 $this->assertTrue(isset($courses[$course2->id])); 200 $this->assertTrue(isset($courses[$course3->id])); 201 202 // User u1 rated files in course 3 only. 203 $ratingquery = provider::get_sql_join('r', 'core_course', 'files', 'c.id', $u1->id, true); 204 $sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 205 $courses = $DB->get_records_sql($sql, $ratingquery->params); 206 207 $this->assertCount(1, $courses); 208 $this->assertFalse(isset($courses[$course1->id])); 209 $this->assertFalse(isset($courses[$course2->id])); 210 $this->assertTrue(isset($courses[$course3->id])); 211 212 // Return any course which the u2 has rated. 213 // User u2 rated only course 2. 214 $ratingquery = provider::get_sql_join('r', 'core_course', 'course', 'c.id', $u2->id, true); 215 $sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 216 $courses = $DB->get_records_sql($sql, $ratingquery->params); 217 218 $this->assertCount(1, $courses); 219 $this->assertFalse(isset($courses[$course1->id])); 220 $this->assertTrue(isset($courses[$course2->id])); 221 $this->assertFalse(isset($courses[$course3->id])); 222 223 // User u2 rated u3. 224 $ratingquery = provider::get_sql_join('r', 'user', 'user', 'u.id', $u2->id, true); 225 $sql = "SELECT u.id FROM {user} u {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 226 $users = $DB->get_records_sql($sql, $ratingquery->params); 227 228 $this->assertCount(1, $users); 229 $this->assertFalse(isset($users[$u1->id])); 230 $this->assertFalse(isset($users[$u2->id])); 231 $this->assertTrue(isset($users[$u3->id])); 232 233 // Return any course which the u3 has rated. 234 // User u3 did not rate anything. 235 $ratingquery = provider::get_sql_join('r', 'core_course', 'course', 'c.id', $u3->id, true); 236 $sql = "SELECT c.id FROM {course} c {$ratingquery->join} WHERE {$ratingquery->userwhere}"; 237 $courses = $DB->get_records_sql($sql, $ratingquery->params); 238 239 $this->assertCount(0, $courses); 240 $this->assertFalse(isset($courses[$course1->id])); 241 $this->assertFalse(isset($courses[$course2->id])); 242 $this->assertFalse(isset($courses[$course3->id])); 243 } 244 245 /** 246 * Ensure that export_area_ratings exports all ratings that a user has made, and all ratings for a users own content. 247 */ 248 public function test_export_area_ratings() { 249 global $DB; 250 $this->resetAfterTest(); 251 252 $course1 = $this->getDataGenerator()->create_course(); 253 $course2 = $this->getDataGenerator()->create_course(); 254 $course3 = $this->getDataGenerator()->create_course(); 255 256 $u1 = $this->getDataGenerator()->create_user(); 257 $u2 = $this->getDataGenerator()->create_user(); 258 $u3 = $this->getDataGenerator()->create_user(); 259 260 // Rate the courses. 261 $rm = new \rating_manager(); 262 $ratingoptions = (object) [ 263 'component' => 'core_course', 264 'ratingarea' => 'course', 265 'scaleid' => 100, 266 ]; 267 268 // Rate all courses as u1, and something else in the same context. 269 $this->rate_as_user($u1->id, 'core_course', 'course', $course1->id, \context_course::instance($course1->id), 25); 270 $this->rate_as_user($u1->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 50); 271 $this->rate_as_user($u1->id, 'core_course', 'course', $course3->id, \context_course::instance($course3->id), 75); 272 $this->rate_as_user($u1->id, 'core_course', 'files', $course3->id, \context_course::instance($course3->id), 99); 273 $this->rate_as_user($u1->id, 'user', 'user', $u3->id, \context_user::instance($u3->id), 10); 274 275 // Rate course2 as u2, and something else in a different context/component.. 276 $this->rate_as_user($u2->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 90); 277 $this->rate_as_user($u2->id, 'user', 'user', $u3->id, \context_user::instance($u3->id), 20); 278 279 // Test exports. 280 // User 1 rated all three courses, and the core_course, and user 3. 281 // User 1::course1 is stored in [] subcontext. 282 $context = \context_course::instance($course1->id); 283 $subcontext = []; 284 provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'course', $course1->id, true); 285 286 $writer = writer::with_context($context); 287 $this->assertTrue($writer->has_any_data()); 288 $rating = $writer->get_related_data($subcontext, 'rating'); 289 $this->assert_has_rating($u1, 25, $rating); 290 291 // User 1::course2 is stored in ['foo'] subcontext. 292 $context = \context_course::instance($course2->id); 293 $subcontext = ['foo']; 294 provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'course', $course2->id, true); 295 296 $writer = writer::with_context($context); 297 $this->assertTrue($writer->has_any_data()); 298 $result = $writer->get_related_data($subcontext, 'rating'); 299 $this->assertCount(1, $result); 300 $this->assert_has_rating($u1, 50, $result); 301 302 // User 1::course3 is stored in ['foo'] subcontext. 303 $context = \context_course::instance($course3->id); 304 $subcontext = ['foo']; 305 provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'course', $course3->id, true); 306 307 $writer = writer::with_context($context); 308 $this->assertTrue($writer->has_any_data()); 309 $result = $writer->get_related_data($subcontext, 'rating'); 310 $this->assertCount(1, $result); 311 $this->assert_has_rating($u1, 75, $result); 312 313 // User 1::course3::files is stored in ['foo', 'files'] subcontext. 314 $context = \context_course::instance($course3->id); 315 $subcontext = ['foo', 'files']; 316 provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'files', $course3->id, true); 317 318 $writer = writer::with_context($context); 319 $this->assertTrue($writer->has_any_data()); 320 $result = $writer->get_related_data($subcontext, 'rating'); 321 $this->assertCount(1, $result); 322 $this->assert_has_rating($u1, 99, $result); 323 324 // Both users 1 and 2 rated user 3. 325 // Exporting the data for user 3 should include both of those ratings. 326 $context = \context_user::instance($u3->id); 327 $subcontext = ['user']; 328 provider::export_area_ratings($u3->id, $context, $subcontext, 'user', 'user', $u3->id, false); 329 330 $writer = writer::with_context($context); 331 $this->assertTrue($writer->has_any_data()); 332 $result = $writer->get_related_data($subcontext, 'rating'); 333 $this->assertCount(2, $result); 334 $this->assert_has_rating($u1, 10, $result); 335 $this->assert_has_rating($u2, 20, $result); 336 } 337 338 /** 339 * Test delete_ratings() method. 340 */ 341 public function test_delete_ratings() { 342 global $DB; 343 $this->resetAfterTest(); 344 345 $course1 = $this->getDataGenerator()->create_course(); 346 $course2 = $this->getDataGenerator()->create_course(); 347 $course3 = $this->getDataGenerator()->create_course(); 348 349 $u1 = $this->getDataGenerator()->create_user(); 350 $u2 = $this->getDataGenerator()->create_user(); 351 $u3 = $this->getDataGenerator()->create_user(); 352 353 // Rate all courses as u1, and something else in the same context. 354 $this->rate_as_user($u1->id, 'core_course', 'course', $course1->id, \context_course::instance($course1->id), 25); 355 $this->rate_as_user($u1->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 50); 356 $this->rate_as_user($u1->id, 'core_course', 'course', $course3->id, \context_course::instance($course3->id), 75); 357 $this->rate_as_user($u1->id, 'core_course', 'files', $course3->id, \context_course::instance($course3->id), 99); 358 $this->rate_as_user($u1->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 10); 359 360 // Rate course2 as u2, and something else in a different context/component.. 361 $this->rate_as_user($u2->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 90); 362 $this->rate_as_user($u2->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 20); 363 364 // Delete all ratings in course1. 365 $expectedratingscount = $DB->count_records('rating'); 366 provider::delete_ratings(\context_course::instance($course1->id)); 367 $expectedratingscount -= 1; 368 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 369 370 // Delete ratings in course2 specifying wrong component. 371 provider::delete_ratings(\context_course::instance($course2->id), 'other_component'); 372 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 373 374 // Delete ratings in course2 specifying correct component. 375 provider::delete_ratings(\context_course::instance($course2->id), 'core_course'); 376 $expectedratingscount -= 2; 377 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 378 379 // Delete user ratings specifyng all attributes. 380 provider::delete_ratings(\context_user::instance($u3->id), 'core_user', 'user', $u3->id); 381 $expectedratingscount -= 2; 382 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 383 } 384 385 /** 386 * Test delete_ratings_select() method. 387 */ 388 public function test_delete_ratings_select() { 389 global $DB; 390 $this->resetAfterTest(); 391 392 $course1 = $this->getDataGenerator()->create_course(); 393 $course2 = $this->getDataGenerator()->create_course(); 394 $course3 = $this->getDataGenerator()->create_course(); 395 396 $u1 = $this->getDataGenerator()->create_user(); 397 $u2 = $this->getDataGenerator()->create_user(); 398 $u3 = $this->getDataGenerator()->create_user(); 399 400 // Rate all courses as u1, and something else in the same context. 401 $this->rate_as_user($u1->id, 'core_course', 'course', $course1->id, \context_course::instance($course1->id), 25); 402 $this->rate_as_user($u1->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 50); 403 $this->rate_as_user($u1->id, 'core_course', 'course', $course3->id, \context_course::instance($course3->id), 75); 404 $this->rate_as_user($u1->id, 'core_course', 'files', $course3->id, \context_course::instance($course3->id), 99); 405 $this->rate_as_user($u1->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 10); 406 407 // Rate course2 as u2, and something else in a different context/component.. 408 $this->rate_as_user($u2->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 90); 409 $this->rate_as_user($u2->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 20); 410 411 // Delete ratings in course1. 412 list($sql, $params) = $DB->get_in_or_equal([$course1->id, $course2->id], SQL_PARAMS_NAMED); 413 $expectedratingscount = $DB->count_records('rating'); 414 provider::delete_ratings_select(\context_course::instance($course1->id), 415 'core_course', 'course', $sql, $params); 416 $expectedratingscount -= 1; 417 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 418 } 419 420 /** 421 * Assert that a user has the correct rating. 422 * 423 * @param \stdClass $author The user with the rating 424 * @param int $score The rating that was given 425 * @param \stdClass[] The ratings which were found 426 */ 427 protected function assert_has_rating($author, $score, $actual) { 428 $found = false; 429 foreach ($actual as $rating) { 430 if ($author->id == $rating->author) { 431 $found = true; 432 $this->assertEquals($score, $rating->rating); 433 } 434 } 435 $this->assertTrue($found); 436 } 437 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body