Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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
 * Privacy provider tests.
19
 *
20
 * @package    block_comments
21
 * @copyright  2018 Shamim Rezaie <shamim@moodle.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
namespace block_comments\privacy;
25
 
26
use core_privacy\local\metadata\collection;
27
use block_comments\privacy\provider;
28
use core_privacy\local\request\approved_userlist;
29
use stdClass;
30
 
31
defined('MOODLE_INTERNAL') || die();
32
 
33
/**
34
 * Privacy provider test for block_comments.
35
 *
36
 * @copyright  2018 Shamim Rezaie <shamim@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
    /** @var stdClass A student who is only enrolled in course1. */
42
    protected $student1;
43
 
44
    /** @var stdClass A student who is only enrolled in course2. */
45
    protected $student2;
46
 
47
    /** @var stdClass A student who is enrolled in both course1 and course2. */
48
    protected $student12;
49
 
50
    /** @var stdClass A test course. */
51
    protected $course1;
52
 
53
    /** @var stdClass A test course. */
54
    protected $course2;
55
 
56
    protected function setUp(): void {
57
        global $DB;
58
 
59
        $this->resetAfterTest();
60
        $this->setAdminUser();
61
 
62
        // Create courses.
63
        $generator = $this->getDataGenerator();
64
        $this->course1 = $generator->create_course();
65
        $this->course2 = $generator->create_course();
66
 
67
        // Create and enrol students.
68
        $this->student1 = $generator->create_user();
69
        $this->student2 = $generator->create_user();
70
        $this->student12 = $generator->create_user();
71
 
72
        $studentrole = $DB->get_record('role', ['shortname' => 'student']);
73
        $generator->enrol_user($this->student1->id,  $this->course1->id, $studentrole->id);
74
        $generator->enrol_user($this->student2->id,  $this->course2->id, $studentrole->id);
75
        $generator->enrol_user($this->student12->id,  $this->course1->id, $studentrole->id);
76
        $generator->enrol_user($this->student12->id,  $this->course2->id, $studentrole->id);
77
 
78
        // Comment block on course pages.
79
        $block = $this->add_comments_block_in_context(\context_course::instance($this->course1->id));
80
        $block = $this->add_comments_block_in_context(\context_course::instance($this->course2->id));
81
    }
82
 
83
    /**
84
     * Posts a comment on a given context.
85
     *
86
     * @param string $text The comment's text.
87
     * @param \context $context The context on which we want to put the comment.
88
     */
89
    protected function add_comment($text, \context $context) {
90
        $args = new \stdClass;
91
        $args->context = $context;
92
        $args->area = 'page_comments';
93
        $args->itemid = 0;
94
        $args->component = 'block_comments';
95
        $args->linktext = get_string('showcomments');
96
        $args->notoggle = true;
97
        $args->autostart = true;
98
        $args->displaycancel = false;
99
        $comment = new \comment($args);
100
 
101
        $comment->add($text);
102
    }
103
 
104
    /**
105
     * Creates a comments block on a context.
106
     *
107
     * @param \context $context The context on which we want to put the block.
108
     * @return \block_base The created block instance.
109
     * @throws \coding_exception
110
     */
111
    protected function add_comments_block_in_context(\context $context) {
112
        global $DB;
113
 
114
        $course = null;
115
 
116
        $page = new \moodle_page();
117
        $page->set_context($context);
118
 
119
        switch ($context->contextlevel) {
120
            case CONTEXT_SYSTEM:
121
                $page->set_pagelayout('frontpage');
122
                $page->set_pagetype('site-index');
123
                break;
124
            case CONTEXT_COURSE:
125
                $page->set_pagelayout('standard');
126
                $page->set_pagetype('course-view');
127
                $course = $DB->get_record('course', ['id' => $context->instanceid]);
128
                $page->set_course($course);
129
                break;
130
            case CONTEXT_MODULE:
131
                $page->set_pagelayout('standard');
132
                $mod = $DB->get_field_sql("SELECT m.name
133
                                             FROM {modules} m
134
                                             JOIN {course_modules} cm on cm.module = m.id
135
                                            WHERE cm.id = ?", [$context->instanceid]);
136
                $page->set_pagetype("mod-$mod-view");
137
                break;
138
            case CONTEXT_USER:
139
                $page->set_pagelayout('mydashboard');
140
                $page->set_pagetype('my-index');
141
                break;
142
            default:
143
                throw new coding_exception('Unsupported context for test');
144
        }
145
 
146
        $page->blocks->load_blocks();
147
 
148
        $page->blocks->add_block_at_end_of_default_region('comments');
149
 
150
        // We need to use another page object as load_blocks() only loads the blocks once.
151
        $page2 = new \moodle_page();
152
        $page2->set_context($page->context);
153
        $page2->set_pagelayout($page->pagelayout);
154
        $page2->set_pagetype($page->pagetype);
155
        if ($course) {
156
            $page2->set_course($course);
157
        }
158
 
159
        $page->blocks->load_blocks();
160
        $page2->blocks->load_blocks();
161
        $blocks = $page2->blocks->get_blocks_for_region($page2->blocks->get_default_region());
162
        $block = end($blocks);
163
 
164
        $block = block_instance('comments', $block->instance);
165
 
166
        return $block;
167
    }
168
 
169
    /**
170
     * Test for provider::get_metadata().
171
     */
11 efrain 172
    public function test_get_metadata(): void {
1 efrain 173
        $collection = new collection('block_comments');
174
        $newcollection = provider::get_metadata($collection);
175
        $itemcollection = $newcollection->get_collection();
176
        $this->assertCount(1, $itemcollection);
177
 
178
        $link = reset($itemcollection);
179
 
180
        $this->assertEquals('core_comment', $link->get_name());
181
        $this->assertEmpty($link->get_privacy_fields());
182
        $this->assertEquals('privacy:metadata:core_comment', $link->get_summary());
183
    }
184
 
185
    /**
186
     * Test for provider::get_contexts_for_userid() when user had not posted any comments..
187
     */
11 efrain 188
    public function test_get_contexts_for_userid_no_comment(): void {
1 efrain 189
        $this->setUser($this->student1);
190
        $coursecontext1 = \context_course::instance($this->course1->id);
191
        $this->add_comment('New comment', $coursecontext1);
192
 
193
        $this->setUser($this->student2);
194
        $contextlist = provider::get_contexts_for_userid($this->student2->id);
195
        $this->assertCount(0, $contextlist);
196
    }
197
 
198
    /**
199
     * Test for provider::get_contexts_for_userid().
200
     */
11 efrain 201
    public function test_get_contexts_for_userid(): void {
1 efrain 202
        $coursecontext1 = \context_course::instance($this->course1->id);
203
        $coursecontext2 = \context_course::instance($this->course2->id);
204
 
205
        $this->setUser($this->student12);
206
        $this->add_comment('New comment', $coursecontext1);
207
        $this->add_comment('New comment', $coursecontext1);
208
        $this->add_comment('New comment', $coursecontext2);
209
 
210
        $contextlist = provider::get_contexts_for_userid($this->student12->id);
211
        $this->assertCount(2, $contextlist);
212
 
213
        $contextids = $contextlist->get_contextids();
214
        $this->assertEqualsCanonicalizing([$coursecontext1->id, $coursecontext2->id], $contextids);
215
    }
216
 
217
    /**
218
     * Test for provider::export_user_data() when the user has not posted any comments.
219
     */
11 efrain 220
    public function test_export_for_context_no_comment(): void {
1 efrain 221
        $coursecontext1 = \context_course::instance($this->course1->id);
222
        $coursecontext2 = \context_course::instance($this->course2->id);
223
 
224
        $this->setUser($this->student1);
225
        $this->add_comment('New comment', $coursecontext1);
226
 
227
        $this->setUser($this->student2);
228
 
229
        $this->setUser($this->student2);
230
        $this->export_context_data_for_user($this->student2->id, $coursecontext2, 'block_comments');
231
        $writer = \core_privacy\local\request\writer::with_context($coursecontext2);
232
        $this->assertFalse($writer->has_any_data());
233
 
234
    }
235
 
236
    /**
237
     * Test for provider::export_user_data().
238
     */
11 efrain 239
    public function test_export_for_context(): void {
1 efrain 240
        $coursecontext1 = \context_course::instance($this->course1->id);
241
        $coursecontext2 = \context_course::instance($this->course2->id);
242
 
243
        $this->setUser($this->student12);
244
        $this->add_comment('New comment', $coursecontext1);
245
        $this->add_comment('New comment', $coursecontext1);
246
        $this->add_comment('New comment', $coursecontext2);
247
 
248
        // Export all of the data for the context.
249
        $this->export_context_data_for_user($this->student12->id, $coursecontext1, 'block_comments');
250
        $writer = \core_privacy\local\request\writer::with_context($coursecontext1);
251
        $this->assertTrue($writer->has_any_data());
252
    }
253
 
254
    /**
255
     * Test for provider::delete_data_for_all_users_in_context().
256
     */
11 efrain 257
    public function test_delete_data_for_all_users_in_context(): void {
1 efrain 258
        global $DB;
259
 
260
        $coursecontext1 = \context_course::instance($this->course1->id);
261
        $coursecontext2 = \context_course::instance($this->course2->id);
262
 
263
        $this->setUser($this->student1);
264
        $this->add_comment('New comment', $coursecontext1);
265
 
266
        $this->setUser($this->student2);
267
        $this->add_comment('New comment', $coursecontext2);
268
 
269
        $this->setUser($this->student12);
270
        $this->add_comment('New comment', $coursecontext1);
271
        $this->add_comment('New comment', $coursecontext1);
272
        $this->add_comment('New comment', $coursecontext2);
273
 
274
        // Before deletion, we should have 3 comments in $coursecontext1 and 2 comments in $coursecontext2.
275
        $this->assertEquals(
276
                3,
277
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext1->id])
278
        );
279
        $this->assertEquals(
280
                2,
281
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext2->id])
282
        );
283
 
284
        // Delete data based on context.
285
        provider::delete_data_for_all_users_in_context($coursecontext1);
286
 
287
        // After deletion, the comments for $coursecontext1 should have been deleted.
288
        $this->assertEquals(
289
                0,
290
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext1->id])
291
        );
292
        $this->assertEquals(
293
                2,
294
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext2->id])
295
        );
296
    }
297
 
298
    /**
299
     * Test for provider::delete_data_for_all_users_in_context() when there are also comments from other plugins.
300
     */
11 efrain 301
    public function test_delete_data_for_all_users_in_context_with_comments_from_other_plugins(): void {
1 efrain 302
        global $DB;
303
 
304
        $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
305
        $instance = $assigngenerator->create_instance(['course' => $this->course1]);
306
        $cm = get_coursemodule_from_instance('assign', $instance->id);
307
        $assigncontext = \context_module::instance($cm->id);
308
        $assign = new \assign($assigncontext, $cm, $this->course1);
309
 
310
        // Add a comments block in the assignment page.
311
        $this->add_comments_block_in_context($assigncontext);
312
 
313
        $submission = $assign->get_user_submission($this->student1->id, true);
314
 
315
        $options = new \stdClass();
316
        $options->area = 'submission_comments';
317
        $options->course = $assign->get_course();
318
        $options->context = $assigncontext;
319
        $options->itemid = $submission->id;
320
        $options->component = 'assignsubmission_comments';
321
        $options->showcount = true;
322
        $options->displaycancel = true;
323
 
324
        $comment = new \comment($options);
325
        $comment->set_post_permission(true);
326
 
327
        $this->setUser($this->student1);
328
        $comment->add('Comment from student 1');
329
 
330
        $this->add_comment('New comment', $assigncontext);
331
 
332
        $this->setUser($this->student2);
333
        $this->add_comment('New comment', $assigncontext);
334
 
335
        // Before deletion, we should have 3 comments in $assigncontext.
336
        // One comment is for the assignment submission and 2 are for the comments block.
337
        $this->assertEquals(
338
                3,
339
                $DB->count_records('comments', ['contextid' => $assigncontext->id])
340
        );
341
        $this->assertEquals(
342
                2,
343
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $assigncontext->id])
344
        );
345
 
346
        provider::delete_data_for_all_users_in_context($assigncontext);
347
 
348
        // After deletion, the comments for $assigncontext in the comment block should have been deleted,
349
        // but the assignment submission comment should be left.
350
        $this->assertEquals(
351
                1,
352
                $DB->count_records('comments', ['contextid' => $assigncontext->id])
353
        );
354
        $this->assertEquals(
355
                0,
356
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $assigncontext->id])
357
        );
358
    }
359
 
360
    /**
361
     * Test for provider::delete_data_for_user().
362
     */
11 efrain 363
    public function test_delete_data_for_user(): void {
1 efrain 364
        global $DB;
365
 
366
        $coursecontext1 = \context_course::instance($this->course1->id);
367
        $coursecontext2 = \context_course::instance($this->course2->id);
368
 
369
        $this->setUser($this->student1);
370
        $this->add_comment('New comment', $coursecontext1);
371
 
372
        $this->setUser($this->student2);
373
        $this->add_comment('New comment', $coursecontext2);
374
 
375
        $this->setUser($this->student12);
376
        $this->add_comment('New comment', $coursecontext1);
377
        $this->add_comment('New comment', $coursecontext1);
378
        $this->add_comment('New comment', $coursecontext2);
379
 
380
        // Before deletion, we should have 3 comments in $coursecontext1 and 2 comments in $coursecontext2,
381
        // and 3 comments by student12 in $coursecontext1 and $coursecontext2 combined.
382
        $this->assertEquals(
383
                3,
384
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext1->id])
385
        );
386
        $this->assertEquals(
387
                2,
388
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext2->id])
389
        );
390
        $this->assertEquals(
391
                3,
392
                $DB->count_records('comments', ['component' => 'block_comments', 'userid' => $this->student12->id])
393
        );
394
 
395
        $contextlist = new \core_privacy\local\request\approved_contextlist($this->student12, 'block_comments',
396
                [$coursecontext1->id, $coursecontext2->id]);
397
        provider::delete_data_for_user($contextlist);
398
 
399
        // After deletion, the comments for the student12 should have been deleted.
400
        $this->assertEquals(
401
                1,
402
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext1->id])
403
        );
404
        $this->assertEquals(
405
                1,
406
                $DB->count_records('comments', ['component' => 'block_comments', 'contextid' => $coursecontext2->id])
407
        );
408
        $this->assertEquals(
409
                0,
410
                $DB->count_records('comments', ['component' => 'block_comments', 'userid' => $this->student12->id])
411
        );
412
    }
413
 
414
    /**
415
     * Test for provider::delete_data_for_user() when there are also comments from other plugins.
416
     */
11 efrain 417
    public function test_delete_data_for_user_with_comments_from_other_plugins(): void {
1 efrain 418
        global $DB;
419
 
420
        $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
421
        $instance = $assigngenerator->create_instance(['course' => $this->course1]);
422
        $cm = get_coursemodule_from_instance('assign', $instance->id);
423
        $assigncontext = \context_module::instance($cm->id);
424
        $assign = new \assign($assigncontext, $cm, $this->course1);
425
 
426
        // Add a comments block in the assignment page.
427
        $this->add_comments_block_in_context($assigncontext);
428
 
429
        $submission = $assign->get_user_submission($this->student1->id, true);
430
 
431
        $options = new \stdClass();
432
        $options->area = 'submission_comments';
433
        $options->course = $assign->get_course();
434
        $options->context = $assigncontext;
435
        $options->itemid = $submission->id;
436
        $options->component = 'assignsubmission_comments';
437
        $options->showcount = true;
438
        $options->displaycancel = true;
439
 
440
        $comment = new \comment($options);
441
        $comment->set_post_permission(true);
442
 
443
        $this->setUser($this->student1);
444
        $comment->add('Comment from student 1');
445
 
446
        $this->add_comment('New comment', $assigncontext);
447
        $this->add_comment('New comment', $assigncontext);
448
 
449
        // Before deletion, we should have 3 comments in $assigncontext.
450
        // one comment is for the assignment submission and 2 are for the comments block.
451
        $this->assertEquals(
452
                3,
453
                $DB->count_records('comments', ['contextid' => $assigncontext->id])
454
        );
455
 
456
        $contextlist = new \core_privacy\local\request\approved_contextlist($this->student1, 'block_comments',
457
                [$assigncontext->id]);
458
        provider::delete_data_for_user($contextlist);
459
 
460
        // After deletion, the comments for the student1 in the comment block should have been deleted,
461
        // but the assignment submission comment should be left.
462
        $this->assertEquals(
463
                1,
464
                $DB->count_records('comments', ['contextid' => $assigncontext->id])
465
        );
466
        $this->assertEquals(
467
                0,
468
                $DB->count_records('comments', ['component' => 'block_comments', 'userid' => $this->student1->id])
469
        );
470
    }
471
 
472
    /**
473
     * Test that only users within a course context are fetched.
474
     * @group qtesttt
475
     */
11 efrain 476
    public function test_get_users_in_context(): void {
1 efrain 477
        $component = 'block_comments';
478
 
479
        $coursecontext1 = \context_course::instance($this->course1->id);
480
        $coursecontext2 = \context_course::instance($this->course2->id);
481
 
482
        $userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
483
        provider::get_users_in_context($userlist1);
484
        $this->assertCount(0, $userlist1);
485
 
486
        $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
487
        provider::get_users_in_context($userlist2);
488
        $this->assertCount(0, $userlist2);
489
 
490
        $this->setUser($this->student12);
491
        $this->add_comment('New comment', $coursecontext1);
492
        $this->add_comment('New comment', $coursecontext2);
493
        $this->setUser($this->student1);
494
        $this->add_comment('New comment', $coursecontext1);
495
 
496
        // The list of users should contain user12 and user1.
497
        provider::get_users_in_context($userlist1);
498
        $this->assertCount(2, $userlist1);
499
        $this->assertTrue(in_array($this->student1->id, $userlist1->get_userids()));
500
        $this->assertTrue(in_array($this->student12->id, $userlist1->get_userids()));
501
 
502
        // The list of users should contain user12.
503
        provider::get_users_in_context($userlist2);
504
        $this->assertCount(1, $userlist2);
505
        $expected = [$this->student12->id];
506
        $actual = $userlist2->get_userids();
507
        $this->assertEquals($expected, $actual);
508
    }
509
 
510
    /**
511
     * Test that data for users in approved userlist is deleted.
512
     */
11 efrain 513
    public function test_delete_data_for_users(): void {
1 efrain 514
        $component = 'block_comments';
515
 
516
        $coursecontext1 = \context_course::instance($this->course1->id);
517
        $coursecontext2 = \context_course::instance($this->course2->id);
518
 
519
        $this->setUser($this->student12);
520
        $this->add_comment('New comment', $coursecontext1);
521
        $this->add_comment('New comment', $coursecontext2);
522
        $this->setUser($this->student1);
523
        $this->add_comment('New comment', $coursecontext1);
524
 
525
        $userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
526
        provider::get_users_in_context($userlist1);
527
        $this->assertCount(2, $userlist1);
528
 
529
        $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
530
        provider::get_users_in_context($userlist2);
531
        $this->assertCount(1, $userlist2);
532
 
533
        // Convert $userlist1 into an approved_contextlist.
534
        $approvedlist1 = new approved_userlist($coursecontext1, $component, $userlist1->get_userids());
535
        // Delete using delete_data_for_user.
536
        provider::delete_data_for_users($approvedlist1);
537
 
538
        // Re-fetch users in coursecontext1.
539
        $userlist1 = new \core_privacy\local\request\userlist($coursecontext1, $component);
540
        provider::get_users_in_context($userlist1);
541
        // The user data in coursecontext1 should be deleted.
542
        $this->assertCount(0, $userlist1);
543
 
544
        // Re-fetch users in coursecontext2.
545
        $userlist2 = new \core_privacy\local\request\userlist($coursecontext2, $component);
546
        provider::get_users_in_context($userlist2);
547
        // The user data in coursecontext2 should be still present.
548
        $this->assertCount(1, $userlist2);
549
    }
550
 
551
    /**
552
     * Test for provider::delete_data_for_user() when there are also comments from other plugins.
553
     */
11 efrain 554
    public function test_delete_data_for_users_with_comments_from_other_plugins(): void {
1 efrain 555
        $component = 'block_comments';
556
 
557
        $assigngenerator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
558
        $instance = $assigngenerator->create_instance(['course' => $this->course1]);
559
        $cm = get_coursemodule_from_instance('assign', $instance->id);
560
        $assigncontext = \context_module::instance($cm->id);
561
        $assign = new \assign($assigncontext, $cm, $this->course1);
562
 
563
        // Add a comments block in the assignment page.
564
        $this->add_comments_block_in_context($assigncontext);
565
 
566
        $submission = $assign->get_user_submission($this->student1->id, true);
567
 
568
        $options = new \stdClass();
569
        $options->area = 'submission_comments';
570
        $options->course = $assign->get_course();
571
        $options->context = $assigncontext;
572
        $options->itemid = $submission->id;
573
        $options->component = 'assignsubmission_comments';
574
        $options->showcount = true;
575
        $options->displaycancel = true;
576
 
577
        $comment = new \comment($options);
578
        $comment->set_post_permission(true);
579
 
580
        $this->setUser($this->student1);
581
        $comment->add('Comment from student 1');
582
 
583
        $this->add_comment('New comment', $assigncontext);
584
        $this->add_comment('New comment', $assigncontext);
585
 
586
        $userlist1 = new \core_privacy\local\request\userlist($assigncontext, $component);
587
        provider::get_users_in_context($userlist1);
588
        $this->assertCount(1, $userlist1);
589
 
590
        // Convert $userlist1 into an approved_contextlist.
591
        $approvedlist = new approved_userlist($assigncontext, $component, $userlist1->get_userids());
592
        // Delete using delete_data_for_user.
593
        provider::delete_data_for_users($approvedlist);
594
 
595
        // Re-fetch users in assigncontext.
596
        $userlist1 = new \core_privacy\local\request\userlist($assigncontext, $component);
597
        provider::get_users_in_context($userlist1);
598
        // The user data in assigncontext should be deleted.
599
        $this->assertCount(0, $userlist1);
600
    }
601
}