Differences Between: [Versions 311 and 403] [Versions 400 and 403] [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 /** @var \core_privacy\tests\request\content_writer $writer */ 287 $writer = writer::with_context($context); 288 $this->assertTrue($writer->has_any_data()); 289 $rating = $writer->get_related_data($subcontext, 'rating'); 290 $this->assert_has_rating($u1, 25, $rating); 291 292 // User 1::course2 is stored in ['foo'] subcontext. 293 $context = \context_course::instance($course2->id); 294 $subcontext = ['foo']; 295 provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'course', $course2->id, true); 296 297 /** @var \core_privacy\tests\request\content_writer $writer */ 298 $writer = writer::with_context($context); 299 $this->assertTrue($writer->has_any_data()); 300 $result = $writer->get_related_data($subcontext, 'rating'); 301 $this->assertCount(1, $result); 302 $this->assert_has_rating($u1, 50, $result); 303 304 // User 1::course3 is stored in ['foo'] subcontext. 305 $context = \context_course::instance($course3->id); 306 $subcontext = ['foo']; 307 provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'course', $course3->id, true); 308 309 /** @var \core_privacy\tests\request\content_writer $writer */ 310 $writer = writer::with_context($context); 311 $this->assertTrue($writer->has_any_data()); 312 $result = $writer->get_related_data($subcontext, 'rating'); 313 $this->assertCount(1, $result); 314 $this->assert_has_rating($u1, 75, $result); 315 316 // User 1::course3::files is stored in ['foo', 'files'] subcontext. 317 $context = \context_course::instance($course3->id); 318 $subcontext = ['foo', 'files']; 319 provider::export_area_ratings($u1->id, $context, $subcontext, 'core_course', 'files', $course3->id, true); 320 321 /** @var \core_privacy\tests\request\content_writer $writer */ 322 $writer = writer::with_context($context); 323 $this->assertTrue($writer->has_any_data()); 324 $result = $writer->get_related_data($subcontext, 'rating'); 325 $this->assertCount(1, $result); 326 $this->assert_has_rating($u1, 99, $result); 327 328 // Both users 1 and 2 rated user 3. 329 // Exporting the data for user 3 should include both of those ratings. 330 $context = \context_user::instance($u3->id); 331 $subcontext = ['user']; 332 provider::export_area_ratings($u3->id, $context, $subcontext, 'user', 'user', $u3->id, false); 333 334 /** @var \core_privacy\tests\request\content_writer $writer */ 335 $writer = writer::with_context($context); 336 $this->assertTrue($writer->has_any_data()); 337 $result = $writer->get_related_data($subcontext, 'rating'); 338 $this->assertCount(2, $result); 339 $this->assert_has_rating($u1, 10, $result); 340 $this->assert_has_rating($u2, 20, $result); 341 } 342 343 /** 344 * Test delete_ratings() method. 345 */ 346 public function test_delete_ratings() { 347 global $DB; 348 $this->resetAfterTest(); 349 350 $course1 = $this->getDataGenerator()->create_course(); 351 $course2 = $this->getDataGenerator()->create_course(); 352 $course3 = $this->getDataGenerator()->create_course(); 353 354 $u1 = $this->getDataGenerator()->create_user(); 355 $u2 = $this->getDataGenerator()->create_user(); 356 $u3 = $this->getDataGenerator()->create_user(); 357 358 // Rate all courses as u1, and something else in the same context. 359 $this->rate_as_user($u1->id, 'core_course', 'course', $course1->id, \context_course::instance($course1->id), 25); 360 $this->rate_as_user($u1->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 50); 361 $this->rate_as_user($u1->id, 'core_course', 'course', $course3->id, \context_course::instance($course3->id), 75); 362 $this->rate_as_user($u1->id, 'core_course', 'files', $course3->id, \context_course::instance($course3->id), 99); 363 $this->rate_as_user($u1->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 10); 364 365 // Rate course2 as u2, and something else in a different context/component.. 366 $this->rate_as_user($u2->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 90); 367 $this->rate_as_user($u2->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 20); 368 369 // Delete all ratings in course1. 370 $expectedratingscount = $DB->count_records('rating'); 371 provider::delete_ratings(\context_course::instance($course1->id)); 372 $expectedratingscount -= 1; 373 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 374 375 // Delete ratings in course2 specifying wrong component. 376 provider::delete_ratings(\context_course::instance($course2->id), 'other_component'); 377 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 378 379 // Delete ratings in course2 specifying correct component. 380 provider::delete_ratings(\context_course::instance($course2->id), 'core_course'); 381 $expectedratingscount -= 2; 382 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 383 384 // Delete user ratings specifyng all attributes. 385 provider::delete_ratings(\context_user::instance($u3->id), 'core_user', 'user', $u3->id); 386 $expectedratingscount -= 2; 387 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 388 } 389 390 /** 391 * Test delete_ratings_select() method. 392 */ 393 public function test_delete_ratings_select() { 394 global $DB; 395 $this->resetAfterTest(); 396 397 $course1 = $this->getDataGenerator()->create_course(); 398 $course2 = $this->getDataGenerator()->create_course(); 399 $course3 = $this->getDataGenerator()->create_course(); 400 401 $u1 = $this->getDataGenerator()->create_user(); 402 $u2 = $this->getDataGenerator()->create_user(); 403 $u3 = $this->getDataGenerator()->create_user(); 404 405 // Rate all courses as u1, and something else in the same context. 406 $this->rate_as_user($u1->id, 'core_course', 'course', $course1->id, \context_course::instance($course1->id), 25); 407 $this->rate_as_user($u1->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 50); 408 $this->rate_as_user($u1->id, 'core_course', 'course', $course3->id, \context_course::instance($course3->id), 75); 409 $this->rate_as_user($u1->id, 'core_course', 'files', $course3->id, \context_course::instance($course3->id), 99); 410 $this->rate_as_user($u1->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 10); 411 412 // Rate course2 as u2, and something else in a different context/component.. 413 $this->rate_as_user($u2->id, 'core_course', 'course', $course2->id, \context_course::instance($course2->id), 90); 414 $this->rate_as_user($u2->id, 'core_user', 'user', $u3->id, \context_user::instance($u3->id), 20); 415 416 // Delete ratings in course1. 417 list($sql, $params) = $DB->get_in_or_equal([$course1->id, $course2->id], SQL_PARAMS_NAMED); 418 $expectedratingscount = $DB->count_records('rating'); 419 provider::delete_ratings_select(\context_course::instance($course1->id), 420 'core_course', 'course', $sql, $params); 421 $expectedratingscount -= 1; 422 $this->assertEquals($expectedratingscount, $DB->count_records('rating')); 423 } 424 425 /** 426 * Assert that a user has the correct rating. 427 * 428 * @param \stdClass $author The user with the rating 429 * @param int $score The rating that was given 430 * @param \stdClass[] The ratings which were found 431 */ 432 protected function assert_has_rating($author, $score, $actual) { 433 $found = false; 434 foreach ($actual as $rating) { 435 if ($author->id == $rating->author) { 436 $found = true; 437 $this->assertEquals($score, $rating->rating); 438 } 439 } 440 $this->assertTrue($found); 441 } 442 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body