Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}