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
 * Privacy tests for core_course.
18
 *
19
 * @package    core_course
20
 * @category   test
21
 * @copyright  2018 Adrian Greeve <adrian@moodle.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
namespace core_course\privacy;
25
 
26
defined('MOODLE_INTERNAL') || die();
27
 
28
global $CFG;
29
require_once($CFG->dirroot . '/completion/tests/fixtures/completion_creation.php');
30
 
31
use core_privacy\local\request\transform;
32
 
33
/**
34
 * Unit tests for course/classes/privacy/policy
35
 *
36
 * @copyright  2018 Adrian Greeve <adrian@moodle.com>
37
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38
 */
39
class provider_test extends \core_privacy\tests\provider_testcase {
40
 
41
    use \completion_creation;
42
 
43
    /**
44
     * Test getting the appropriate context for the userid. This should only ever
45
     * return the user context for the user id supplied.
46
     */
47
    public function test_get_contexts_for_userid() {
48
        $this->resetAfterTest();
49
 
50
        $user1 = $this->getDataGenerator()->create_user();
51
        $user2 = $this->getDataGenerator()->create_user();
52
 
53
        // Make sure contexts are not being returned for user1.
54
        $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user1->id);
55
        $this->assertCount(0, $contextlist->get_contextids());
56
 
57
        // Make sure contexts are not being returned for user2.
58
        $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user2->id);
59
        $this->assertCount(0, $contextlist->get_contextids());
60
 
61
        // Create course completion data for user1.
62
        $this->create_course_completion();
63
        $this->complete_course($user1);
64
 
65
        // Make sure the course context is being returned for user1.
66
        $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user1->id);
67
        $expected = [$this->coursecontext->id];
68
        $actual = $contextlist->get_contextids();
69
        $this->assertCount(1, $actual);
70
        $this->assertEquals($expected, $actual);
71
 
72
        // Make sure contexts are still not being returned for user2.
73
        $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user2->id);
74
        $this->assertCount(0, $contextlist->get_contextids());
75
 
76
        // User2 has a favourite course.
77
        $user2context = \context_user::instance($user2->id);
78
        $ufservice = \core_favourites\service_factory::get_service_for_user_context($user2context);
79
        $ufservice->create_favourite('core_course', 'courses', $this->coursecontext->instanceid,
80
            $this->coursecontext);
81
 
82
        // Make sure the course context is being returned for user2.
83
        $contextlist = \core_course\privacy\provider::get_contexts_for_userid($user2->id);
84
        $expected = [$this->coursecontext->id];
85
        $actual = $contextlist->get_contextids();
86
        $this->assertCount(1, $actual);
87
        $this->assertEquals($expected, $actual);
88
    }
89
 
90
    /**
91
     * Test fetching users within a context.
92
     */
93
    public function test_get_users_in_context() {
94
        $this->resetAfterTest();
95
        $component = 'core_course';
96
 
97
        $user1 = $this->getDataGenerator()->create_user();
98
        $user2 = $this->getDataGenerator()->create_user();
99
        $user3 = $this->getDataGenerator()->create_user();
100
        $user4 = $this->getDataGenerator()->create_user();
101
 
102
        // User1 and user2 complete course.
103
        $this->create_course_completion();
104
        $this->complete_course($user1);
105
        $this->complete_course($user2);
106
 
107
        // User3 is enrolled but has not completed course.
108
        $this->getDataGenerator()->enrol_user($user3->id, $this->course->id, 'student');
109
 
110
        // User4 has a favourited course.
111
        $systemcontext = \context_system::instance();
112
        $user4ctx = \context_user::instance($user4->id);
113
        $ufservice = \core_favourites\service_factory::get_service_for_user_context($user4ctx);
114
        $ufservice->create_favourite('core_course', 'courses', $this->coursecontext->instanceid,
115
                $this->coursecontext);
116
 
117
        // Ensure only users that have course completion or favourites are returned.
118
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, $component);
119
        \core_course\privacy\provider::get_users_in_context($userlist);
120
        $expected = [
121
            $user1->id,
122
            $user2->id,
123
            $user4->id
124
        ];
125
        $actual = $userlist->get_userids();
126
        sort($expected);
127
        sort($actual);
128
        $this->assertCount(3, $actual);
129
        $this->assertEquals($expected, $actual);
130
 
131
        // Ensure that users are not being returned in other contexts than the course context.
132
        $userlist = new \core_privacy\local\request\userlist($systemcontext, $component);
133
        \core_course\privacy\provider::get_users_in_context($userlist);
134
        $actual = $userlist->get_userids();
135
        $this->assertCount(0, $actual);
136
    }
137
 
138
    /**
139
     * Test that user data is exported.
140
     */
141
    public function test_export_user_data() {
142
        $this->resetAfterTest();
143
 
144
        $user = $this->getDataGenerator()->create_user();
145
        $this->create_course_completion();
146
        $this->complete_course($user);
147
        $approvedlist = new \core_privacy\local\request\approved_contextlist($user, 'core_course',
148
                [$this->coursecontext->id]);
149
        $writer = \core_privacy\local\request\writer::with_context($this->coursecontext);
150
        \core_course\privacy\provider::export_user_data($approvedlist);
151
        $completiondata = $writer->get_data([get_string('privacy:completionpath', 'course')]);
152
        $this->assertEquals('Complete', $completiondata->status);
153
        $this->assertCount(2, $completiondata->criteria);
154
 
155
        // User has a favourite course.
156
        $usercontext = \context_user::instance($user->id);
157
        $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);
158
        $favourite = $ufservice->create_favourite('core_course', 'courses',
159
                $this->coursecontext->instanceid, $this->coursecontext);
160
 
161
        // Ensure that user's favourites data in the course context is being exported.
162
        $writer = \core_privacy\local\request\writer::with_context($this->coursecontext);
163
        \core_course\privacy\provider::export_user_data($approvedlist);
164
        $favouritedata = $writer->get_data([get_string('privacy:favouritespath', 'course')]);
165
 
166
        $this->assertEquals(transform::yesno(true), $favouritedata->starred);
167
        $this->assertEquals('', $favouritedata->ordering);
168
        $this->assertEquals(transform::datetime($favourite->timecreated), $favouritedata->timecreated);
169
        $this->assertEquals(transform::datetime($favourite->timemodified), $favouritedata->timemodified);
170
    }
171
 
172
    /**
173
     * Verify that if a module context is included in the contextlist_collection and its parent course is not, the
174
     * export_context_data() call picks this up, and that the contextual course information is included.
175
     */
176
    public function test_export_context_data_module_context_only() {
177
        $this->resetAfterTest();
178
 
179
        // Create a course and a single module.
180
        $course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course 1', 'shortname' => 'C1']);
181
        $context1 = \context_course::instance($course1->id);
182
        $modassign = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id, 'name' => 'assign test 1']);
183
        $assigncontext = \context_module::instance($modassign->cmid);
184
 
185
        // Now, let's assume during user info export, only the coursemodule context is returned in the contextlist_collection.
186
        $user = $this->getDataGenerator()->create_user();
187
        $collection = new \core_privacy\local\request\contextlist_collection($user->id);
188
        $approvedlist = new \core_privacy\local\request\approved_contextlist($user, 'mod_assign', [$assigncontext->id]);
189
        $collection->add_contextlist($approvedlist);
190
 
191
        // Now, verify that core_course will detect this, and add relevant contextual information.
192
        \core_course\privacy\provider::export_context_data($collection);
193
        $writer = \core_privacy\local\request\writer::with_context($context1);
194
        $this->assertTrue($writer->has_any_data());
195
        $writerdata = $writer->get_data();
196
        $this->assertObjectHasProperty('fullname', $writerdata);
197
        $this->assertObjectHasProperty('shortname', $writerdata);
198
        $this->assertObjectHasProperty('idnumber', $writerdata);
199
        $this->assertObjectHasProperty('summary', $writerdata);
200
    }
201
 
202
    /**
203
     * Verify that if a module context and its parent course context are both included in the contextlist_collection, that course
204
     * contextual information is present in the export.
205
     */
206
    public function test_export_context_data_course_and_module_contexts() {
207
        $this->resetAfterTest();
208
 
209
        // Create a course and a single module.
210
        $course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course 1', 'shortname' => 'C1', 'format' => 'site']);
211
        $context1 = \context_course::instance($course1->id);
212
        $modassign = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id, 'name' => 'assign test 1']);
213
        $assigncontext = \context_module::instance($modassign->cmid);
214
 
215
        // Now, assume during user info export, that both module and course contexts are returned in the contextlist_collection.
216
        $user = $this->getDataGenerator()->create_user();
217
        $collection = new \core_privacy\local\request\contextlist_collection($user->id);
218
        $approvedlist = new \core_privacy\local\request\approved_contextlist($user, 'mod_assign', [$assigncontext->id]);
219
        $approvedlist2 = new \core_privacy\local\request\approved_contextlist($user, 'core_course', [$context1->id]);
220
        $collection->add_contextlist($approvedlist);
221
        $collection->add_contextlist($approvedlist2);
222
 
223
        // Now, verify that core_course still adds relevant contextual information, even for courses which are explicitly listed in
224
        // the contextlist_collection.
225
        \core_course\privacy\provider::export_context_data($collection);
226
        $writer = \core_privacy\local\request\writer::with_context($context1);
227
        $this->assertTrue($writer->has_any_data());
228
        $writerdata = $writer->get_data();
229
        $this->assertObjectHasProperty('fullname', $writerdata);
230
        $this->assertObjectHasProperty('shortname', $writerdata);
231
        $this->assertObjectHasProperty('idnumber', $writerdata);
232
        $this->assertObjectHasProperty('summary', $writerdata);
233
    }
234
 
235
    /**
236
     * Test deleting all user data for one context.
237
     */
238
    public function test_delete_data_for_all_users_in_context() {
239
        global $DB;
240
 
241
        $this->resetAfterTest();
242
 
243
        $user1 = $this->getDataGenerator()->create_user();
244
        $user2 = $this->getDataGenerator()->create_user();
245
        $this->create_course_completion();
246
 
247
        $systemcontext = \context_system::instance();
248
        $user1ctx = \context_user::instance($user1->id);
249
        $user2ctx = \context_user::instance($user2->id);
250
        // User1 and user2 have a favourite course.
251
        $ufservice1 = \core_favourites\service_factory::get_service_for_user_context($user1ctx);
252
        $ufservice1->create_favourite('core_course', 'courses', $this->coursecontext->instanceid,
253
                $this->coursecontext);
254
        $ufservice2 = \core_favourites\service_factory::get_service_for_user_context($user2ctx);
255
        $ufservice2->create_favourite('core_course', 'courses', $this->coursecontext->instanceid,
256
                $this->coursecontext);
257
 
258
        // Ensure only users that have course favourites are returned in the course context (user1 and user2).
259
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
260
        \core_course\privacy\provider::get_users_in_context($userlist);
261
        $actual = $userlist->get_userids();
262
        $this->assertCount(2, $actual);
263
 
264
        // Ensure the users does not have a course completion data.
265
        $records = $DB->get_records('course_modules_completion');
266
        $this->assertCount(0, $records);
267
        $records = $DB->get_records('course_completion_crit_compl');
268
        $this->assertCount(0, $records);
269
 
270
        // Create course completions for user1 and users.
271
        $this->complete_course($user1);
272
        $this->complete_course($user2);
273
        $records = $DB->get_records('course_modules_completion');
274
        $this->assertCount(2, $records);
275
        $records = $DB->get_records('course_completion_crit_compl');
276
        $this->assertCount(4, $records);
277
 
278
        // Delete data for all users in a context different than the course context (system context).
279
        \core_course\privacy\provider::delete_data_for_all_users_in_context($systemcontext);
280
 
281
        // Ensure the data in the course context has not been deleted.
282
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
283
        \core_course\privacy\provider::get_users_in_context($userlist);
284
        $actual = $userlist->get_userids();
285
        $this->assertCount(2, $actual);
286
 
287
        // Delete data for all users in the course context.
288
        \core_course\privacy\provider::delete_data_for_all_users_in_context($this->coursecontext);
289
 
290
        // Ensure the completion data has been removed in the course context.
291
        $records = $DB->get_records('course_modules_completion');
292
        $this->assertCount(0, $records);
293
        $records = $DB->get_records('course_completion_crit_compl');
294
        $this->assertCount(0, $records);
295
 
296
        // Ensure that users are not returned after the deletion in the course context.
297
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
298
        \core_course\privacy\provider::get_users_in_context($userlist);
299
        $actual = $userlist->get_userids();
300
        $this->assertCount(0, $actual);
301
    }
302
 
303
    /**
304
     * Test deleting data for only one user.
305
     */
306
    public function test_delete_data_for_user() {
307
        $this->resetAfterTest();
308
 
309
        $user1 = $this->getDataGenerator()->create_user();
310
        $user2 = $this->getDataGenerator()->create_user();
311
        $user3 = $this->getDataGenerator()->create_user();
312
 
313
        // Create course completion for user1.
314
        $this->create_course_completion();
315
        $this->complete_course($user1);
316
 
317
        // Ensure user1 is returned in the course context.
318
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
319
        \core_course\privacy\provider::get_users_in_context($userlist);
320
        $actual = $userlist->get_userids();
321
        $expected = [$user1->id];
322
        $this->assertCount(1, $actual);
323
        $this->assertEquals($expected, $actual);
324
 
325
        // User2 and user3 have a favourite course.
326
        $systemcontext = \context_system::instance();
327
        $user2ctx = \context_user::instance($user2->id);
328
        $user3ctx = \context_user::instance($user3->id);
329
        $ufservice2 = \core_favourites\service_factory::get_service_for_user_context($user2ctx);
330
        $ufservice2->create_favourite('core_course', 'courses', $this->coursecontext->instanceid,
331
                $this->coursecontext);
332
        $ufservice3 = \core_favourites\service_factory::get_service_for_user_context($user3ctx);
333
        $ufservice3->create_favourite('core_course', 'courses', $this->coursecontext->instanceid,
334
                $this->coursecontext);
335
 
336
        // Ensure user1, user2 and user3 are returned in the course context.
337
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
338
        \core_course\privacy\provider::get_users_in_context($userlist);
339
        $actual = $userlist->get_userids();
340
        $expected = [
341
            $user1->id,
342
            $user2->id,
343
            $user3->id
344
        ];
345
        sort($expected);
346
        sort($actual);
347
        $this->assertCount(3, $actual);
348
        $this->assertEquals($expected, $actual);
349
 
350
        // Delete user1's data in the course context.
351
        $approvedlist = new \core_privacy\local\request\approved_contextlist($user1, 'core_course',
352
                [$this->coursecontext->id]);
353
        \core_course\privacy\provider::delete_data_for_user($approvedlist);
354
 
355
        // Ensure user1's data is deleted and only user2 and user3 are returned in the course context.
356
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
357
        \core_course\privacy\provider::get_users_in_context($userlist);
358
        $actual = $userlist->get_userids();
359
        $expected = [
360
            $user2->id,
361
            $user3->id
362
        ];
363
        sort($expected);
364
        sort($actual);
365
        $this->assertEquals($expected, $actual);
366
 
367
        // Delete user2's data in a context different than the course context (system context).
368
        $approvedlist = new \core_privacy\local\request\approved_contextlist($user2, 'core_course',
369
                [$systemcontext->id]);
370
        \core_course\privacy\provider::delete_data_for_user($approvedlist);
371
 
372
        // Ensure user2 and user3 are still returned in the course context.
373
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
374
        \core_course\privacy\provider::get_users_in_context($userlist);
375
        $actual = $userlist->get_userids();
376
        $expected = [
377
            $user2->id,
378
            $user3->id
379
        ];
380
        sort($expected);
381
        sort($actual);
382
        $this->assertEquals($expected, $actual);
383
 
384
        // Delete user2's data in the course context.
385
        $approvedlist = new \core_privacy\local\request\approved_contextlist($user2, 'core_course',
386
                [$this->coursecontext->id]);
387
        \core_course\privacy\provider::delete_data_for_user($approvedlist);
388
 
389
        // Ensure user2's is deleted and user3 is still returned in the course context.
390
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
391
        \core_course\privacy\provider::get_users_in_context($userlist);
392
        $actual = $userlist->get_userids();
393
        $expected = [
394
            $user3->id
395
        ];
396
        $this->assertEquals($expected, $actual);
397
    }
398
 
399
    /**
400
     * Test deleting data within a context for an approved userlist.
401
     */
402
    public function test_delete_data_for_users() {
403
        $this->resetAfterTest();
404
 
405
        $component = 'core_course';
406
        $user1 = $this->getDataGenerator()->create_user();
407
        $user2 = $this->getDataGenerator()->create_user();
408
        $user3 = $this->getDataGenerator()->create_user();
409
 
410
        $this->create_course_completion();
411
        $this->complete_course($user1);
412
        $this->complete_course($user2);
413
 
414
        // Ensure user1, user2 are returned in the course context.
415
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
416
        \core_course\privacy\provider::get_users_in_context($userlist);
417
        $actual = $userlist->get_userids();
418
        $expected = [
419
            $user1->id,
420
            $user2->id
421
        ];
422
        sort($expected);
423
        sort($actual);
424
        $this->assertCount(2, $actual);
425
        $this->assertEquals($expected, $actual);
426
 
427
        $systemcontext = \context_system::instance();
428
        // User3 has a favourite course.
429
        $user3ctx = \context_user::instance($user3->id);
430
        $ufservice = \core_favourites\service_factory::get_service_for_user_context($user3ctx);
431
        $ufservice->create_favourite('core_course', 'courses', $this->coursecontext->instanceid,
432
                $this->coursecontext);
433
 
434
        // Ensure user1, user2 and user3 are now returned in the course context.
435
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
436
        \core_course\privacy\provider::get_users_in_context($userlist);
437
        $actual = $userlist->get_userids();
438
        $expected = [
439
            $user1->id,
440
            $user2->id,
441
            $user3->id
442
        ];
443
        sort($expected);
444
        sort($actual);
445
        $this->assertCount(3, $actual);
446
        $this->assertEquals($expected, $actual);
447
 
448
        // Delete data for user1 and user3 in the course context.
449
        $approveduserids = [$user1->id, $user3->id];
450
        $approvedlist = new \core_privacy\local\request\approved_userlist($this->coursecontext, $component, $approveduserids);
451
        \core_course\privacy\provider::delete_data_for_users($approvedlist);
452
 
453
        // Ensure user1 and user3 are deleted and user2 is still returned in the course context.
454
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
455
        \core_course\privacy\provider::get_users_in_context($userlist);
456
        $actual = $userlist->get_userids();
457
        $expected = [$user2->id];
458
        $this->assertCount(1, $actual);
459
        $this->assertEquals($expected, $actual);
460
 
461
        // Try to delete user2's data in a context different than course (system context).
462
        $approveduserids = [$user2->id];
463
        $approvedlist = new \core_privacy\local\request\approved_userlist($systemcontext, $component, $approveduserids);
464
        \core_course\privacy\provider::delete_data_for_users($approvedlist);
465
 
466
        // Ensure user2 is still returned in the course context.
467
        $userlist = new \core_privacy\local\request\userlist($this->coursecontext, 'core_course');
468
        \core_course\privacy\provider::get_users_in_context($userlist);
469
        $actual = $userlist->get_userids();
470
        $expected = [
471
            $user2->id
472
        ];
473
        $this->assertCount(1, $actual);
474
        $this->assertEquals($expected, $actual);
475
    }
476
}