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
 * Test non-plugin enrollib parts.
19
 *
20
 * @package    core_enrol
21
 * @category   phpunit
22
 * @copyright  2012 Petr Skoda {@link http://skodak.org}
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24
 */
25
 
26
use core\plugininfo\enrol;
27
 
28
defined('MOODLE_INTERNAL') || die();
29
 
30
 
31
/**
32
 * Test non-plugin enrollib parts.
33
 *
34
 * @package    core
35
 * @category   phpunit
36
 * @copyright  2012 Petr Skoda {@link http://skodak.org}
37
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38
 */
1441 ariadna 39
final class enrollib_test extends advanced_testcase {
1 efrain 40
 
11 efrain 41
    public function test_enrol_get_all_users_courses(): void {
1 efrain 42
        global $DB, $CFG;
43
 
44
        $this->resetAfterTest();
45
 
1441 ariadna 46
        // Use a mock incrementing clock to ensure deterministic and testable time values.
47
        $clock = $this->mock_clock_with_incrementing(1750000000);
48
 
1 efrain 49
        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
50
        $this->assertNotEmpty($studentrole);
51
        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
52
        $this->assertNotEmpty($teacherrole);
53
 
54
        $admin = get_admin();
55
        $user1 = $this->getDataGenerator()->create_user();
56
        $user2 = $this->getDataGenerator()->create_user();
57
        $user3 = $this->getDataGenerator()->create_user();
58
        $user4 = $this->getDataGenerator()->create_user();
59
        $user5 = $this->getDataGenerator()->create_user();
60
 
61
        $category1 = $this->getDataGenerator()->create_category(array('visible'=>0));
62
        $category2 = $this->getDataGenerator()->create_category();
63
 
64
        $course1 = $this->getDataGenerator()->create_course(array(
65
            'shortname' => 'Z',
66
            'idnumber' => '123',
67
            'category' => $category1->id,
68
        ));
69
        $course2 = $this->getDataGenerator()->create_course(array(
70
            'shortname' => 'X',
71
            'idnumber' => '789',
72
            'category' => $category2->id,
73
        ));
74
        $course3 = $this->getDataGenerator()->create_course(array(
75
            'shortname' => 'Y',
76
            'idnumber' => '456',
77
            'category' => $category2->id,
78
            'visible' => 0,
79
        ));
80
        $course4 = $this->getDataGenerator()->create_course(array(
81
            'shortname' => 'W',
82
            'category' => $category2->id,
83
        ));
84
 
85
        $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
86
        $DB->set_field('enrol', 'status', ENROL_INSTANCE_DISABLED, array('id'=>$maninstance1->id));
87
        $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
88
        $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
89
        $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
90
        $maninstance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
91
 
92
        $manual = enrol_get_plugin('manual');
93
        $this->assertNotEmpty($manual);
94
 
95
        $manual->enrol_user($maninstance1, $user1->id, $teacherrole->id);
96
        $manual->enrol_user($maninstance1, $user2->id, $studentrole->id);
97
        $manual->enrol_user($maninstance1, $user4->id, $teacherrole->id, 0, 0, ENROL_USER_SUSPENDED);
98
        $manual->enrol_user($maninstance1, $admin->id, $studentrole->id);
99
 
100
        $manual->enrol_user($maninstance2, $user1->id);
101
        $manual->enrol_user($maninstance2, $user2->id);
1441 ariadna 102
        $manual->enrol_user($maninstance2, $user3->id, 0, 1, $clock->time() + HOURSECS);
1 efrain 103
 
104
        $manual->enrol_user($maninstance3, $user1->id);
105
        $manual->enrol_user($maninstance3, $user2->id);
1441 ariadna 106
        $manual->enrol_user($maninstance3, $user3->id, 0, 1, $clock->time() - HOURSECS);
1 efrain 107
        $manual->enrol_user($maninstance3, $user4->id, 0, 0, 0, ENROL_USER_SUSPENDED);
108
 
1441 ariadna 109
        $manual->enrol_user($maninstance4, $user5->id, 0, $clock->time());
1 efrain 110
 
111
        $courses = enrol_get_all_users_courses($CFG->siteguest);
112
        $this->assertSame(array(), $courses);
113
 
114
        $courses = enrol_get_all_users_courses(0);
115
        $this->assertSame(array(), $courses);
116
 
117
        // Results are sorted by visibility, sortorder by default (in our case order of creation)
118
 
119
        $courses = enrol_get_all_users_courses($admin->id);
120
        $this->assertCount(1, $courses);
121
        $this->assertEquals(array($course1->id), array_keys($courses));
122
 
123
        $courses = enrol_get_all_users_courses($admin->id, true);
124
        $this->assertCount(0, $courses);
125
        $this->assertEquals(array(), array_keys($courses));
126
 
127
        $courses = enrol_get_all_users_courses($user1->id);
128
        $this->assertCount(3, $courses);
129
        $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
130
 
131
        $courses = enrol_get_all_users_courses($user1->id, true);
132
        $this->assertCount(2, $courses);
133
        $this->assertEquals(array($course2->id, $course3->id), array_keys($courses));
134
 
135
        $courses = enrol_get_all_users_courses($user2->id);
136
        $this->assertCount(3, $courses);
137
        $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
138
 
139
        $courses = enrol_get_all_users_courses($user2->id, true);
140
        $this->assertCount(2, $courses);
141
        $this->assertEquals(array($course2->id, $course3->id), array_keys($courses));
142
 
143
        $courses = enrol_get_all_users_courses($user3->id);
144
        $this->assertCount(2, $courses);
145
        $this->assertEquals(array($course2->id, $course3->id), array_keys($courses));
146
 
147
        $courses = enrol_get_all_users_courses($user3->id, true);
148
        $this->assertCount(1, $courses);
149
        $this->assertEquals(array($course2->id), array_keys($courses));
150
 
151
        $courses = enrol_get_all_users_courses($user4->id);
152
        $this->assertCount(2, $courses);
153
        $this->assertEquals(array($course1->id, $course3->id), array_keys($courses));
154
 
155
        $courses = enrol_get_all_users_courses($user4->id, true);
156
        $this->assertCount(0, $courses);
157
        $this->assertEquals(array(), array_keys($courses));
158
 
1441 ariadna 159
        $courses = enrol_get_all_users_courses($user5->id, true);
160
        $this->assertCount(1, $courses);
161
        $this->assertEquals([$course4->id], array_keys($courses));
162
 
1 efrain 163
        // Make sure sorting and columns work.
164
 
165
        $basefields = array('id', 'category', 'sortorder', 'shortname', 'fullname', 'idnumber',
166
            'startdate', 'visible', 'groupmode', 'groupmodeforce', 'defaultgroupingid');
167
 
168
        $courses = enrol_get_all_users_courses($user2->id, true);
169
        $course = reset($courses);
170
        context_helper::preload_from_record($course);
171
        $course = (array)$course;
172
        $this->assertEqualsCanonicalizing($basefields, array_keys($course));
173
 
174
        $courses = enrol_get_all_users_courses($user2->id, false, 'timecreated');
175
        $course = reset($courses);
176
        $this->assertTrue(property_exists($course, 'timecreated'));
177
 
178
        $courses = enrol_get_all_users_courses($user2->id, false, null, 'id DESC');
179
        $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses));
180
 
181
        // Make sure that implicit sorting defined in navsortmycoursessort is respected.
182
 
183
        $CFG->navsortmycoursessort = 'shortname';
184
 
185
        $courses = enrol_get_all_users_courses($user1->id);
186
        $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses));
187
 
188
        // But still the explicit sorting takes precedence over the implicit one.
189
 
190
        $courses = enrol_get_all_users_courses($user1->id, false, null, 'shortname DESC');
191
        $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
192
 
193
        // Make sure that implicit visibility sorting defined in navsortmycourseshiddenlast is respected for all course sortings.
194
 
195
        $CFG->navsortmycoursessort = 'sortorder';
196
        $CFG->navsortmycourseshiddenlast = true;
197
        $courses = enrol_get_all_users_courses($user1->id);
198
        $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
199
 
200
        $CFG->navsortmycoursessort = 'sortorder';
201
        $CFG->navsortmycourseshiddenlast = false;
202
        $courses = enrol_get_all_users_courses($user1->id);
203
        $this->assertEquals(array($course1->id, $course3->id, $course2->id), array_keys($courses));
204
 
205
        $CFG->navsortmycoursessort = 'fullname';
206
        $CFG->navsortmycourseshiddenlast = true;
207
        $courses = enrol_get_all_users_courses($user1->id);
208
        $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
209
 
210
        $CFG->navsortmycoursessort = 'fullname';
211
        $CFG->navsortmycourseshiddenlast = false;
212
        $courses = enrol_get_all_users_courses($user1->id);
213
        $this->assertEquals(array($course1->id, $course2->id, $course3->id), array_keys($courses));
214
 
215
        $CFG->navsortmycoursessort = 'shortname';
216
        $CFG->navsortmycourseshiddenlast = true;
217
        $courses = enrol_get_all_users_courses($user1->id);
218
        $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses));
219
 
220
        $CFG->navsortmycoursessort = 'shortname';
221
        $CFG->navsortmycourseshiddenlast = false;
222
        $courses = enrol_get_all_users_courses($user1->id);
223
        $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses));
224
 
225
        $CFG->navsortmycoursessort = 'idnumber';
226
        $CFG->navsortmycourseshiddenlast = true;
227
        $courses = enrol_get_all_users_courses($user1->id);
228
        $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
229
 
230
        $CFG->navsortmycoursessort = 'idnumber';
231
        $CFG->navsortmycourseshiddenlast = false;
232
        $courses = enrol_get_all_users_courses($user1->id);
233
        $this->assertEquals(array($course1->id, $course3->id, $course2->id), array_keys($courses));
234
 
235
        // But still the explicit visibility sorting takes precedence over the implicit one.
236
 
237
        $courses = enrol_get_all_users_courses($user1->id, false, null, 'visible DESC, shortname DESC');
238
        $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses));
239
    }
240
 
241
    /**
242
     * Test enrol_course_delete() without passing a user id. When a value for user id is not present, the method
243
     * should delete all enrolment related data in the course.
244
     */
11 efrain 245
    public function test_enrol_course_delete_without_userid(): void {
1 efrain 246
        global $DB;
247
 
248
        $this->resetAfterTest();
249
 
250
        // Create users.
251
        $user1 = $this->getDataGenerator()->create_user();
252
        $user2 = $this->getDataGenerator()->create_user();
253
        // Create a course.
254
        $course = $this->getDataGenerator()->create_course();
255
        $coursecontext = context_course::instance($course->id);
256
 
257
        $studentrole = $DB->get_record('role', ['shortname' => 'student']);
258
 
259
        $manual = enrol_get_plugin('manual');
260
        $manualinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual'], '*', MUST_EXIST);
261
        // Enrol user1 as a student in the course using manual enrolment.
262
        $manual->enrol_user($manualinstance, $user1->id, $studentrole->id);
263
 
264
        $self = enrol_get_plugin('self');
265
        $selfinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'], '*', MUST_EXIST);
266
        $self->update_status($selfinstance, ENROL_INSTANCE_ENABLED);
267
        // Enrol user2 as a student in the course using self enrolment.
268
        $self->enrol_user($selfinstance, $user2->id, $studentrole->id);
269
 
270
        // Delete all enrolment related records in the course.
271
        enrol_course_delete($course);
272
 
273
        // The course enrolment of user1 should not exists.
274
        $user1enrolment = $DB->get_record('user_enrolments',
275
            ['enrolid' => $manualinstance->id, 'userid' => $user1->id]);
276
        $this->assertFalse($user1enrolment);
277
 
278
        // The role assignment of user1 should not exists.
279
        $user1roleassignment = $DB->get_record('role_assignments',
280
            ['roleid' => $studentrole->id, 'userid'=> $user1->id, 'contextid' => $coursecontext->id]
281
        );
282
        $this->assertFalse($user1roleassignment);
283
 
284
        // The course enrolment of user2 should not exists.
285
        $user2enrolment = $DB->get_record('user_enrolments',
286
            ['enrolid' => $selfinstance->id, 'userid' => $user2->id]);
287
        $this->assertFalse($user2enrolment);
288
 
289
        // The role assignment of user2 should not exists.
290
        $user2roleassignment = $DB->get_record('role_assignments',
291
            ['roleid' => $studentrole->id, 'userid'=> $user2->id, 'contextid' => $coursecontext->id]);
292
        $this->assertFalse($user2roleassignment);
293
 
294
        // All existing course enrolment instances should not exists.
295
        $enrolmentinstances = enrol_get_instances($course->id, false);
296
        $this->assertCount(0, $enrolmentinstances);
297
    }
298
 
299
    /**
300
     * Test enrol_course_delete() when user id is present.
301
     * When a value for user id is present, the method should make sure the user has the proper capability to
302
     * un-enrol users before removing the enrolment data. If the capabilities are missing the data should not be removed.
303
     *
304
     * @dataProvider enrol_course_delete_with_userid_provider
305
     * @param array $excludedcapabilities The capabilities that should be excluded from the user's role
306
     * @param bool $expected The expected results
307
     */
11 efrain 308
    public function test_enrol_course_delete_with_userid($excludedcapabilities, $expected): void {
1 efrain 309
        global $DB;
310
 
311
        $this->resetAfterTest();
312
        // Create users.
313
        $user1 = $this->getDataGenerator()->create_user();
314
        $user2 = $this->getDataGenerator()->create_user();
315
        $user3 = $this->getDataGenerator()->create_user();
316
        // Create a course.
317
        $course = $this->getDataGenerator()->create_course();
318
        $coursecontext = context_course::instance($course->id);
319
 
320
        $studentrole = $DB->get_record('role', ['shortname' => 'student']);
321
        $editingteacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
322
 
323
        $manual = enrol_get_plugin('manual');
324
        $manualinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual'],
325
            '*', MUST_EXIST);
326
        // Enrol user1 as a student in the course using manual enrolment.
327
        $manual->enrol_user($manualinstance, $user1->id, $studentrole->id);
328
        // Enrol user3 as an editing teacher in the course using manual enrolment.
329
        // By default, the editing teacher role has the capability to un-enroll users which have been enrolled using
330
        // the existing enrolment methods.
331
        $manual->enrol_user($manualinstance, $user3->id, $editingteacherrole->id);
332
 
333
        $self = enrol_get_plugin('self');
334
        $selfinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'],
335
            '*', MUST_EXIST);
336
        $self->update_status($selfinstance, ENROL_INSTANCE_ENABLED);
337
        // Enrol user2 as a student in the course using self enrolment.
338
        $self->enrol_user($selfinstance, $user2->id, $studentrole->id);
339
 
340
        foreach($excludedcapabilities as $capability) {
341
            // Un-assign the given capability from the editing teacher role.
342
            unassign_capability($capability, $editingteacherrole->id);
343
        }
344
 
345
        // Delete only enrolment related records in the course where user3 has the required capability.
346
        enrol_course_delete($course, $user3->id);
347
 
348
        // Check the existence of the course enrolment of user1.
349
        $user1enrolmentexists = (bool) $DB->count_records('user_enrolments',
350
            ['enrolid' => $manualinstance->id, 'userid' => $user1->id]);
351
        $this->assertEquals($expected['User 1 course enrolment exists'], $user1enrolmentexists);
352
 
353
        // Check the existence of the role assignment of user1 in the course.
354
        $user1roleassignmentexists = (bool) $DB->count_records('role_assignments',
355
            ['roleid' => $studentrole->id, 'userid' => $user1->id, 'contextid' => $coursecontext->id]);
356
        $this->assertEquals($expected['User 1 role assignment exists'], $user1roleassignmentexists);
357
 
358
        // Check the existence of the course enrolment of user2.
359
        $user2enrolmentexists = (bool) $DB->count_records('user_enrolments',
360
            ['enrolid' => $selfinstance->id, 'userid' => $user2->id]);
361
        $this->assertEquals($expected['User 2 course enrolment exists'], $user2enrolmentexists);
362
 
363
        // Check the existence of the role assignment of user2 in the course.
364
        $user2roleassignmentexists = (bool) $DB->count_records('role_assignments',
365
            ['roleid' => $studentrole->id, 'userid' => $user2->id, 'contextid' => $coursecontext->id]);
366
        $this->assertEquals($expected['User 2 role assignment exists'], $user2roleassignmentexists);
367
 
368
        // Check the existence of the course enrolment of user3.
369
        $user3enrolmentexists = (bool) $DB->count_records('user_enrolments',
370
            ['enrolid' => $manualinstance->id, 'userid' => $user3->id]);
371
        $this->assertEquals($expected['User 3 course enrolment exists'], $user3enrolmentexists);
372
 
373
        // Check the existence of the role assignment of user3 in the course.
374
        $user3roleassignmentexists = (bool) $DB->count_records('role_assignments',
375
            ['roleid' => $editingteacherrole->id, 'userid' => $user3->id, 'contextid' => $coursecontext->id]);
376
        $this->assertEquals($expected['User 3 role assignment exists'], $user3roleassignmentexists);
377
 
378
        // Check the existence of the manual enrolment instance in the course.
379
        $manualinstance = (bool) $DB->count_records('enrol', ['enrol' => 'manual', 'courseid' => $course->id]);
380
        $this->assertEquals($expected['Manual course enrolment instance exists'], $manualinstance);
381
 
382
        // Check existence of the self enrolment instance in the course.
383
        $selfinstance = (bool) $DB->count_records('enrol', ['enrol' => 'self', 'courseid' => $course->id]);
384
        $this->assertEquals($expected['Self course enrolment instance exists'], $selfinstance);
385
    }
386
 
387
    /**
388
     * Data provider for test_enrol_course_delete_with_userid().
389
     *
390
     * @return array
391
     */
1441 ariadna 392
    public static function enrol_course_delete_with_userid_provider(): array {
1 efrain 393
        return [
394
            'The teacher can un-enrol users in a course' =>
395
                [
396
                    'excludedcapabilities' => [],
1441 ariadna 397
                    'expected' => [
1 efrain 398
                        // Whether certain enrolment related data still exists in the course after the deletion.
399
                        // When the user has the capabilities to un-enrol users and the enrolment plugins allow manual
400
                        // unenerolment than all course enrolment data should be removed.
401
                        'Manual course enrolment instance exists' => false,
402
                        'Self course enrolment instance exists' => false,
403
                        'User 1 course enrolment exists' => false,
404
                        'User 1 role assignment exists' => false,
405
                        'User 2 course enrolment exists' => false,
406
                        'User 2 role assignment exists' => false,
407
                        'User 3 course enrolment exists' => false,
408
                        'User 3 role assignment exists' => false
409
                    ],
410
                ],
411
            'The teacher cannot un-enrol self enrolled users'  =>
412
                [
413
                    'excludedcapabilities' => [
414
                        // Exclude the following capabilities for the editing teacher.
415
                        'enrol/self:unenrol'
416
                    ],
1441 ariadna 417
                    'expected' => [
1 efrain 418
                        // When the user does not have the capabilities to un-enrol self enrolled users, the data
419
                        // related to this enrolment method should not be removed. Everything else should be removed.
420
                        'Manual course enrolment instance exists' => false,
421
                        'Self course enrolment instance exists' => true,
422
                        'User 1 course enrolment exists' => false,
423
                        'User 1 role assignment exists' => false,
424
                        'User 2 course enrolment exists' => true,
425
                        'User 2 role assignment exists' => true,
426
                        'User 3 course enrolment exists' => false,
427
                        'User 3 role assignment exists' => false
428
                    ],
429
                ],
430
            'The teacher cannot un-enrol self and manually enrolled users' =>
431
                [
432
                    'excludedcapabilities' => [
433
                        // Exclude the following capabilities for the editing teacher.
434
                        'enrol/manual:unenrol',
435
                        'enrol/self:unenrol'
436
                    ],
1441 ariadna 437
                    'expected' => [
1 efrain 438
                        // When the user does not have the capabilities to un-enrol self and manually enrolled users,
439
                        // the data related to these enrolment methods should not be removed.
440
                        'Manual course enrolment instance exists' => true,
441
                        'Self course enrolment instance exists' => true,
442
                        'User 1 course enrolment exists' => true,
443
                        'User 1 role assignment exists' => true,
444
                        'User 2 course enrolment exists' => true,
445
                        'User 2 role assignment exists' => true,
446
                        'User 3 course enrolment exists' => true,
447
                        'User 3 role assignment exists' => true
448
                    ],
449
                ],
450
        ];
451
    }
452
 
453
 
11 efrain 454
    public function test_enrol_user_sees_own_courses(): void {
1 efrain 455
        global $DB, $CFG;
456
 
457
        $this->resetAfterTest();
458
 
459
        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
460
        $this->assertNotEmpty($studentrole);
461
        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
462
        $this->assertNotEmpty($teacherrole);
463
 
464
        $admin = get_admin();
465
        $user1 = $this->getDataGenerator()->create_user();
466
        $user2 = $this->getDataGenerator()->create_user();
467
        $user3 = $this->getDataGenerator()->create_user();
468
        $user4 = $this->getDataGenerator()->create_user();
469
        $user5 = $this->getDataGenerator()->create_user();
470
        $user6 = $this->getDataGenerator()->create_user();
471
 
472
        $category1 = $this->getDataGenerator()->create_category(array('visible'=>0));
473
        $category2 = $this->getDataGenerator()->create_category();
474
        $course1 = $this->getDataGenerator()->create_course(array('category'=>$category1->id));
475
        $course2 = $this->getDataGenerator()->create_course(array('category'=>$category2->id));
476
        $course3 = $this->getDataGenerator()->create_course(array('category'=>$category2->id, 'visible'=>0));
477
        $course4 = $this->getDataGenerator()->create_course(array('category'=>$category2->id));
478
 
479
        $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
480
        $DB->set_field('enrol', 'status', ENROL_INSTANCE_DISABLED, array('id'=>$maninstance1->id));
481
        $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
482
        $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
483
        $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
484
        $maninstance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
485
 
486
        $manual = enrol_get_plugin('manual');
487
        $this->assertNotEmpty($manual);
488
 
489
        $manual->enrol_user($maninstance1, $admin->id, $studentrole->id);
490
 
491
        $manual->enrol_user($maninstance3, $user1->id, $teacherrole->id);
492
 
493
        $manual->enrol_user($maninstance2, $user2->id, $studentrole->id);
494
 
495
        $manual->enrol_user($maninstance1, $user3->id, $studentrole->id, 1, time()+(60*60));
496
        $manual->enrol_user($maninstance2, $user3->id, 0, 1, time()-(60*60));
497
        $manual->enrol_user($maninstance3, $user2->id, $studentrole->id);
498
        $manual->enrol_user($maninstance4, $user2->id, 0, 0, 0, ENROL_USER_SUSPENDED);
499
 
500
        $manual->enrol_user($maninstance1, $user4->id, $teacherrole->id, 0, 0, ENROL_USER_SUSPENDED);
501
        $manual->enrol_user($maninstance3, $user4->id, 0, 0, 0, ENROL_USER_SUSPENDED);
502
 
503
 
504
        $this->assertFalse(enrol_user_sees_own_courses($CFG->siteguest));
505
        $this->assertFalse(enrol_user_sees_own_courses(0));
506
        $this->assertFalse(enrol_user_sees_own_courses($admin));
507
        $this->assertFalse(enrol_user_sees_own_courses(-222)); // Nonexistent user.
508
 
509
        $this->assertTrue(enrol_user_sees_own_courses($user1));
510
        $this->assertTrue(enrol_user_sees_own_courses($user2->id));
511
        $this->assertFalse(enrol_user_sees_own_courses($user3->id));
512
        $this->assertFalse(enrol_user_sees_own_courses($user4));
513
        $this->assertFalse(enrol_user_sees_own_courses($user5));
514
 
515
        $this->setAdminUser();
516
        $this->assertFalse(enrol_user_sees_own_courses());
517
 
518
        $this->setGuestUser();
519
        $this->assertFalse(enrol_user_sees_own_courses());
520
 
521
        $this->setUser(0);
522
        $this->assertFalse(enrol_user_sees_own_courses());
523
 
524
        $this->setUser($user1);
525
        $this->assertTrue(enrol_user_sees_own_courses());
526
 
527
        $this->setUser($user2);
528
        $this->assertTrue(enrol_user_sees_own_courses());
529
 
530
        $this->setUser($user3);
531
        $this->assertFalse(enrol_user_sees_own_courses());
532
 
533
        $this->setUser($user4);
534
        $this->assertFalse(enrol_user_sees_own_courses());
535
 
536
        $this->setUser($user5);
537
        $this->assertFalse(enrol_user_sees_own_courses());
538
 
539
        $user1 = $DB->get_record('user', array('id'=>$user1->id));
540
        $this->setUser($user1);
541
        $reads = $DB->perf_get_reads();
542
        $this->assertTrue(enrol_user_sees_own_courses());
543
        $this->assertGreaterThan($reads, $DB->perf_get_reads());
544
 
545
        $user1 = $DB->get_record('user', array('id'=>$user1->id));
546
        $this->setUser($user1);
547
        require_login($course3);
548
        $reads = $DB->perf_get_reads();
549
        $this->assertTrue(enrol_user_sees_own_courses());
550
        $this->assertEquals($reads, $DB->perf_get_reads());
551
    }
552
 
11 efrain 553
    public function test_enrol_get_shared_courses(): void {
1 efrain 554
        $this->resetAfterTest();
555
 
556
        $user1 = $this->getDataGenerator()->create_user();
557
        $user2 = $this->getDataGenerator()->create_user();
558
        $user3 = $this->getDataGenerator()->create_user();
559
 
560
        $course1 = $this->getDataGenerator()->create_course();
561
        $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
562
        $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
563
 
564
        $course2 = $this->getDataGenerator()->create_course();
565
        $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
566
 
567
        // Test that user1 and user2 have courses in common.
568
        $this->assertTrue(enrol_get_shared_courses($user1, $user2, false, true));
569
        // Test that user1 and user3 have no courses in common.
570
        $this->assertFalse(enrol_get_shared_courses($user1, $user3, false, true));
571
 
572
        // Test retrieving the courses in common.
573
        $sharedcourses = enrol_get_shared_courses($user1, $user2, true);
574
 
575
        // Only should be one shared course.
576
        $this->assertCount(1, $sharedcourses);
577
        $sharedcourse = array_shift($sharedcourses);
578
        // It should be course 1.
579
        $this->assertEquals($sharedcourse->id, $course1->id);
580
    }
581
 
11 efrain 582
    public function test_enrol_get_shared_courses_different_methods(): void {
1 efrain 583
        global $DB, $CFG;
584
 
585
        require_once($CFG->dirroot . '/enrol/self/externallib.php');
586
 
587
        $this->resetAfterTest();
588
 
589
        $user1 = $this->getDataGenerator()->create_user();
590
        $user2 = $this->getDataGenerator()->create_user();
591
        $user3 = $this->getDataGenerator()->create_user();
592
 
593
        $course1 = $this->getDataGenerator()->create_course();
594
 
595
        // Enrol user1 and user2 in course1 with a different enrolment methode.
596
        // Add self enrolment method for course1.
597
        $selfplugin = enrol_get_plugin('self');
598
        $this->assertNotEmpty($selfplugin);
599
 
600
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
601
        $this->assertNotEmpty($studentrole);
602
 
603
        $instance1id = $selfplugin->add_instance($course1, array('status' => ENROL_INSTANCE_ENABLED,
604
                                                                 'name' => 'Test instance 1',
605
                                                                 'customint6' => 1,
606
                                                                 'roleid' => $studentrole->id));
607
 
608
        $instance1 = $DB->get_record('enrol', array('id' => $instance1id), '*', MUST_EXIST);
609
 
610
        self::setUser($user2);
611
        // Self enrol me (user2).
612
        $result = enrol_self_external::enrol_user($course1->id);
613
 
614
        // Enrol user1 manually.
615
        $this->getDataGenerator()->enrol_user($user1->id, $course1->id, null, 'manual');
616
 
617
        $course2 = $this->getDataGenerator()->create_course();
618
        $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
619
 
620
        $course3 = $this->getDataGenerator()->create_course();
621
        $this->getDataGenerator()->enrol_user($user2->id, $course3->id);
622
 
623
        // Test that user1 and user2 have courses in common.
624
        $this->assertTrue(enrol_get_shared_courses($user1, $user2, false, true));
625
        // Test that user1 and user3 have no courses in common.
626
        $this->assertFalse(enrol_get_shared_courses($user1, $user3, false, true));
627
 
628
        // Test retrieving the courses in common.
629
        $sharedcourses = enrol_get_shared_courses($user1, $user2, true);
630
 
631
        // Only should be one shared course.
632
        $this->assertCount(1, $sharedcourses);
633
        $sharedcourse = array_shift($sharedcourses);
634
        // It should be course 1.
635
        $this->assertEquals($sharedcourse->id, $course1->id);
636
    }
637
 
638
    /**
639
     * Test user enrolment created event.
640
     */
11 efrain 641
    public function test_user_enrolment_created_event(): void {
1 efrain 642
        global $DB;
643
 
644
        $this->resetAfterTest();
645
 
646
        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
647
        $this->assertNotEmpty($studentrole);
648
 
649
        $admin = get_admin();
650
 
651
        $course1 = $this->getDataGenerator()->create_course();
652
 
653
        $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
654
 
655
        $manual = enrol_get_plugin('manual');
656
        $this->assertNotEmpty($manual);
657
 
658
        // Enrol user and capture event.
659
        $sink = $this->redirectEvents();
660
        $manual->enrol_user($maninstance1, $admin->id, $studentrole->id);
661
        $events = $sink->get_events();
662
        $sink->close();
663
        $event = array_shift($events);
664
 
665
        $dbuserenrolled = $DB->get_record('user_enrolments', array('userid' => $admin->id));
666
        $this->assertInstanceOf('\core\event\user_enrolment_created', $event);
667
        $this->assertEquals($dbuserenrolled->id, $event->objectid);
668
        $this->assertEquals(context_course::instance($course1->id), $event->get_context());
669
        $this->assertEventContextNotUsed($event);
670
    }
671
 
672
    /**
673
     * Test user_enrolment_deleted event.
674
     */
11 efrain 675
    public function test_user_enrolment_deleted_event(): void {
1 efrain 676
        global $DB;
677
 
678
        $this->resetAfterTest(true);
679
 
680
        $manualplugin = enrol_get_plugin('manual');
681
        $user = $this->getDataGenerator()->create_user();
682
        $course = $this->getDataGenerator()->create_course();
683
        $student = $DB->get_record('role', array('shortname' => 'student'));
684
 
685
        $enrol = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
686
 
687
        // Enrol user.
688
        $manualplugin->enrol_user($enrol, $user->id, $student->id);
689
 
690
        // Get the user enrolment information, used to validate legacy event data.
691
        $dbuserenrolled = $DB->get_record('user_enrolments', array('userid' => $user->id));
692
 
693
        // Unenrol user and capture event.
694
        $sink = $this->redirectEvents();
695
        $manualplugin->unenrol_user($enrol, $user->id);
696
        $events = $sink->get_events();
697
        $sink->close();
698
        $event = array_pop($events);
699
 
700
        // Validate the event.
701
        $this->assertInstanceOf('\core\event\user_enrolment_deleted', $event);
702
        $this->assertEquals(context_course::instance($course->id), $event->get_context());
703
        $this->assertEventContextNotUsed($event);
704
    }
705
 
706
    /**
707
     * Test enrol_instance_created, enrol_instance_updated and enrol_instance_deleted events.
708
     */
11 efrain 709
    public function test_instance_events(): void {
1 efrain 710
        global $DB;
711
 
712
        $this->resetAfterTest(true);
713
 
714
        $selfplugin = enrol_get_plugin('self');
715
        $studentrole = $DB->get_record('role', array('shortname' => 'student'));
716
 
717
        $course = $this->getDataGenerator()->create_course();
718
 
719
        // Creating enrol instance.
720
        $sink = $this->redirectEvents();
721
        $instanceid = $selfplugin->add_instance($course, array('status' => ENROL_INSTANCE_ENABLED,
722
                                                                'name' => 'Test instance 1',
723
                                                                'customint6' => 1,
724
                                                                'roleid' => $studentrole->id));
725
        $events = $sink->get_events();
726
        $sink->close();
727
 
728
        $this->assertCount(1, $events);
729
        $event = array_pop($events);
730
        $this->assertInstanceOf('\core\event\enrol_instance_created', $event);
731
        $this->assertEquals(context_course::instance($course->id), $event->get_context());
732
        $this->assertEquals('self', $event->other['enrol']);
733
        $this->assertEventContextNotUsed($event);
734
 
735
        // Updating enrol instance.
736
        $instance = $DB->get_record('enrol', array('id' => $instanceid));
737
        $sink = $this->redirectEvents();
738
        $selfplugin->update_status($instance, ENROL_INSTANCE_DISABLED);
739
 
740
        $events = $sink->get_events();
741
        $sink->close();
742
 
743
        $this->assertCount(1, $events);
744
        $event = array_pop($events);
745
        $this->assertInstanceOf('\core\event\enrol_instance_updated', $event);
746
        $this->assertEquals(context_course::instance($course->id), $event->get_context());
747
        $this->assertEquals('self', $event->other['enrol']);
748
        $this->assertEventContextNotUsed($event);
749
 
750
        // Deleting enrol instance.
751
        $instance = $DB->get_record('enrol', array('id' => $instanceid));
752
        $sink = $this->redirectEvents();
753
        $selfplugin->delete_instance($instance);
754
 
755
        $events = $sink->get_events();
756
        $sink->close();
757
 
758
        $this->assertCount(1, $events);
759
        $event = array_pop($events);
760
        $this->assertInstanceOf('\core\event\enrol_instance_deleted', $event);
761
        $this->assertEquals(context_course::instance($course->id), $event->get_context());
762
        $this->assertEquals('self', $event->other['enrol']);
763
        $this->assertEventContextNotUsed($event);
764
    }
765
 
766
    /**
767
     * Confirms that timemodified field was updated after modification of user enrollment
768
     */
11 efrain 769
    public function test_enrollment_update_timemodified(): void {
1 efrain 770
        global $DB;
771
 
772
        $this->resetAfterTest(true);
773
        $datagen = $this->getDataGenerator();
774
 
775
        /** @var enrol_manual_plugin $manualplugin */
776
        $manualplugin = enrol_get_plugin('manual');
777
        $this->assertNotNull($manualplugin);
778
 
779
        $studentroleid = $DB->get_field('role', 'id', ['shortname' => 'student'], MUST_EXIST);
780
        $course = $datagen->create_course();
781
        $user = $datagen->create_user();
782
 
783
        $instanceid = null;
784
        $instances = enrol_get_instances($course->id, true);
785
        foreach ($instances as $inst) {
786
            if ($inst->enrol == 'manual') {
787
                $instanceid = (int)$inst->id;
788
                break;
789
            }
790
        }
791
        if (empty($instanceid)) {
792
            $instanceid = $manualplugin->add_default_instance($course);
793
            if (empty($instanceid)) {
794
                $instanceid = $manualplugin->add_instance($course);
795
            }
796
        }
797
        $this->assertNotNull($instanceid);
798
 
799
        $instance = $DB->get_record('enrol', ['id' => $instanceid], '*', MUST_EXIST);
800
        $manualplugin->enrol_user($instance, $user->id, $studentroleid, 0, 0, ENROL_USER_ACTIVE);
801
        $userenrolorig = (int)$DB->get_field(
802
            'user_enrolments',
803
            'timemodified',
804
            ['enrolid' => $instance->id, 'userid' => $user->id],
805
            MUST_EXIST
806
        );
807
        $this->waitForSecond();
808
        $this->waitForSecond();
809
        $manualplugin->update_user_enrol($instance, $user->id, ENROL_USER_SUSPENDED);
810
        $userenrolpost = (int)$DB->get_field(
811
            'user_enrolments',
812
            'timemodified',
813
            ['enrolid' => $instance->id, 'userid' => $user->id],
814
            MUST_EXIST
815
        );
816
 
817
        $this->assertGreaterThan($userenrolorig, $userenrolpost);
818
    }
819
 
820
    /**
821
     * Test to confirm that enrol_get_my_courses only return the courses that
822
     * the logged in user is enrolled in.
823
     */
11 efrain 824
    public function test_enrol_get_my_courses_only_enrolled_courses(): void {
1 efrain 825
        $user = $this->getDataGenerator()->create_user();
826
        $course1 = $this->getDataGenerator()->create_course();
827
        $course2 = $this->getDataGenerator()->create_course();
828
        $course3 = $this->getDataGenerator()->create_course();
829
        $course4 = $this->getDataGenerator()->create_course();
830
 
831
        $this->getDataGenerator()->enrol_user($user->id, $course1->id);
832
        $this->getDataGenerator()->enrol_user($user->id, $course2->id);
833
        $this->getDataGenerator()->enrol_user($user->id, $course3->id);
834
        $this->resetAfterTest(true);
835
        $this->setUser($user);
836
 
837
        // By default this function should return all of the courses the user
838
        // is enrolled in.
839
        $courses = enrol_get_my_courses();
840
 
841
        $this->assertCount(3, $courses);
842
        $this->assertEquals($course1->id, $courses[$course1->id]->id);
843
        $this->assertEquals($course2->id, $courses[$course2->id]->id);
844
        $this->assertEquals($course3->id, $courses[$course3->id]->id);
845
 
846
        // If a set of course ids are provided then the result set will only contain
847
        // these courses.
848
        $courseids = [$course1->id, $course2->id];
849
        $courses = enrol_get_my_courses(['id'], 'visible DESC,sortorder ASC', 0, $courseids);
850
 
851
        $this->assertCount(2, $courses);
852
        $this->assertEquals($course1->id, $courses[$course1->id]->id);
853
        $this->assertEquals($course2->id, $courses[$course2->id]->id);
854
 
855
        // If the course ids list contains any ids for courses the user isn't enrolled in
856
        // then they will be ignored (in this case $course4).
857
        $courseids = [$course1->id, $course2->id, $course4->id];
858
        $courses = enrol_get_my_courses(['id'], 'visible DESC,sortorder ASC', 0, $courseids);
859
 
860
        $this->assertCount(2, $courses);
861
        $this->assertEquals($course1->id, $courses[$course1->id]->id);
862
        $this->assertEquals($course2->id, $courses[$course2->id]->id);
863
    }
864
 
865
    /**
866
     * Tests the enrol_get_my_courses function when using the $includehidden parameter, which
867
     * should remove any courses hidden from the user's timeline
868
     *
869
     * @throws coding_exception
870
     * @throws dml_exception
871
     */
11 efrain 872
    public function test_enrol_get_my_courses_include_hidden(): void {
1 efrain 873
        global $DB, $CFG;
874
 
875
        $this->resetAfterTest(true);
876
 
877
        // Create test user and 4 courses, two of which have guest access enabled.
878
        $user = $this->getDataGenerator()->create_user();
879
        $course1 = $this->getDataGenerator()->create_course(
880
            (object)array('shortname' => 'X',
881
                'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
882
                'enrol_guest_password_0' => ''));
883
        $course2 = $this->getDataGenerator()->create_course(
884
            (object)array('shortname' => 'Z',
885
                'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
886
                'enrol_guest_password_0' => ''));
887
        $course3 = $this->getDataGenerator()->create_course(
888
            (object)array('shortname' => 'Y',
889
                'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
890
                'enrol_guest_password_0' => 'frog'));
891
        $course4 = $this->getDataGenerator()->create_course(
892
            (object)array('shortname' => 'W',
893
                'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
894
                'enrol_guest_password_0' => ''));
895
 
896
        // User is enrolled in first course.
897
        $this->getDataGenerator()->enrol_user($user->id, $course1->id);
898
        $this->getDataGenerator()->enrol_user($user->id, $course2->id);
899
        $this->getDataGenerator()->enrol_user($user->id, $course3->id);
900
        $this->getDataGenerator()->enrol_user($user->id, $course4->id);
901
 
902
        // Check enrol_get_my_courses basic use (without include hidden provided).
903
        $this->setUser($user);
904
        $courses = enrol_get_my_courses();
905
        $this->assertEquals([$course4->id, $course3->id, $course2->id, $course1->id], array_keys($courses));
906
 
907
        // Hide a course.
908
        set_user_preference('block_myoverview_hidden_course_' . $course3->id, true);
909
 
910
        // Hidden course shouldn't be returned.
911
        $courses = enrol_get_my_courses(null, null, 0, [], false, 0, [$course3->id]);
912
        $this->assertEquals([$course4->id, $course2->id, $course1->id], array_keys($courses));
913
 
914
        // Offset should take into account hidden course.
915
        $courses = enrol_get_my_courses(null, null, 0, [], false, 2, [$course3->id]);
916
        $this->assertEquals([$course1->id], array_keys($courses));
917
    }
918
 
919
    /**
920
     * Tests the enrol_get_my_courses function when using the $allaccessible parameter, which
921
     * includes a wider range of courses (enrolled courses + other accessible ones).
922
     */
11 efrain 923
    public function test_enrol_get_my_courses_all_accessible(): void {
1 efrain 924
        global $DB, $CFG;
925
 
926
        $this->resetAfterTest(true);
927
 
928
        // Create test user and 4 courses, two of which have guest access enabled.
929
        $user = $this->getDataGenerator()->create_user();
930
        $course1 = $this->getDataGenerator()->create_course(
931
                (object)array('shortname' => 'X',
932
                'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
933
                'enrol_guest_password_0' => ''));
934
        $course2 = $this->getDataGenerator()->create_course(
935
                (object)array('shortname' => 'Z',
936
                'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
937
                'enrol_guest_password_0' => ''));
938
        $course3 = $this->getDataGenerator()->create_course(
939
                (object)array('shortname' => 'Y',
940
                'enrol_guest_status_0' => ENROL_INSTANCE_ENABLED,
941
                'enrol_guest_password_0' => 'frog'));
942
        $course4 = $this->getDataGenerator()->create_course(
943
                (object)array('shortname' => 'W',
944
                'enrol_guest_status_0' => ENROL_INSTANCE_DISABLED,
945
                'enrol_guest_password_0' => ''));
946
 
947
        // User is enrolled in first course.
948
        $this->getDataGenerator()->enrol_user($user->id, $course1->id);
949
 
950
        // Check enrol_get_my_courses basic use (without all accessible).
951
        $this->setUser($user);
952
        $courses = enrol_get_my_courses();
953
        $this->assertEquals([$course1->id], array_keys($courses));
954
 
955
        // Turn on all accessible, now they can access the second course too.
956
        $courses = enrol_get_my_courses(null, 'id', 0, [], true);
957
        $this->assertEquals([$course1->id, $course2->id], array_keys($courses));
958
 
959
        // Log in as guest to third course.
960
        load_temp_course_role(context_course::instance($course3->id), $CFG->guestroleid);
961
        $courses = enrol_get_my_courses(null, 'id', 0, [], true);
962
        $this->assertEquals([$course1->id, $course2->id, $course3->id], array_keys($courses));
963
 
964
        // Check fields parameter still works. Fields default (certain base fields).
965
        $this->assertObjectHasProperty('id', $courses[$course3->id]);
966
        $this->assertObjectHasProperty('shortname', $courses[$course3->id]);
967
        $this->assertObjectNotHasProperty('summary', $courses[$course3->id]);
968
 
969
        // Specified fields (one, string).
970
        $courses = enrol_get_my_courses('summary', 'id', 0, [], true);
971
        $this->assertObjectHasProperty('id', $courses[$course3->id]);
972
        $this->assertObjectHasProperty('shortname', $courses[$course3->id]);
973
        $this->assertObjectHasProperty('summary', $courses[$course3->id]);
974
        $this->assertObjectNotHasProperty('summaryformat', $courses[$course3->id]);
975
 
976
        // Specified fields (two, string).
977
        $courses = enrol_get_my_courses('summary, summaryformat', 'id', 0, [], true);
978
        $this->assertObjectHasProperty('summary', $courses[$course3->id]);
979
        $this->assertObjectHasProperty('summaryformat', $courses[$course3->id]);
980
 
981
        // Specified fields (two, array).
982
        $courses = enrol_get_my_courses(['summary', 'summaryformat'], 'id', 0, [], true);
983
        $this->assertObjectHasProperty('summary', $courses[$course3->id]);
984
        $this->assertObjectHasProperty('summaryformat', $courses[$course3->id]);
985
 
986
        // By default, courses are ordered by sortorder - which by default is most recent first.
987
        $courses = enrol_get_my_courses(null, null, 0, [], true);
988
        $this->assertEquals([$course3->id, $course2->id, $course1->id], array_keys($courses));
989
 
990
        // Make sure that implicit sorting defined in navsortmycoursessort is respected.
991
        $CFG->navsortmycoursessort = 'shortname';
992
        $courses = enrol_get_my_courses(null, null, 0, [], true);
993
        $this->assertEquals([$course1->id, $course3->id, $course2->id], array_keys($courses));
994
 
995
        // But still the explicit sorting takes precedence over the implicit one.
996
        $courses = enrol_get_my_courses(null, 'shortname DESC', 0, [], true);
997
        $this->assertEquals([$course2->id, $course3->id, $course1->id], array_keys($courses));
998
 
999
        // Check filter parameter still works.
1000
        $courses = enrol_get_my_courses(null, 'id', 0, [$course2->id, $course3->id, $course4->id], true);
1001
        $this->assertEquals([$course2->id, $course3->id], array_keys($courses));
1002
 
1003
        // Check limit parameter.
1004
        $courses = enrol_get_my_courses(null, 'id', 2, [], true);
1005
        $this->assertEquals([$course1->id, $course2->id], array_keys($courses));
1006
 
1007
        // Now try access for a different user who has manager role at system level.
1008
        $manager = $this->getDataGenerator()->create_user();
1009
        $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
1010
        role_assign($managerroleid, $manager->id, \context_system::instance()->id);
1011
        $this->setUser($manager);
1012
 
1013
        // With default get enrolled, they don't have any courses.
1014
        $courses = enrol_get_my_courses();
1015
        $this->assertCount(0, $courses);
1016
 
1017
        // But with all accessible, they have 4 because they have moodle/course:view everywhere.
1018
        $courses = enrol_get_my_courses(null, 'id', 0, [], true);
1019
        $this->assertEquals([$course1->id, $course2->id, $course3->id, $course4->id],
1020
                array_keys($courses));
1021
 
1022
        // If we prohibit manager from course:view on course 1 though...
1023
        assign_capability('moodle/course:view', CAP_PROHIBIT, $managerroleid,
1024
                \context_course::instance($course1->id));
1025
        $courses = enrol_get_my_courses(null, 'id', 0, [], true);
1026
        $this->assertEquals([$course2->id, $course3->id, $course4->id], array_keys($courses));
1027
 
1028
        // Check for admin user, which has a slightly different query.
1029
        $this->setAdminUser();
1030
        $courses = enrol_get_my_courses(null, 'id', 0, [], true);
1031
        $this->assertEquals([$course1->id, $course2->id, $course3->id, $course4->id], array_keys($courses));
1032
    }
1033
 
1034
    /**
1035
     * Data provider for {@see test_enrol_get_my_courses_by_time}
1036
     *
1037
     * @return array
1038
     */
1441 ariadna 1039
    public static function enrol_get_my_courses_by_time_provider(): array {
1 efrain 1040
        return [
1041
            'No start or end time' =>
1042
                [null, null, true],
1043
            'Start time now, no end time' =>
1044
                [0, null, true],
1045
            'Start time now, end time in the future' =>
1046
                [0, MINSECS, true],
1047
            'Start time in the past, no end time' =>
1048
                [-MINSECS, null, true],
1049
            'Start time in the past, end time in the future' =>
1050
                [-MINSECS, MINSECS, true],
1051
            'Start time in the past, end time in the past' =>
1052
                [-DAYSECS, -HOURSECS, false],
1053
            'Start time in the future' =>
1054
                [MINSECS, null, false],
1055
        ];
1056
    }
1057
 
1058
    /**
1059
     * Test that expected course enrolments are returned when they have timestart / timeend specified
1060
     *
1061
     * @param int|null $timestartoffset Null for 0, otherwise offset from current time
1062
     * @param int|null $timeendoffset Null for 0, otherwise offset from current time
1063
     * @param bool $expectreturn
1064
     *
1065
     * @dataProvider enrol_get_my_courses_by_time_provider
1066
     */
1067
    public function test_enrol_get_my_courses_by_time(?int $timestartoffset, ?int $timeendoffset, bool $expectreturn): void {
1068
        $this->resetAfterTest();
1069
 
1070
        $time = time();
1071
        $timestart = $timestartoffset === null ? 0 : $time + $timestartoffset;
1072
        $timeend = $timeendoffset === null ? 0 : $time + $timeendoffset;
1073
 
1074
        $course = $this->getDataGenerator()->create_course();
1075
        $user = $this->getDataGenerator()->create_and_enrol($course, 'student', null, 'manual', $timestart, $timeend);
1076
        $this->setUser($user);
1077
 
1078
        $courses = enrol_get_my_courses();
1079
        if ($expectreturn) {
1080
            $this->assertCount(1, $courses);
1081
            $this->assertEquals($course->id, reset($courses)->id);
1082
        } else {
1083
            $this->assertEmpty($courses);
1084
        }
1085
    }
1086
 
1087
    /**
1088
     * test_course_users
1089
     *
1090
     * @return void
1091
     */
11 efrain 1092
    public function test_course_users(): void {
1 efrain 1093
        $this->resetAfterTest();
1094
 
1095
        $user1 = $this->getDataGenerator()->create_user();
1096
        $user2 = $this->getDataGenerator()->create_user();
1097
        $course1 = $this->getDataGenerator()->create_course();
1098
        $course2 = $this->getDataGenerator()->create_course();
1099
 
1100
        $this->getDataGenerator()->enrol_user($user1->id, $course1->id);
1101
        $this->getDataGenerator()->enrol_user($user2->id, $course1->id);
1102
        $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
1103
 
1104
        $this->assertCount(2, enrol_get_course_users($course1->id));
1105
        $this->assertCount(2, enrol_get_course_users($course1->id, true));
1106
 
1107
        $this->assertCount(1, enrol_get_course_users($course1->id, true, array($user1->id)));
1108
 
1109
        $this->assertCount(2, enrol_get_course_users(false, false, array($user1->id)));
1110
 
1111
        $instances = enrol_get_instances($course1->id, true);
1112
        $manualinstance = reset($instances);
1113
 
1114
        $manualplugin = enrol_get_plugin('manual');
1115
        $manualplugin->update_user_enrol($manualinstance, $user1->id, ENROL_USER_SUSPENDED);
1116
        $this->assertCount(2, enrol_get_course_users($course1->id, false));
1117
        $this->assertCount(1, enrol_get_course_users($course1->id, true));
1118
    }
1119
 
1120
    /**
1121
     * test_course_users in groups
1122
     *
1123
     * @covers \enrol_get_course_users()
1124
     * @return void
1125
     */
11 efrain 1126
    public function test_course_users_in_groups(): void {
1 efrain 1127
        $this->resetAfterTest();
1128
 
1129
        $user1 = $this->getDataGenerator()->create_user();
1130
        $user2 = $this->getDataGenerator()->create_user();
1131
        $user3 = $this->getDataGenerator()->create_user();
1132
        $course = $this->getDataGenerator()->create_course();
1133
        $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
1134
        $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
1135
 
1136
        $this->getDataGenerator()->enrol_user($user1->id, $course->id);
1137
        $this->getDataGenerator()->enrol_user($user2->id, $course->id);
1138
        $this->getDataGenerator()->enrol_user($user3->id, $course->id);
1139
 
1140
        $this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $user1->id]);
1141
        $this->getDataGenerator()->create_group_member(['groupid' => $group2->id, 'userid' => $user1->id]);
1142
        $this->getDataGenerator()->create_group_member(['groupid' => $group2->id, 'userid' => $user2->id]);
1143
 
1144
        $this->assertCount(3, enrol_get_course_users($course->id));
1145
        $this->assertCount(1, enrol_get_course_users($course->id, false, [], [], [$group1->id]));
1146
        $this->assertCount(2, enrol_get_course_users($course->id, false, [], [], [$group2->id]));
1147
 
1148
        $instances = enrol_get_instances($course->id, true);
1149
        $manualinstance = reset($instances);
1150
 
1151
        $manualplugin = enrol_get_plugin('manual');
1152
        $manualplugin->update_user_enrol($manualinstance, $user1->id, ENROL_USER_SUSPENDED);
1153
        $this->assertCount(2, enrol_get_course_users($course->id, false, [], [], [$group2->id]));
1154
        $this->assertCount(1, enrol_get_course_users($course->id, true, [], [], [$group2->id]));
1155
    }
1156
 
1157
    /**
1158
     * Test count of enrolled users
1159
     *
1160
     * @return void
1161
     */
11 efrain 1162
    public function test_count_enrolled_users(): void {
1 efrain 1163
        global $DB;
1164
 
1165
        $this->resetAfterTest(true);
1166
 
1167
        $course = $this->getDataGenerator()->create_course();
1168
        $context = \context_course::instance($course->id);
1169
 
1170
        $user1 = $this->getDataGenerator()->create_user();
1171
        $user2 = $this->getDataGenerator()->create_user();
1172
 
1173
        $studentrole = $DB->get_record('role', ['shortname' => 'student']);
1174
 
1175
        // Add each user to the manual enrolment instance.
1176
        $manual = enrol_get_plugin('manual');
1177
 
1178
        $manualinstance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual'], '*', MUST_EXIST);
1179
 
1180
        $manual->enrol_user($manualinstance, $user1->id, $studentrole->id);
1181
        $manual->enrol_user($manualinstance, $user2->id, $studentrole->id);
1182
 
1183
        $this->assertEquals(2, count_enrolled_users($context));
1184
 
1185
        // Create a self enrolment instance, enrol first user only.
1186
        $self = enrol_get_plugin('self');
1187
 
1188
        $selfid = $self->add_instance($course,
1189
            ['status' => ENROL_INSTANCE_ENABLED, 'name' => 'Self', 'customint6' => 1, 'roleid' => $studentrole->id]);
1190
        $selfinstance = $DB->get_record('enrol', ['id' => $selfid], '*', MUST_EXIST);
1191
 
1192
        $self->enrol_user($selfinstance, $user1->id, $studentrole->id);
1193
 
1194
        // There are still only two distinct users.
1195
        $this->assertEquals(2, count_enrolled_users($context));
1196
    }
1197
 
1198
    /**
1199
     * Test cases for the test_enrol_get_my_courses_sort_by_last_access test.
1200
     */
1441 ariadna 1201
    public static function get_enrol_get_my_courses_sort_by_last_access_test_cases(): array {
1 efrain 1202
        $now = time();
1203
 
1204
        $enrolledcoursesdata = [
1205
            ['shortname' => 'a', 'lastaccess' => $now - 2],
1206
            ['shortname' => 'b', 'lastaccess' => $now - 1],
1207
            ['shortname' => 'c', 'lastaccess' => $now],
1208
            ['shortname' => 'd', 'lastaccess' => $now - 1],
1209
            ['shortname' => 'e']
1210
        ];
1211
        $unenrolledcoursesdata = [
1212
            ['shortname' => 'x', 'lastaccess' => $now - 2],
1213
            ['shortname' => 'y', 'lastaccess' => $now - 1],
1214
            ['shortname' => 'z', 'lastaccess' => $now]
1215
        ];
1216
 
1217
        return [
1218
            'empty set' => [
1219
                'enrolledcoursesdata' => [],
1220
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1221
                'sort' => 'ul.timeaccess asc',
1222
                'limit' => 0,
1223
                'offset' => 0,
1224
                'expectedcourses' => []
1225
            ],
1226
            'ul.timeaccess asc, shortname asc no limit or offset' => [
1227
                'enrolledcoursesdata' => $enrolledcoursesdata,
1228
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1229
                'sort' => 'ul.timeaccess asc, shortname asc',
1230
                'limit' => 0,
1231
                'offset' => 0,
1232
                'expectedcourses' => ['e', 'a', 'b', 'd', 'c']
1233
            ],
1234
            'ul.timeaccess asc, shortname asc with limit no offset' => [
1235
                'enrolledcoursesdata' => $enrolledcoursesdata,
1236
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1237
                'sort' => 'ul.timeaccess asc, shortname asc',
1238
                'limit' => 2,
1239
                'offset' => 0,
1240
                'expectedcourses' => ['e', 'a']
1241
            ],
1242
            'ul.timeaccess asc, shortname asc with limit and offset' => [
1243
                'enrolledcoursesdata' => $enrolledcoursesdata,
1244
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1245
                'sort' => 'ul.timeaccess asc, shortname asc',
1246
                'limit' => 2,
1247
                'offset' => 2,
1248
                'expectedcourses' => ['b', 'd']
1249
            ],
1250
            'ul.timeaccess asc, shortname asc with limit and offset beyond end of data set' => [
1251
                'enrolledcoursesdata' => $enrolledcoursesdata,
1252
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1253
                'sort' => 'ul.timeaccess asc, shortname asc',
1254
                'limit' => 2,
1255
                'offset' => 4,
1256
                'expectedcourses' => ['c']
1257
            ],
1258
            'ul.timeaccess desc, shortname asc no limit or offset' => [
1259
                'enrolledcoursesdata' => $enrolledcoursesdata,
1260
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1261
                'sort' => 'ul.timeaccess desc, shortname asc',
1262
                'limit' => 0,
1263
                'offset' => 0,
1264
                'expectedcourses' => ['c', 'b', 'd', 'a', 'e']
1265
            ],
1266
            'ul.timeaccess desc, shortname desc, no limit or offset' => [
1267
                'enrolledcoursesdata' => $enrolledcoursesdata,
1268
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1269
                'sort' => 'ul.timeaccess desc, shortname desc',
1270
                'limit' => 0,
1271
                'offset' => 0,
1272
                'expectedcourses' => ['c', 'd', 'b', 'a', 'e']
1273
            ],
1274
            'ul.timeaccess asc, shortname desc, no limit or offset' => [
1275
                'enrolledcoursesdata' => $enrolledcoursesdata,
1276
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1277
                'sort' => 'ul.timeaccess asc, shortname desc',
1278
                'limit' => 0,
1279
                'offset' => 0,
1280
                'expectedcourses' => ['e', 'a', 'd', 'b', 'c']
1281
            ],
1282
            'shortname asc, no limit or offset' => [
1283
                'enrolledcoursesdata' => $enrolledcoursesdata,
1284
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1285
                'sort' => 'shortname asc',
1286
                'limit' => 0,
1287
                'offset' => 0,
1288
                'expectedcourses' => ['a', 'b', 'c', 'd', 'e']
1289
            ],
1290
            'shortname desc, no limit or offset' => [
1291
                'enrolledcoursesdata' => $enrolledcoursesdata,
1292
                'unenrolledcoursesdata' => $unenrolledcoursesdata,
1293
                'sort' => 'shortname desc',
1294
                'limit' => 0,
1295
                'offset' => 0,
1296
                'expectedcourses' => ['e', 'd', 'c', 'b', 'a']
1297
            ],
1298
        ];
1299
    }
1300
 
1301
    /**
1302
     * Test the get_enrolled_courses_by_timeline_classification function.
1303
     *
1441 ariadna 1304
     * @dataProvider get_enrol_get_my_courses_sort_by_last_access_test_cases
1 efrain 1305
     * @param array $enrolledcoursesdata Courses to create and enrol the user in
1306
     * @param array $unenrolledcoursesdata Courses to create nut not enrol the user in
1307
     * @param string $sort Sort string for the enrol function
1308
     * @param int $limit Maximum number of results
1309
     * @param int $offset Offset the courses result set by this amount
1310
     * @param array $expectedcourses Expected courses in result
1311
     */
1312
    public function test_enrol_get_my_courses_sort_by_last_access(
1313
        $enrolledcoursesdata,
1314
        $unenrolledcoursesdata,
1315
        $sort,
1316
        $limit,
1317
        $offset,
1318
        $expectedcourses
11 efrain 1319
    ): void {
1 efrain 1320
        global $DB, $CFG;
1321
 
1322
        $this->resetAfterTest();
1323
        $generator = $this->getDataGenerator();
1324
        $student = $generator->create_user();
1325
        $lastaccessrecords = [];
1326
 
1327
        foreach ($enrolledcoursesdata as $coursedata) {
1328
            $lastaccess = null;
1329
 
1330
            if (isset($coursedata['lastaccess'])) {
1331
                $lastaccess = $coursedata['lastaccess'];
1332
                unset($coursedata['lastaccess']);
1333
            }
1334
 
1335
            $course = $generator->create_course($coursedata);
1336
            $generator->enrol_user($student->id, $course->id, 'student');
1337
 
1338
            if (!is_null($lastaccess)) {
1339
                $lastaccessrecords[] = [
1340
                    'userid' => $student->id,
1341
                    'courseid' => $course->id,
1342
                    'timeaccess' => $lastaccess
1343
                ];
1344
            }
1345
        }
1346
 
1347
        foreach ($unenrolledcoursesdata as $coursedata) {
1348
            $lastaccess = null;
1349
 
1350
            if (isset($coursedata['lastaccess'])) {
1351
                $lastaccess = $coursedata['lastaccess'];
1352
                unset($coursedata['lastaccess']);
1353
            }
1354
 
1355
            $course = $generator->create_course($coursedata);
1356
 
1357
            if (!is_null($lastaccess)) {
1358
                $lastaccessrecords[] = [
1359
                    'userid' => $student->id,
1360
                    'courseid' => $course->id,
1361
                    'timeaccess' => $lastaccess
1362
                ];
1363
            }
1364
        }
1365
 
1366
        if (!empty($lastaccessrecords)) {
1367
            $DB->insert_records('user_lastaccess', $lastaccessrecords);
1368
        }
1369
 
1370
        $this->setUser($student);
1371
 
1372
        $result = enrol_get_my_courses('shortname', $sort, $limit, [], false, $offset);
1373
        $actual = array_map(function($course) {
1374
            return $course->shortname;
1375
        }, array_values($result));
1376
 
1377
        $this->assertEquals($expectedcourses, $actual);
1378
    }
1379
 
1380
    /**
1381
     * Test enrol_get_course_users_roles function.
1382
     *
1383
     * @return void
1384
     */
11 efrain 1385
    public function test_enrol_get_course_users_roles(): void {
1 efrain 1386
        global $DB;
1387
 
1388
        $this->resetAfterTest();
1389
 
1390
        $user1 = $this->getDataGenerator()->create_user();
1391
        $user2 = $this->getDataGenerator()->create_user();
1392
        $course = $this->getDataGenerator()->create_course();
1393
        $context = context_course::instance($course->id);
1394
 
1395
        $roles = array();
1396
        $roles['student'] = $DB->get_field('role', 'id', array('shortname' => 'student'), MUST_EXIST);
1397
        $roles['teacher'] = $DB->get_field('role', 'id', array('shortname' => 'teacher'), MUST_EXIST);
1398
 
1399
        $manual = enrol_get_plugin('manual');
1400
        $this->assertNotEmpty($manual);
1401
 
1402
        $enrol = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual'), '*', MUST_EXIST);
1403
 
1404
        // Test without enrolments.
1405
        $this->assertEmpty(enrol_get_course_users_roles($course->id));
1406
 
1407
        // Test with 1 user, 1 role.
1408
        $manual->enrol_user($enrol, $user1->id, $roles['student']);
1409
        $return = enrol_get_course_users_roles($course->id);
1410
        $this->assertArrayHasKey($user1->id, $return);
1411
        $this->assertArrayHasKey($roles['student'], $return[$user1->id]);
1412
        $this->assertArrayNotHasKey($roles['teacher'], $return[$user1->id]);
1413
 
1414
        // Test with 1 user, 2 role.
1415
        $manual->enrol_user($enrol, $user1->id, $roles['teacher']);
1416
        $return = enrol_get_course_users_roles($course->id);
1417
        $this->assertArrayHasKey($user1->id, $return);
1418
        $this->assertArrayHasKey($roles['student'], $return[$user1->id]);
1419
        $this->assertArrayHasKey($roles['teacher'], $return[$user1->id]);
1420
 
1421
        // Test with another user, 1 role.
1422
        $manual->enrol_user($enrol, $user2->id, $roles['student']);
1423
        $return = enrol_get_course_users_roles($course->id);
1424
        $this->assertArrayHasKey($user1->id, $return);
1425
        $this->assertArrayHasKey($roles['student'], $return[$user1->id]);
1426
        $this->assertArrayHasKey($roles['teacher'], $return[$user1->id]);
1427
        $this->assertArrayHasKey($user2->id, $return);
1428
        $this->assertArrayHasKey($roles['student'], $return[$user2->id]);
1429
        $this->assertArrayNotHasKey($roles['teacher'], $return[$user2->id]);
1430
    }
1431
 
1432
    /**
1433
     * Test enrol_calculate_duration function
1434
     */
11 efrain 1435
    public function test_enrol_calculate_duration(): void {
1 efrain 1436
        // Start time 07/01/2019 @ 12:00am (UTC).
1437
        $timestart = 1561939200;
1438
        // End time 07/05/2019 @ 12:00am (UTC).
1439
        $timeend = 1562284800;
1440
        $duration = enrol_calculate_duration($timestart, $timeend);
1441
        $durationinday = $duration / DAYSECS;
1442
        $this->assertEquals(4, $durationinday);
1443
 
1444
        // End time 07/10/2019 @ 12:00am (UTC).
1445
        $timeend = 1562716800;
1446
        $duration = enrol_calculate_duration($timestart, $timeend);
1447
        $durationinday = $duration / DAYSECS;
1448
        $this->assertEquals(9, $durationinday);
1449
    }
1450
 
1451
    /**
1452
     * Test get_enrolled_with_capabilities_join cannotmatchanyrows attribute.
1453
     *
1441 ariadna 1454
     * @dataProvider get_enrolled_with_capabilities_join_cannotmatchanyrows_data
1 efrain 1455
     * @param string $capability the tested capability
1456
     * @param bool $useprohibit if the capability must be assigned to prohibit
1457
     * @param int $expectedmatch expected cannotmatchanyrows value
1458
     * @param int $expectedcount expceted count value
1459
     */
1460
    public function test_get_enrolled_with_capabilities_join_cannotmatchanyrows(
1461
        string $capability,
1462
        bool $useprohibit,
1463
        int $expectedmatch,
1464
        int $expectedcount
11 efrain 1465
    ): void {
1 efrain 1466
        global $DB, $CFG;
1467
 
1468
        $this->resetAfterTest();
1469
 
1470
        $course = $this->getDataGenerator()->create_course();
1471
        $context = context_course::instance($course->id);
1472
 
1473
        $roleid = $CFG->defaultuserroleid;
1474
 
1475
        // Override capability if necessary.
1476
        if ($useprohibit && $capability) {
1477
            assign_capability($capability, CAP_PROHIBIT, $roleid, $context);
1478
        }
1479
 
1480
        // Check if we must enrol or not.
1481
        $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
1482
 
1483
        $join = get_enrolled_with_capabilities_join($context, '', $capability);
1484
 
1485
        // Execute query.
1486
        $sql = "SELECT COUNT(DISTINCT u.id)
1487
                  FROM {user} u {$join->joins}
1488
                 WHERE {$join->wheres}";
1489
        $countrecords = $DB->count_records_sql($sql, $join->params);
1490
 
1491
        // Validate cannotmatchanyrows.
1492
        $this->assertEquals($expectedmatch, $join->cannotmatchanyrows);
1493
        $this->assertEquals($expectedcount, $countrecords);
1494
    }
1495
 
1496
    /**
1497
     * Data provider for test_get_enrolled_with_capabilities_join_cannotmatchanyrows
1498
     *
1499
     * @return @array of testing scenarios
1500
     */
1441 ariadna 1501
    public static function get_enrolled_with_capabilities_join_cannotmatchanyrows_data(): array {
1 efrain 1502
        return [
1503
            'no prohibits, no capability' => [
1504
                'capability' => '',
1505
                'useprohibit' => false,
1506
                'expectedmatch' => 0,
1507
                'expectedcount' => 1,
1508
            ],
1509
            'no prohibits with capability' => [
1510
                'capability' => 'moodle/course:manageactivities',
1511
                'useprohibit' => false,
1512
                'expectedmatch' => 0,
1513
                'expectedcount' => 1,
1514
            ],
1515
            'prohibits with capability' => [
1516
                'capability' => 'moodle/course:manageactivities',
1517
                'useprohibit' => true,
1518
                'expectedmatch' => 1,
1519
                'expectedcount' => 0,
1520
            ],
1521
        ];
1522
    }
1523
 
1524
    /**
1525
     * Test last_time_enrolments_synced not recorded with "force" option for enrol_check_plugins.
1526
     * @covers ::enrol_check_plugins
1527
     */
11 efrain 1528
    public function test_enrol_check_plugins_with_forced_option(): void {
1 efrain 1529
        $this->resetAfterTest();
1530
        $user = $this->getDataGenerator()->create_user();
1531
 
1532
        $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1533
        enrol_check_plugins($user);
1534
        $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1535
    }
1536
 
1537
    /**
1538
     * Data provided for test_enrol_check_plugins_with_empty_config_value test.
1539
     * @return array
1540
     */
1441 ariadna 1541
    public static function empty_config_data_provider(): array {
1 efrain 1542
        return [
1543
            [0],
1544
            ["0"],
1545
            [false],
1546
            [''],
1547
            ['string'],
1548
        ];
1549
    }
1550
 
1551
    /**
1552
     * Test that empty 'enrolments_sync_interval' is treated as forced option for enrol_check_plugins.
1553
     *
1554
     * @dataProvider empty_config_data_provider
1555
     * @covers ::enrol_check_plugins
1556
     *
1557
     * @param mixed $config Config value.
1558
     */
11 efrain 1559
    public function test_enrol_check_plugins_with_empty_config_value($config): void {
1 efrain 1560
        global $CFG;
1561
 
1562
        $this->resetAfterTest();
1563
        $CFG->enrolments_sync_interval = $config;
1564
        $user = $this->getDataGenerator()->create_user();
1565
 
1566
        $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1567
        enrol_check_plugins($user, false);
1568
        $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1569
    }
1570
 
1571
    /**
1572
     * Test last_time_enrolments_synced is recorded without "force" option for enrol_check_plugins.
1573
     * @covers ::enrol_check_plugins
1574
     */
11 efrain 1575
    public function test_last_time_enrolments_synced_is_set_if_not_forced(): void {
1 efrain 1576
        $this->resetAfterTest();
1577
        $user = $this->getDataGenerator()->create_user();
1578
 
1579
        $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1580
 
1581
        enrol_check_plugins($user, false);
1582
        $firstrun = get_user_preferences('last_time_enrolments_synced', null, $user);
1583
        $this->assertNotNull($firstrun);
1584
        sleep(1);
1585
 
1586
        enrol_check_plugins($user, false);
1587
        $secondrun = get_user_preferences('last_time_enrolments_synced', null, $user);
1588
        $this->assertNotNull($secondrun);
1589
        $this->assertTrue((int)$secondrun == (int)$firstrun);
1590
    }
1591
 
1592
    /**
1593
     * Test last_time_enrolments_synced is recorded correctly without "force" option for enrol_check_plugins.
1594
     * @covers ::enrol_check_plugins
1595
     */
11 efrain 1596
    public function test_last_time_enrolments_synced_is_set_if_not_forced_if_have_not_passed_interval(): void {
1 efrain 1597
        global $CFG;
1598
 
1599
        $this->resetAfterTest();
1600
        $CFG->enrolments_sync_interval = 1;
1601
        $user = $this->getDataGenerator()->create_user();
1602
 
1603
        $this->assertNull(get_user_preferences('last_time_enrolments_synced', null, $user));
1604
 
1605
        enrol_check_plugins($user, false);
1606
        $firstrun = get_user_preferences('last_time_enrolments_synced', null, $user);
1607
        $this->assertNotNull($firstrun);
1608
        sleep(2);
1609
 
1610
        enrol_check_plugins($user, false);
1611
        $secondrun = get_user_preferences('last_time_enrolments_synced', null, $user);
1612
        $this->assertNotNull($secondrun);
1613
        $this->assertTrue((int)$secondrun > (int)$firstrun);
1614
    }
1615
 
1616
    /**
1617
     * Test enrol_selfenrol_available function behavior.
1618
     *
1619
     * @covers ::enrol_selfenrol_available
1620
     */
11 efrain 1621
    public function test_enrol_selfenrol_available(): void {
1 efrain 1622
        global $DB, $CFG;
1623
 
1624
        $this->resetAfterTest();
1625
        $this->preventResetByRollback(); // Messaging does not like transactions...
1626
 
1627
        $selfplugin = enrol_get_plugin('self');
1628
 
1629
        $user1 = $this->getDataGenerator()->create_user();
1630
        $user2 = $this->getDataGenerator()->create_user();
1631
 
1632
        $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST);
1633
        $course = $this->getDataGenerator()->create_course();
1634
        $cohort1 = $this->getDataGenerator()->create_cohort();
1635
        $cohort2 = $this->getDataGenerator()->create_cohort();
1636
 
1637
        // New enrolments are allowed and enrolment instance is enabled.
1638
        $instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'], '*', MUST_EXIST);
1639
        $instance->customint6 = 1;
1640
        $DB->update_record('enrol', $instance);
1641
        $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED);
1642
        $this->setUser($user1);
1643
        $this->assertTrue(enrol_selfenrol_available($course->id));
1644
        $this->setGuestUser();
1645
        $this->assertTrue(enrol_selfenrol_available($course->id));
1646
 
1647
        $canntenrolerror = get_string('canntenrol', 'enrol_self');
1648
 
1649
        // New enrolments are not allowed, but enrolment instance is enabled.
1650
        $instance->customint6 = 0;
1651
        $DB->update_record('enrol', $instance);
1652
        $this->setUser($user1);
1653
        $this->assertFalse(enrol_selfenrol_available($course->id));
1654
        $this->setGuestUser();
1655
        $this->assertFalse(enrol_selfenrol_available($course->id));
1656
 
1657
        // New enrolments are allowed, but enrolment instance is disabled.
1658
        $instance->customint6 = 1;
1659
        $DB->update_record('enrol', $instance);
1660
        $selfplugin->update_status($instance, ENROL_INSTANCE_DISABLED);
1661
        $this->setUser($user1);
1662
        $this->assertFalse(enrol_selfenrol_available($course->id));
1663
        $this->setGuestUser();
1664
        $this->assertFalse(enrol_selfenrol_available($course->id));
1665
 
1666
        // New enrolments are not allowed and enrolment instance is disabled.
1667
        $instance->customint6 = 0;
1668
        $DB->update_record('enrol', $instance);
1669
        $this->setUser($user1);
1670
        $this->assertFalse(enrol_selfenrol_available($course->id));
1671
        $this->setGuestUser();
1672
        $this->assertFalse(enrol_selfenrol_available($course->id));
1673
 
1674
        // Enable enrolment instance for the rest of the tests.
1675
        $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED);
1676
 
1677
        // Enrol start date is in future.
1678
        $instance->customint6 = 1;
1679
        $instance->enrolstartdate = time() + 60;
1680
        $DB->update_record('enrol', $instance);
1681
        $error = get_string('canntenrolearly', 'enrol_self', userdate($instance->enrolstartdate));
1682
        $this->setUser($user1);
1683
        $this->assertFalse(enrol_selfenrol_available($course->id));
1684
        $this->setGuestUser();
1685
        $this->assertFalse(enrol_selfenrol_available($course->id));
1686
 
1687
        // Enrol start date is in past.
1688
        $instance->enrolstartdate = time() - 60;
1689
        $DB->update_record('enrol', $instance);
1690
        $this->setUser($user1);
1691
        $this->assertTrue(enrol_selfenrol_available($course->id));
1692
        $this->setGuestUser();
1693
        $this->assertTrue(enrol_selfenrol_available($course->id));
1694
 
1695
        // Enrol end date is in future.
1696
        $instance->enrolstartdate = 0;
1697
        $instance->enrolenddate = time() + 60;
1698
        $DB->update_record('enrol', $instance);
1699
        $this->setUser($user1);
1700
        $this->assertTrue(enrol_selfenrol_available($course->id));
1701
        $this->setGuestUser();
1702
        $this->assertTrue(enrol_selfenrol_available($course->id));
1703
 
1704
        // Enrol end date is in past.
1705
        $instance->enrolenddate = time() - 60;
1706
        $DB->update_record('enrol', $instance);
1707
        $error = get_string('canntenrollate', 'enrol_self', userdate($instance->enrolenddate));
1708
        $this->setUser($user1);
1709
        $this->assertFalse(enrol_selfenrol_available($course->id));
1710
        $this->setGuestUser();
1711
        $this->assertFalse(enrol_selfenrol_available($course->id));
1712
 
1713
        // Maximum enrolments reached.
1714
        $instance->customint3 = 1;
1715
        $instance->enrolenddate = 0;
1716
        $DB->update_record('enrol', $instance);
1717
        $selfplugin->enrol_user($instance, $user2->id, $studentrole->id);
1718
        $error = get_string('maxenrolledreached', 'enrol_self');
1719
        $this->setUser($user1);
1720
        $this->assertFalse(enrol_selfenrol_available($course->id));
1721
        $this->setGuestUser();
1722
        $this->assertFalse(enrol_selfenrol_available($course->id));
1723
 
1724
        // Maximum enrolments not reached.
1725
        $instance->customint3 = 3;
1726
        $DB->update_record('enrol', $instance);
1727
        $this->setUser($user1);
1728
        $this->assertTrue(enrol_selfenrol_available($course->id));
1729
        $this->setGuestUser();
1730
        $this->assertTrue(enrol_selfenrol_available($course->id));
1731
 
1732
        require_once("$CFG->dirroot/cohort/lib.php");
1733
        cohort_add_member($cohort1->id, $user2->id);
1734
 
1735
        // Cohort test.
1736
        $instance->customint5 = $cohort1->id;
1737
        $DB->update_record('enrol', $instance);
1738
        $error = get_string('cohortnonmemberinfo', 'enrol_self', $cohort1->name);
1739
        $this->setUser($user1);
1740
        $this->assertFalse(enrol_selfenrol_available($course->id));
1741
        $this->setGuestUser();
1742
        $this->assertFalse(enrol_selfenrol_available($course->id));
1743
        $this->setUser($user2);
1744
        $this->assertFalse(enrol_selfenrol_available($course->id));
1745
    }
1746
 
1747
    /**
1748
     * Test the behaviour of validate_enrol_plugin_data().
1749
     *
1441 ariadna 1750
     * @covers \enrol_plugin::validate_enrol_plugin_data
1 efrain 1751
     */
1752
    public function test_validate_enrol_plugin_data(): void {
1753
        $this->resetAfterTest();
1754
 
1755
        // Plugin is disabled in system.
1756
        enrol::enable_plugin('manual', false);
1757
        $manualplugin = enrol_get_plugin('manual');
1758
 
1759
        $enrolmentdata = [];
1760
        $errors = $manualplugin->validate_enrol_plugin_data($enrolmentdata);
1761
        $this->assertArrayHasKey('plugindisabled', $errors);
1762
        $this->assertArrayNotHasKey('errorunsupportedmethod', $errors);
1763
 
1764
        $categoryplugin = enrol_get_plugin('category');
1765
        $errors = $categoryplugin->validate_enrol_plugin_data($enrolmentdata);
1766
        $this->assertArrayHasKey('errorunsupportedmethod', $errors);
1767
    }
1768
 
1769
    /**
1770
     * Test the behaviour of update_enrol_plugin_data().
1771
     *
1441 ariadna 1772
     * @covers \enrol_plugin::update_enrol_plugin_data
1 efrain 1773
     */
1774
    public function test_update_enrol_plugin_data(): void {
1775
        global $DB;
1776
        $this->resetAfterTest();
1777
        $manualplugin = enrol_get_plugin('manual');
1778
 
1779
        $admin = get_admin();
1780
        $this->setUser($admin);
1781
 
1782
        $enrolmentdata = [];
1783
 
1784
        $cat = $this->getDataGenerator()->create_category();
1785
        $course = $this->getDataGenerator()->create_course(['category' => $cat->id, 'shortname' => 'ANON']);
1786
        $instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'manual'], '*', MUST_EXIST);
1787
 
1788
        $teacherroleid = $DB->get_field('role', 'id', ['shortname' => 'teacher']);
1789
        $editingteacherroleid = $DB->get_field('role', 'id', ['shortname' => 'editingteacher']);
1790
 
1791
        $enrolmentdata['startdate'] = '3 Feb 2024';
1792
        $enrolmentdata['enddate'] = '4 Feb 2024';
1793
        $enrolmentdata['role'] = 'teacher';
1794
        $enrolmentdata['name'] = 'testinstance';
1795
 
1796
        $expectedinstance = $instance;
1797
        $expectedinstance->enrolstartdate = strtotime($enrolmentdata['startdate']);
1798
        $expectedinstance->enrolenddate = strtotime($enrolmentdata['enddate']);
1799
        $expectedinstance->role = $teacherroleid;
1800
        $expectedinstance->name = $enrolmentdata['name'];
1801
        $expectedinstance->enrolperiod = $expectedinstance->enrolenddate - $expectedinstance->enrolstartdate;
1802
        $modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance);
1803
        $this->assertEquals($expectedinstance, $modifiedinstance);
1804
 
1805
        $enrolmentdata['roleid'] = $editingteacherroleid;
1806
        unset($enrolmentdata['startdate']);
1807
        unset($enrolmentdata['enddate']);
1808
        unset($enrolmentdata['role']);
1809
        $enrolmentdata['enrolperiod'] = $modifiedinstance->enrolperiod++;
1810
        $expectedinstance->roleid = $editingteacherroleid;
1811
        $expectedinstance->enrolstartdate = 0;
1812
        $expectedinstance->enrolenddate = 0;
1813
        $expectedinstance->enrolperiod++;
1814
        $modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance);
1815
        $this->assertEquals($expectedinstance, $modifiedinstance);
1816
 
1817
        $enrolmentdata['startdate'] = '3 Feb 2024';
1818
        $enrolmentdata['enrolperiod'] = 3600;
1819
        $expectedinstance->enrolstartdate = strtotime($enrolmentdata['startdate']);
1820
        $expectedinstance->enrolperiod = $enrolmentdata['enrolperiod'];
1821
        $expectedinstance->enrolenddate = $expectedinstance->enrolstartdate + $enrolmentdata['enrolperiod'];
1822
        $modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance);
1823
        $this->assertEquals($expectedinstance, $modifiedinstance);
1824
 
1825
        $enrolmentdata['enddate'] = '5 Feb 2024';
1826
        unset($enrolmentdata['enrolperiod']);
1827
        $expectedinstance->enrolenddate = strtotime($enrolmentdata['startdate']);
1828
        $expectedinstance->enrolperiod = $expectedinstance->enrolenddate - $expectedinstance->enrolstartdate;
1829
        $modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance);
1830
        $this->assertEquals($expectedinstance, $modifiedinstance);
1831
 
1832
        $enrolmentdata['enrolperiod'] = '2hours';
1833
        $expectedinstance->enrolperiod = 7200;
1834
        $expectedinstance->enrolenddate = $expectedinstance->enrolstartdate + $expectedinstance->enrolperiod;
1835
        $modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance);
1836
        $this->assertEquals($expectedinstance, $modifiedinstance);
1837
    }
1441 ariadna 1838
 
1839
    /**
1840
     * Test case for checking the email greetings in various user notification emails.
1841
     *
1842
     * @covers \enrol_plugin::send_course_welcome_message_to_user
1843
     */
1844
    public function test_email_greetings(): void {
1845
        global $DB;
1846
        $this->resetAfterTest();
1847
 
1848
        // Create course.
1849
        $course = $this->getDataGenerator()->create_course([
1850
            'fullname' => 'Course 1',
1851
            'shortname' => 'C1',
1852
        ]);
1853
        // Create user.
1854
        $student = $this->getDataGenerator()->create_user();
1855
        // Get manual plugin.
1856
        $manualplugin = enrol_get_plugin('manual');
1857
        $maninstance = $DB->get_record(
1858
            'enrol',
1859
            ['courseid' => $course->id, 'enrol' => 'manual'],
1860
            '*',
1861
            MUST_EXIST,
1862
        );
1863
 
1864
        $messagesink = $this->redirectMessages();
1865
        $manualplugin->send_course_welcome_message_to_user(
1866
            instance: $maninstance,
1867
            userid: $student->id,
1868
            sendoption: ENROL_SEND_EMAIL_FROM_NOREPLY,
1869
            message: '',
1870
        );
1871
        $messages = $messagesink->get_messages_by_component_and_type(
1872
            'moodle',
1873
            'enrolcoursewelcomemessage',
1874
        );
1875
        $this->assertNotEmpty($messages);
1876
        $message = reset($messages);
1877
        $this->assertStringContainsString('Hi ' . $student->firstname, quoted_printable_decode($message->fullmessage));
1878
    }
1 efrain 1879
}