Proyectos de Subversion Moodle

Rev

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