Proyectos de Subversion Moodle

Rev

| 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
namespace report_log;
18
 
19
use context_course;
20
use core_user;
21
 
22
/**
23
 * Class report_log\renderable_test to cover functions in \report_log_renderable.
24
 *
25
 * @package    report_log
26
 * @copyright  2023 Stephan Robotta <stephan.robotta@bfh.ch>
27
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
28
 */
29
class renderable_test extends \advanced_testcase {
30
    /**
31
     * @var int The course with separate groups.
32
     */
33
    const COURSE_SEPARATE_GROUP = 0;
34
    /**
35
     * @var int The course with separate groups.
36
     */
37
    const COURSE_VISIBLE_GROUP = 1;
38
    /**
39
     * @var int The course with separate groups.
40
     */
41
    const COURSE_NO_GROUP = 2;
42
    /**
43
     * @var array The setup of users.
44
     */
45
    const SETUP_USER_DEFS = [
46
        // Make student2 also member of group1.
47
        'student' => [
48
            'student0' => ['group0'],
49
            'student1' => ['group1'],
50
            'student2' => ['group0', 'group1'],
51
            'student3' => [],
52
        ],
53
        // Make teacher2 also member of group1.
54
        'teacher' => [
55
            'teacher0' => ['group0'],
56
            'teacher1' => ['group1'],
57
            'teacher2' => ['group0', 'group1'],
58
            'teacher3' => [],
59
        ],
60
        // Make editingteacher also member of group1.
61
        'editingteacher' => [
62
            'editingteacher0' => ['group0'],
63
            'editingteacher1' => ['group1'],
64
            'editingteacher2' => ['group0', 'group1'],
65
        ],
66
    ];
67
    /**
68
     * @var array|\stdClass all users indexed by username.
69
     */
70
    private $users = [];
71
    /**
72
     * @var array The groups by courses (array of array).
73
     */
74
    private $groupsbycourse = [];
75
    /**
76
     * @var array The courses.
77
     */
78
    private $courses;
79
 
80
    /**
81
     * Get the data provider for test_get_user_list().
82
     *
83
     * @return array
84
     */
85
    public static function get_user_visibility_list_provider(): array {
86
        return [
87
            'separategroups: student 0' => [
88
                self::COURSE_SEPARATE_GROUP,
89
                'student0',
90
                // All users in group 0.
91
                [
92
                    'student0', 'student2',
93
                    'teacher0', 'teacher2',
94
                    'editingteacher0', 'editingteacher2',
95
                ],
96
            ],
97
            'separategroups: student 1' => [
98
                self::COURSE_SEPARATE_GROUP,
99
                'student1',
100
                // All users in group1.
101
                [
102
                    'student1', 'student2',
103
                    'teacher1', 'teacher2',
104
                    'editingteacher1', 'editingteacher2',
105
                ],
106
            ],
107
            'separategroups: student 2' => [
108
                self::COURSE_SEPARATE_GROUP,
109
                'student2',
110
                // All users in group0 and group1.
111
                [
112
                    'student0', 'student1', 'student2',
113
                    'teacher0', 'teacher1', 'teacher2',
114
                    'editingteacher0', 'editingteacher1', 'editingteacher2',
115
                ],
116
            ],
117
            'separategroups: student3' => [
118
                self::COURSE_SEPARATE_GROUP,
119
                'student3',
120
                // Student 3 is not in any group so should only see user without a group.
121
                [
122
                    'student3',
123
                    'teacher3',
124
                ],
125
            ],
126
            'separategroups: editing teacher 0' => [
127
                self::COURSE_SEPARATE_GROUP,
128
                'editingteacher0',
129
                // All users including student 3 as we can see all users (event the one not in a group).
130
                [
131
                    'student0', 'student1', 'student2', 'student3',
132
                    'teacher0', 'teacher1', 'teacher2', 'teacher3',
133
                    'editingteacher0', 'editingteacher1', 'editingteacher2',
134
                ],
135
            ],
136
            'separategroups: teacher 0' => [
137
                self::COURSE_SEPARATE_GROUP,
138
                'teacher0',
139
                // All users in group 0.
140
                [
141
                    'student0', 'student2',
142
                    'teacher0', 'teacher2',
143
                    'editingteacher0', 'editingteacher2',
144
                ],
145
            ],
146
            'separategroups: teacher 2' => [
147
                self::COURSE_SEPARATE_GROUP,
148
                'teacher2',
149
                // All users in group0 and group1.
150
                [
151
                    'student0', 'student1', 'student2',
152
                    'teacher0', 'teacher1', 'teacher2',
153
                    'editingteacher0', 'editingteacher1', 'editingteacher2',
154
                ],
155
            ],
156
            'separategroups: teacher 3' => [
157
                self::COURSE_SEPARATE_GROUP,
158
                'teacher3',
159
                // Teacher 3 is not in any group so should only see user without a group.
160
                [
161
                    'student3',
162
                    'teacher3',
163
                ],
164
            ],
165
            'separategroups: teacher 2 with group set to group 1' => [
166
                self::COURSE_SEPARATE_GROUP,
167
                'teacher2',
168
                // All users in group1.
169
                [
170
                    'student1', 'student2',
171
                    'teacher1', 'teacher2',
172
                    'editingteacher1', 'editingteacher2',
173
                ],
174
                'group1',
175
            ],
176
            'visiblegroup: editing teacher' => [
177
                self::COURSE_VISIBLE_GROUP,
178
                'editingteacher0',
179
                // All users.
180
                [
181
                    'student0', 'student1', 'student2', 'student3',
182
                    'teacher0', 'teacher1', 'teacher2', 'teacher3',
183
                    'editingteacher0', 'editingteacher1', 'editingteacher2',
184
                ],
185
            ],
186
            'visiblegroup: student' => [
187
                self::COURSE_VISIBLE_GROUP,
188
                'student0',
189
                // All users.
190
                [
191
                    'student0', 'student1', 'student2', 'student3',
192
                    'teacher0', 'teacher1', 'teacher2', 'teacher3',
193
                    'editingteacher0', 'editingteacher1', 'editingteacher2',
194
                ],
195
            ],
196
            'visiblegroup: teacher 0' => [
197
                self::COURSE_VISIBLE_GROUP,
198
                'teacher2',
199
                // All users.
200
                [
201
                    'student0', 'student1', 'student2', 'student3',
202
                    'teacher0', 'teacher1', 'teacher2', 'teacher3',
203
                    'editingteacher0', 'editingteacher1', 'editingteacher2',
204
                ],
205
            ],
206
            'visiblegroup: editing teacher 0' => [
207
                self::COURSE_VISIBLE_GROUP,
208
                'editingteacher0',
209
                // All users.
210
                [
211
                    'student0', 'student1', 'student2', 'student3',
212
                    'teacher0', 'teacher1', 'teacher2', 'teacher3',
213
                    'editingteacher0', 'editingteacher1', 'editingteacher2',
214
                ],
215
            ],
216
            'visiblegroup: teacher 2 with group set to group 1' => [
217
                self::COURSE_VISIBLE_GROUP,
218
                'teacher2',
219
                // All users in group1.
220
                [
221
                    'student1', 'student2',
222
                    'teacher1', 'teacher2',
223
                    'editingteacher1', 'editingteacher2',
224
                ],
225
                'group1',
226
            ],
227
        ];
228
    }
229
 
230
    /**
231
     * Data provider for test_get_group_list().
232
     *
233
     * @return array
234
     */
235
    public static function get_group_list_provider(): array {
236
        return [
237
            // The student sees his own group only.
238
            'separategroup: student in one group' => [self::COURSE_SEPARATE_GROUP, 'student0', 1],
239
            'separategroup: student in two groups' => [self::COURSE_SEPARATE_GROUP, 'student2', 2],
240
            // While the teacher is not allowed to see all groups.
241
            'separategroup: teacher in one group' => [self::COURSE_SEPARATE_GROUP, 'teacher0', 1],
242
            'separategroup: teacher in two groups' => [self::COURSE_SEPARATE_GROUP, 'teacher2', 2],
243
            // But editing teacher should see all.
244
            'separategroup: editingteacher' => [self::COURSE_SEPARATE_GROUP, 'editingteacher0', 2],
245
            // The student sees all groups.
246
            'visiblegroup: student in one group' => [self::COURSE_VISIBLE_GROUP, 'student0', 2],
247
            // Same for teacher.
248
            'visiblegroup: teacher in one group' => [self::COURSE_VISIBLE_GROUP, 'teacher0', 2],
249
            // And editing teacher.
250
            'visiblegroup: editingteacher' => [self::COURSE_VISIBLE_GROUP, 'editingteacher0', 2],
251
            // No group.
252
            'nogroups: student in one group' => [self::COURSE_NO_GROUP, 'student0', 0],
253
            // Same for teacher.
254
            'nogroups: teacher in one group' => [self::COURSE_NO_GROUP, 'teacher0', 0],
255
            // And editing teacher.
256
            'nogroups: editingteacher' => [self::COURSE_NO_GROUP, 'editingteacher0', 0],
257
        ];
258
    }
259
 
260
    /**
261
     * Set up a course with two groups, three students being each in one of the groups,
262
     * two teachers each in either group while the second teacher is also member of the other group.
263
     *
264
     * @return void
265
     * @throws \coding_exception
266
     */
267
    public function setUp(): void {
268
        $this->resetAfterTest();
269
        $this->courses[self::COURSE_SEPARATE_GROUP] = $this->getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS]);
270
        $this->courses[self::COURSE_VISIBLE_GROUP] = $this->getDataGenerator()->create_course(['groupmode' => VISIBLEGROUPS]);
271
        $this->courses[self::COURSE_NO_GROUP] = $this->getDataGenerator()->create_course();
272
 
273
        foreach ($this->courses as $coursetype => $course) {
274
            if ($coursetype == self::COURSE_NO_GROUP) {
275
                continue;
276
            }
277
            $this->groupsbycourse[$coursetype] = [];
278
            $this->groupsbycourse[$coursetype]['group0'] =
279
                $this->getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'group0']);
280
            $this->groupsbycourse[$coursetype]['group1'] =
281
                $this->getDataGenerator()->create_group(['courseid' => $course->id, 'name' => 'group1']);
282
        }
283
 
284
        foreach (self::SETUP_USER_DEFS as $role => $userdefs) {
285
            foreach ($userdefs as $username => $groups) {
286
                $user = $this->getDataGenerator()->create_user(
287
                    [
288
                        'username' => $username,
289
                        'firstname' => "FN{$role}{$username}",
290
                        'lastname' => "LN{$role}{$username}",
291
                    ]);
292
                foreach ($this->courses as $coursetype => $course) {
293
                    $this->getDataGenerator()->enrol_user($user->id, $course->id, $role);
294
                    foreach ($groups as $groupname) {
295
                        if ($coursetype == self::COURSE_NO_GROUP) {
296
                            continue;
297
                        }
298
                        $this->getDataGenerator()->create_group_member([
299
                            'groupid' => $this->groupsbycourse[$coursetype][$groupname]->id,
300
                            'userid' => $user->id,
301
                        ]);
302
                    }
303
                }
304
                $this->users[$username] = $user;
305
            }
306
        }
307
    }
308
 
309
    /**
310
     * Test report_log_renderable::get_user_list().
311
     *
312
     * @param int $courseindex
313
     * @param string $username
314
     * @param array $expectedusers
315
     * @param string|null $groupname
316
     * @covers       \report_log_renderable::get_user_list
317
     * @dataProvider get_user_visibility_list_provider
318
     * @return void
319
     */
320
    public function test_get_user_list(int $courseindex, string $username, array $expectedusers,
321
        string $groupname = null): void {
322
        global $PAGE, $CFG;
323
        $currentcourse = $this->courses[$courseindex];
324
        $PAGE->set_url('/report/log/index.php?id=' . $currentcourse->id);
325
        // Fetch all users of group 1 and the guest user.
326
        $currentuser = $this->users[$username];
327
        $this->setUser($currentuser->id);
328
        $groupid = 0;
329
        if ($groupname) {
330
            $groupid = $this->groupsbycourse[$courseindex][$groupname]->id;
331
        }
332
        $renderable = new \report_log_renderable(
333
            "", (int) $currentcourse->id, $currentuser->id, 0, '', $groupid);
334
        $userlist = $renderable->get_user_list();
335
        unset($userlist[$CFG->siteguest]); // We ignore guest.
336
        $usersid = array_keys($userlist);
337
 
338
        $users = array_map(function($userid) {
339
            return core_user::get_user($userid);
340
        }, $usersid);
341
 
342
        // Now check that the users are the expected ones.
343
        asort($expectedusers);
344
        $userlistbyname = array_column($users, 'username');
345
        asort($userlistbyname);
346
        $this->assertEquals(array_values($expectedusers), array_values($userlistbyname));
347
 
348
        // Check that users are in order lastname > firstname > id.
349
        $sortedusers = $users;
350
        // Sort user by lastname > firstname > id.
351
        usort($sortedusers, function($a, $b) {
352
            if ($a->lastname != $b->lastname) {
353
                return $a->lastname <=> $b->lastname;
354
            }
355
            if ($a->firstname != $b->firstname) {
356
                return $a->firstname <=> $b->firstname;
357
            }
358
            return $a->id <=> $b->id;
359
        });
360
 
361
        $sortedusernames = array_column($sortedusers, 'username');
362
        $userlistbyname = array_column($users, 'username');
363
        $this->assertEquals($sortedusernames, $userlistbyname);
364
 
365
    }
366
 
367
    /**
368
     * Test report_log_renderable::get_group_list().
369
     *
370
     * @covers       \report_log_renderable::get_group_list
371
     * @dataProvider get_group_list_provider
372
     * @return void
373
     */
374
    public function test_get_group_list($courseindex, $username, $expectedcount): void {
375
        global $PAGE;
376
        $PAGE->set_url('/report/log/index.php?id=' . $this->courses[$courseindex]->id);
377
        $this->setUser($this->users[$username]->id);
378
        $renderable = new \report_log_renderable("", (int) $this->courses[$courseindex]->id, $this->users[$username]->id);
379
        $groups = $renderable->get_group_list();
380
        $this->assertCount($expectedcount, $groups);
381
    }
382
 
383
    /**
384
     * Test table_log
385
     *
386
     * @param int $courseindex
387
     * @param string $username
388
     * @param array $expectedusers
389
     * @param string|null $groupname
390
     * @covers       \report_log_renderable::get_user_list
391
     * @dataProvider get_user_visibility_list_provider
392
     * @return void
393
     */
394
    public function test_get_table_logs(int $courseindex, string $username, array $expectedusers, ?string $groupname = null): void {
395
        global $DB, $PAGE;
396
        $this->preventResetByRollback(); // This is to ensure that we can actually trigger event and record them in the log store.
397
        // Configure log store.
398
        set_config('enabled_stores', 'logstore_standard', 'tool_log');
399
        $manager = get_log_manager(true);
400
        $DB->delete_records('logstore_standard_log');
401
 
402
        foreach ($this->courses as $course) {
403
            foreach ($this->users as $user) {
404
                $eventdata = [
405
                    'context' => context_course::instance($course->id),
406
                    'userid' => $user->id,
407
                ];
408
                $event = \core\event\course_viewed::create($eventdata);
409
                $event->trigger();
410
            }
411
        }
412
        $stores = $manager->get_readers();
413
        $store = $stores['logstore_standard'];
414
        // Build the report.
415
        $currentuser = $this->users[$username];
416
        $this->setUser($currentuser->id);
417
        $groupid = 0;
418
        if ($groupname) {
419
            $groupid = $this->groupsbycourse[$courseindex][$groupname]->id;
420
        }
421
        $PAGE->set_url('/report/log/index.php?id=' . $this->courses[$courseindex]->id);
422
        $renderable = new \report_log_renderable("", (int) $this->courses[$courseindex]->id, 0, 0, '', $groupid);
423
        $renderable->setup_table();
424
        $table = $renderable->tablelog;
425
        $store->flush();
426
        $table->query_db(100);
427
        $usernames = [];
428
        foreach ($table->rawdata as $event) {
429
            if (get_class($event) !== \core\event\course_viewed::class) {
430
                continue;
431
            }
432
            $user = core_user::get_user($event->userid, '*', MUST_EXIST);
433
            $usernames[] = $user->username;
434
        }
435
        sort($expectedusers);
436
        sort($usernames);
437
        $this->assertEquals($expectedusers, $usernames);
438
    }
439
}