Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace enrol_self;
18
 
19
use context_course;
20
use enrol_self_plugin;
21
 
22
defined('MOODLE_INTERNAL') || die();
23
 
24
global $CFG;
25
require_once($CFG->dirroot.'/enrol/self/lib.php');
26
require_once($CFG->dirroot.'/enrol/self/locallib.php');
27
 
28
/**
29
 * Self enrolment plugin tests.
30
 *
31
 * @package    enrol_self
32
 * @category   phpunit
33
 * @copyright  2012 Petr Skoda {@link http://skodak.org}
34
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35
 * @coversDefaultClass \enrol_self_plugin
36
 */
37
class self_test extends \advanced_testcase {
38
 
39
    public function test_basics() {
40
        $this->assertTrue(enrol_is_enabled('self'));
41
        $plugin = enrol_get_plugin('self');
42
        $this->assertInstanceOf('enrol_self_plugin', $plugin);
43
        $this->assertEquals(1, get_config('enrol_self', 'defaultenrol'));
44
        $this->assertEquals(ENROL_EXT_REMOVED_KEEP, get_config('enrol_self', 'expiredaction'));
45
    }
46
 
47
    public function test_sync_nothing() {
48
        global $SITE;
49
 
50
        $selfplugin = enrol_get_plugin('self');
51
 
52
        $trace = new \null_progress_trace();
53
 
54
        // Just make sure the sync does not throw any errors when nothing to do.
55
        $selfplugin->sync($trace, null);
56
        $selfplugin->sync($trace, $SITE->id);
57
    }
58
 
59
    public function test_longtimnosee() {
60
        global $DB;
61
        $this->resetAfterTest();
62
 
63
        $selfplugin = enrol_get_plugin('self');
64
        $manualplugin = enrol_get_plugin('manual');
65
        $this->assertNotEmpty($manualplugin);
66
 
67
        $now = time();
68
 
69
        $trace = new \progress_trace_buffer(new \text_progress_trace(), false);
70
 
71
        // Prepare some data.
72
 
73
        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
74
        $this->assertNotEmpty($studentrole);
75
        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
76
        $this->assertNotEmpty($teacherrole);
77
 
78
        $record = array('firstaccess'=>$now-60*60*24*800);
79
        $record['lastaccess'] = $now-60*60*24*100;
80
        $user1 = $this->getDataGenerator()->create_user($record);
81
        $record['lastaccess'] = $now-60*60*24*10;
82
        $user2 = $this->getDataGenerator()->create_user($record);
83
        $record['lastaccess'] = $now-60*60*24*1;
84
        $user3 = $this->getDataGenerator()->create_user($record);
85
        $record['lastaccess'] = $now-10;
86
        $user4 = $this->getDataGenerator()->create_user($record);
87
 
88
        $course1 = $this->getDataGenerator()->create_course();
89
        $course2 = $this->getDataGenerator()->create_course();
90
        $course3 = $this->getDataGenerator()->create_course();
91
        $context1 = \context_course::instance($course1->id);
92
        $context2 = \context_course::instance($course2->id);
93
        $context3 = \context_course::instance($course3->id);
94
 
95
        $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'self')));
96
        $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
97
        $instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
98
        $instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
99
        $id = $selfplugin->add_instance($course3, array('status'=>ENROL_INSTANCE_ENABLED, 'roleid'=>$teacherrole->id));
100
        $instance3b = $DB->get_record('enrol', array('id'=>$id), '*', MUST_EXIST);
101
        unset($id);
102
 
103
        $this->assertEquals($studentrole->id, $instance1->roleid);
104
        $instance1->customint2 = 60*60*24*14;
105
        $DB->update_record('enrol', $instance1);
106
        $selfplugin->enrol_user($instance1, $user1->id, $studentrole->id);
107
        $selfplugin->enrol_user($instance1, $user2->id, $studentrole->id);
108
        $selfplugin->enrol_user($instance1, $user3->id, $studentrole->id);
109
        $this->assertEquals(3, $DB->count_records('user_enrolments'));
110
        $DB->insert_record('user_lastaccess', array('userid'=>$user2->id, 'courseid'=>$course1->id, 'timeaccess'=>$now-60*60*24*20));
111
        $DB->insert_record('user_lastaccess', array('userid'=>$user3->id, 'courseid'=>$course1->id, 'timeaccess'=>$now-60*60*24*2));
112
        $DB->insert_record('user_lastaccess', array('userid'=>$user4->id, 'courseid'=>$course1->id, 'timeaccess'=>$now-60));
113
 
114
        $this->assertEquals($studentrole->id, $instance3->roleid);
115
        $instance3->customint2 = 60*60*24*50;
116
        $DB->update_record('enrol', $instance3);
117
        $selfplugin->enrol_user($instance3, $user1->id, $studentrole->id);
118
        $selfplugin->enrol_user($instance3, $user2->id, $studentrole->id);
119
        $selfplugin->enrol_user($instance3, $user3->id, $studentrole->id);
120
        $selfplugin->enrol_user($instance3b, $user1->id, $teacherrole->id);
121
        $selfplugin->enrol_user($instance3b, $user4->id, $teacherrole->id);
122
        $this->assertEquals(8, $DB->count_records('user_enrolments'));
123
        $DB->insert_record('user_lastaccess', array('userid'=>$user2->id, 'courseid'=>$course3->id, 'timeaccess'=>$now-60*60*24*11));
124
        $DB->insert_record('user_lastaccess', array('userid'=>$user3->id, 'courseid'=>$course3->id, 'timeaccess'=>$now-60*60*24*200));
125
        $DB->insert_record('user_lastaccess', array('userid'=>$user4->id, 'courseid'=>$course3->id, 'timeaccess'=>$now-60*60*24*200));
126
 
127
        $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
128
        $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
129
 
130
        $manualplugin->enrol_user($maninstance2, $user1->id, $studentrole->id);
131
        $manualplugin->enrol_user($maninstance3, $user1->id, $teacherrole->id);
132
 
133
        $this->assertEquals(10, $DB->count_records('user_enrolments'));
134
        $this->assertEquals(9, $DB->count_records('role_assignments'));
135
        $this->assertEquals(7, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
136
        $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
137
 
138
        // Execute sync - this is the same thing used from cron.
139
 
140
        $selfplugin->sync($trace, $course2->id);
141
        $output = $trace->get_buffer();
142
        $trace->reset_buffer();
143
        $this->assertEquals(10, $DB->count_records('user_enrolments'));
144
        $this->assertStringContainsString('No expired enrol_self enrolments detected', $output);
145
        $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user1->id)));
146
        $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user2->id)));
147
        $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user1->id)));
148
        $this->assertTrue($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user3->id)));
149
 
150
        $selfplugin->sync($trace, null);
151
        $output = $trace->get_buffer();
152
        $trace->reset_buffer();
153
        $this->assertEquals(6, $DB->count_records('user_enrolments'));
154
        $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user1->id)));
155
        $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user2->id)));
156
        $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user1->id)));
157
        $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user3->id)));
158
        $this->assertStringContainsString('unenrolling user ' . $user1->id . ' from course ' . $course1->id .
159
            ' as they did not log in for at least 14 days', $output);
160
        $this->assertStringContainsString('unenrolling user ' . $user1->id . ' from course ' . $course3->id .
161
            ' as they did not log in for at least 50 days', $output);
162
        $this->assertStringContainsString('unenrolling user ' . $user2->id . ' from course ' . $course1->id .
163
            ' as they did not access the course for at least 14 days', $output);
164
        $this->assertStringContainsString('unenrolling user ' . $user3->id . ' from course ' . $course3->id .
165
            ' as they did not access the course for at least 50 days', $output);
166
        $this->assertStringNotContainsString('unenrolling user ' . $user4->id, $output);
167
 
168
        $this->assertEquals(6, $DB->count_records('role_assignments'));
169
        $this->assertEquals(4, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
170
        $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
171
    }
172
 
173
    /**
174
     * Data provider for longtimenosee notifications tests.
175
     *
176
     * @return array
177
     */
178
    public static function longtimenosee_notifications_provider(): array {
179
 
180
        return [
181
            'No inactive period' => [
182
                'expirynotify' => 1,
183
                'notifyall' => 1,
184
                'expirythreshold' => DAYSECS * 3,
185
                'customint2' => 0,
186
                'numnotifications' => 2,
187
                'progresstrace' => true,
188
            ],
189
            'Notifications disabled' => [
190
                'expirynotify' => 0,
191
                'notifyall' => 1,
192
                'expirythreshold' => DAYSECS * 3,
193
                'customint2' => WEEKSECS,
194
                'numnotifications' => 0,
195
                'progresstrace' => true,
196
            ],
197
            'Notifications enabled' => [
198
                'expirynotify' => 1,
199
                'notifyall' => 1,
200
                'expirythreshold' => DAYSECS * 3,
201
                'customint2' => WEEKSECS,
202
                'numnotifications' => 4,
203
                'progresstrace' => false,
204
            ],
205
        ];
206
    }
207
 
208
    /**
209
     * Tests for the inactivity unerol notification.
210
     *
211
     * Having enrolment duration (timeend) set to 0, the notifications about enrol expiration are not sent
212
     *
213
     * @dataProvider longtimenosee_notifications_provider
214
     * @covers ::send_expiry_notifications
215
     * @param   int         $expirynotify       Whether enrolment expiry notification messages are sent
216
     * @param   int         $notifyall          Whether teachers and students are notified or only teachers
217
     * @param   int         $expirythreshold    How long before expiry are users notified (seconds)
218
     * @param   int         $customint2         Time of inactivity before unerolling a user (seconds)
219
     * @param   int         $numnotifications   Expected number of notifications sent
220
     * @param   bool        $progresstrace      Progress tracing object
221
     * @return void
222
     */
223
    public function test_longtimenosee_notifications(
224
        int $expirynotify,
225
        int $notifyall,
226
        int $expirythreshold,
227
        int $customint2,
228
        int $numnotifications,
229
        bool $progresstrace,
230
    ): void {
231
        global $DB;
232
        $this->resetAfterTest();
233
        $this->preventResetByRollback(); // Messaging does not like transactions...
234
 
235
        $selfplugin = enrol_get_plugin('self');
236
 
237
        $now = time();
238
        $coursestartdate = $now - WEEKSECS * 4;
239
 
240
        $trace = new \null_progress_trace();
241
 
242
        // Note: hopefully nobody executes the unit tests the last second before midnight...
243
        $selfplugin->set_config('expirynotifylast', $now - DAYSECS);
244
        $selfplugin->set_config('expirynotifyhour', 0);
245
 
246
        $studentrole = $DB->get_record('role', ['shortname' => 'student']);
247
        $this->assertNotEmpty($studentrole);
248
        $editingteacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
249
        $this->assertNotEmpty($editingteacherrole);
250
        $managerrole = $DB->get_record('role', ['shortname' => 'manager']);
251
        $this->assertNotEmpty($managerrole);
252
 
253
        $user1 = $this->getDataGenerator()->create_user(['lastname' => 'xuser1']);
254
        $user2 = $this->getDataGenerator()->create_user(['lastname' => 'xuser2']);
255
        $user3 = $this->getDataGenerator()->create_user(['lastname' => 'xuser3']);
256
        $user4 = $this->getDataGenerator()->create_user(['lastname' => 'xuser4']);
257
 
258
        $course1 = $this->getDataGenerator()->create_course(['fullname' => 'xcourse1', 'startdate' => $coursestartdate]);
259
 
260
        $instance1 = $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'self'], '*', MUST_EXIST);
261
        $instance1->expirythreshold = $expirythreshold;
262
        $instance1->expirynotify    = $expirynotify;
263
        $instance1->notifyall       = $notifyall;
264
        $instance1->status          = ENROL_INSTANCE_ENABLED;
265
        $instance1->customint2      = $customint2;
266
        $DB->update_record('enrol', $instance1);
267
 
268
        // Suspended users are not notified.
269
        $selfplugin->enrol_user($instance1, $user1->id, $studentrole->id, $coursestartdate, 0, ENROL_USER_SUSPENDED);
270
        // User accessed recently - should not be notified.
271
        $selfplugin->enrol_user($instance1, $user2->id, $studentrole->id, $coursestartdate, 0);
272
        $DB->insert_record('user_lastaccess', ['userid' => $user2->id, 'courseid' => $course1->id, 'timeaccess' => $now -
273
            DAYSECS * 3]);
274
        // User accessed long time ago - should be notified.
275
        $selfplugin->enrol_user($instance1, $user3->id, $studentrole->id, $coursestartdate, $now + DAYSECS * 2 + HOURSECS);
276
        $DB->insert_record('user_lastaccess', ['userid' => $user3->id, 'courseid' => $course1->id, 'timeaccess' => $now
277
            - DAYSECS * 20]);
278
        // User has never accessed the course - should be notified.
279
        $selfplugin->enrol_user($instance1, $user4->id, $studentrole->id, $coursestartdate, 0);
280
 
281
        $sink = $this->redirectMessages();
282
        if ($progresstrace) {
283
            $selfplugin->send_expiry_notifications($trace);
284
        } else {
285
            // If $trace is not an instance of the progress_trace, then set it to false to test whether debugging is triggered.
286
            $selfplugin->send_expiry_notifications(false);
287
            $this->assertDebuggingCalled(
288
                'enrol_plugin::send_expiry_notifications() now expects progress_trace instance as parameter!'
289
            );
290
        }
291
        $messages = $sink->get_messages();
292
 
293
        $this->assertCount($numnotifications, $messages);
294
        if ($numnotifications && ($customint2 > 0)) {
295
            $this->assertEquals($user3->id, $messages[0]->useridto);
296
            $this->assertStringContainsString('you have not accessed', $messages[0]->fullmessagehtml);
297
        }
298
 
299
        // Make sure that notifications are not repeated.
300
        $sink->clear();
301
 
302
        // Test that no more messages are sent the same day.
303
        $selfplugin->send_expiry_notifications($trace);
304
        $messages = $sink->get_messages();
305
 
306
        $this->assertCount(0, $messages);
307
 
308
        // Test if an enrolment instance is disabled.
309
        $selfplugin->update_status($instance1, ENROL_INSTANCE_DISABLED);
310
        $this->assertNull($selfplugin->send_expiry_notifications($trace));
311
        $selfplugin->update_status($instance1, ENROL_INSTANCE_ENABLED);
312
 
313
        // Test if an expiry notify hour is null.
314
        $selfplugin->set_config('expirynotifyhour', null);
315
        $selfplugin->send_expiry_notifications($trace);
316
        $this->assertDebuggingCalled('send_expiry_notifications() in self enrolment plugin needs expirynotifyhour setting');
317
    }
318
 
319
    public function test_expired() {
320
        global $DB;
321
        $this->resetAfterTest();
322
 
323
        $selfplugin = enrol_get_plugin('self');
324
        $manualplugin = enrol_get_plugin('manual');
325
        $this->assertNotEmpty($manualplugin);
326
 
327
        $now = time();
328
 
329
        $trace = new \null_progress_trace();
330
 
331
        // Prepare some data.
332
 
333
        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
334
        $this->assertNotEmpty($studentrole);
335
        $teacherrole = $DB->get_record('role', array('shortname'=>'teacher'));
336
        $this->assertNotEmpty($teacherrole);
337
        $managerrole = $DB->get_record('role', array('shortname'=>'manager'));
338
        $this->assertNotEmpty($managerrole);
339
 
340
        $user1 = $this->getDataGenerator()->create_user();
341
        $user2 = $this->getDataGenerator()->create_user();
342
        $user3 = $this->getDataGenerator()->create_user();
343
        $user4 = $this->getDataGenerator()->create_user();
344
 
345
        $course1 = $this->getDataGenerator()->create_course();
346
        $course2 = $this->getDataGenerator()->create_course();
347
        $course3 = $this->getDataGenerator()->create_course();
348
        $context1 = \context_course::instance($course1->id);
349
        $context2 = \context_course::instance($course2->id);
350
        $context3 = \context_course::instance($course3->id);
351
 
352
        $this->assertEquals(3, $DB->count_records('enrol', array('enrol'=>'self')));
353
        $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
354
        $this->assertEquals($studentrole->id, $instance1->roleid);
355
        $instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
356
        $this->assertEquals($studentrole->id, $instance2->roleid);
357
        $instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
358
        $this->assertEquals($studentrole->id, $instance3->roleid);
359
        $id = $selfplugin->add_instance($course3, array('status'=>ENROL_INSTANCE_ENABLED, 'roleid'=>$teacherrole->id));
360
        $instance3b = $DB->get_record('enrol', array('id'=>$id), '*', MUST_EXIST);
361
        $this->assertEquals($teacherrole->id, $instance3b->roleid);
362
        unset($id);
363
 
364
        $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
365
        $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
366
 
367
        $manualplugin->enrol_user($maninstance2, $user1->id, $studentrole->id);
368
        $manualplugin->enrol_user($maninstance3, $user1->id, $teacherrole->id);
369
 
370
        $this->assertEquals(2, $DB->count_records('user_enrolments'));
371
        $this->assertEquals(2, $DB->count_records('role_assignments'));
372
        $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
373
        $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
374
 
375
        $selfplugin->enrol_user($instance1, $user1->id, $studentrole->id);
376
        $selfplugin->enrol_user($instance1, $user2->id, $studentrole->id);
377
        $selfplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now-60);
378
 
379
        $selfplugin->enrol_user($instance3, $user1->id, $studentrole->id, 0, 0);
380
        $selfplugin->enrol_user($instance3, $user2->id, $studentrole->id, 0, $now-60*60);
381
        $selfplugin->enrol_user($instance3, $user3->id, $studentrole->id, 0, $now+60*60);
382
        $selfplugin->enrol_user($instance3b, $user1->id, $teacherrole->id, $now-60*60*24*7, $now-60);
383
        $selfplugin->enrol_user($instance3b, $user4->id, $teacherrole->id);
384
 
385
        role_assign($managerrole->id, $user3->id, $context1->id);
386
 
387
        $this->assertEquals(10, $DB->count_records('user_enrolments'));
388
        $this->assertEquals(10, $DB->count_records('role_assignments'));
389
        $this->assertEquals(7, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
390
        $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
391
 
392
        // Execute tests.
393
 
394
        $this->assertEquals(ENROL_EXT_REMOVED_KEEP, $selfplugin->get_config('expiredaction'));
395
        $selfplugin->sync($trace, null);
396
        $this->assertEquals(10, $DB->count_records('user_enrolments'));
397
        $this->assertEquals(10, $DB->count_records('role_assignments'));
398
 
399
 
400
        $selfplugin->set_config('expiredaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);
401
        $selfplugin->sync($trace, $course2->id);
402
        $this->assertEquals(10, $DB->count_records('user_enrolments'));
403
        $this->assertEquals(10, $DB->count_records('role_assignments'));
404
 
405
        $selfplugin->sync($trace, null);
406
        $this->assertEquals(10, $DB->count_records('user_enrolments'));
407
        $this->assertEquals(7, $DB->count_records('role_assignments'));
408
        $this->assertEquals(5, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
409
        $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
410
        $this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context1->id, 'userid'=>$user3->id, 'roleid'=>$studentrole->id)));
411
        $this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user2->id, 'roleid'=>$studentrole->id)));
412
        $this->assertFalse($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user1->id, 'roleid'=>$teacherrole->id)));
413
        $this->assertTrue($DB->record_exists('role_assignments', array('contextid'=>$context3->id, 'userid'=>$user1->id, 'roleid'=>$studentrole->id)));
414
 
415
 
416
        $selfplugin->set_config('expiredaction', ENROL_EXT_REMOVED_UNENROL);
417
 
418
        role_assign($studentrole->id, $user3->id, $context1->id);
419
        role_assign($studentrole->id, $user2->id, $context3->id);
420
        role_assign($teacherrole->id, $user1->id, $context3->id);
421
        $this->assertEquals(10, $DB->count_records('user_enrolments'));
422
        $this->assertEquals(10, $DB->count_records('role_assignments'));
423
        $this->assertEquals(7, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
424
        $this->assertEquals(2, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
425
 
426
        $selfplugin->sync($trace, null);
427
        $this->assertEquals(7, $DB->count_records('user_enrolments'));
428
        $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance1->id, 'userid'=>$user3->id)));
429
        $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3->id, 'userid'=>$user2->id)));
430
        $this->assertFalse($DB->record_exists('user_enrolments', array('enrolid'=>$instance3b->id, 'userid'=>$user1->id)));
431
        $this->assertEquals(6, $DB->count_records('role_assignments'));
432
        $this->assertEquals(5, $DB->count_records('role_assignments', array('roleid'=>$studentrole->id)));
433
        $this->assertEquals(1, $DB->count_records('role_assignments', array('roleid'=>$teacherrole->id)));
434
    }
435
 
436
    public function test_send_expiry_notifications() {
437
        global $DB, $CFG;
438
        $this->resetAfterTest();
439
        $this->preventResetByRollback(); // Messaging does not like transactions...
440
 
441
        /** @var $selfplugin enrol_self_plugin */
442
        $selfplugin = enrol_get_plugin('self');
443
        /** @var $manualplugin enrol_manual_plugin */
444
        $manualplugin = enrol_get_plugin('manual');
445
        $now = time();
446
        $admin = get_admin();
447
 
448
        $trace = new \null_progress_trace();
449
 
450
        // Note: hopefully nobody executes the unit tests the last second before midnight...
451
 
452
        $selfplugin->set_config('expirynotifylast', $now - 60*60*24);
453
        $selfplugin->set_config('expirynotifyhour', 0);
454
 
455
        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
456
        $this->assertNotEmpty($studentrole);
457
        $editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
458
        $this->assertNotEmpty($editingteacherrole);
459
        $managerrole = $DB->get_record('role', array('shortname'=>'manager'));
460
        $this->assertNotEmpty($managerrole);
461
 
462
        $user1 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser1'));
463
        $user2 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser2'));
464
        $user3 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser3'));
465
        $user4 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser4'));
466
        $user5 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser5'));
467
        $user6 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
468
        $user7 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
469
        $user8 = $this->getDataGenerator()->create_user(array('lastname'=>'xuser6'));
470
 
471
        $course1 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse1'));
472
        $course2 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse2'));
473
        $course3 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse3'));
474
        $course4 = $this->getDataGenerator()->create_course(array('fullname'=>'xcourse4'));
475
 
476
        $this->assertEquals(4, $DB->count_records('enrol', array('enrol'=>'manual')));
477
        $this->assertEquals(4, $DB->count_records('enrol', array('enrol'=>'self')));
478
 
479
        $maninstance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'manual'), '*', MUST_EXIST);
480
        $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
481
        $instance1->expirythreshold = 60*60*24*4;
482
        $instance1->expirynotify    = 1;
483
        $instance1->notifyall       = 1;
484
        $instance1->status          = ENROL_INSTANCE_ENABLED;
485
        $DB->update_record('enrol', $instance1);
486
 
487
        $maninstance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'manual'), '*', MUST_EXIST);
488
        $instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
489
        $instance2->expirythreshold = 60*60*24*1;
490
        $instance2->expirynotify    = 1;
491
        $instance2->notifyall       = 1;
492
        $instance2->status          = ENROL_INSTANCE_ENABLED;
493
        $DB->update_record('enrol', $instance2);
494
 
495
        $maninstance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'manual'), '*', MUST_EXIST);
496
        $instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
497
        $instance3->expirythreshold = 60*60*24*1;
498
        $instance3->expirynotify    = 1;
499
        $instance3->notifyall       = 0;
500
        $instance3->status          = ENROL_INSTANCE_ENABLED;
501
        $DB->update_record('enrol', $instance3);
502
 
503
        $maninstance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'manual'), '*', MUST_EXIST);
504
        $instance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'self'), '*', MUST_EXIST);
505
        $instance4->expirythreshold = 60*60*24*1;
506
        $instance4->expirynotify    = 0;
507
        $instance4->notifyall       = 0;
508
        $instance4->status          = ENROL_INSTANCE_ENABLED;
509
        $DB->update_record('enrol', $instance4);
510
 
511
        $selfplugin->enrol_user($instance1, $user1->id, $studentrole->id, 0, $now + 60*60*24*1, ENROL_USER_SUSPENDED); // Suspended users are not notified.
512
        $selfplugin->enrol_user($instance1, $user2->id, $studentrole->id, 0, $now + 60*60*24*5);                       // Above threshold are not notified.
513
        $selfplugin->enrol_user($instance1, $user3->id, $studentrole->id, 0, $now + 60*60*24*3 + 60*60);               // Less than one day after threshold - should be notified.
514
        $selfplugin->enrol_user($instance1, $user4->id, $studentrole->id, 0, $now + 60*60*24*4 - 60*3);                // Less than one day after threshold - should be notified.
515
        $selfplugin->enrol_user($instance1, $user5->id, $studentrole->id, 0, $now + 60*60);                            // Should have been already notified.
516
        $selfplugin->enrol_user($instance1, $user6->id, $studentrole->id, 0, $now - 60);                               // Already expired.
517
        $manualplugin->enrol_user($maninstance1, $user7->id, $editingteacherrole->id);
518
        $manualplugin->enrol_user($maninstance1, $user8->id, $managerrole->id);                                        // Highest role --> enroller.
519
 
520
        $selfplugin->enrol_user($instance2, $user1->id, $studentrole->id);
521
        $selfplugin->enrol_user($instance2, $user2->id, $studentrole->id, 0, $now + 60*60*24*1 + 60*3);                // Above threshold are not notified.
522
        $selfplugin->enrol_user($instance2, $user3->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60);               // Less than one day after threshold - should be notified.
523
 
524
        $manualplugin->enrol_user($maninstance3, $user1->id, $editingteacherrole->id);
525
        $selfplugin->enrol_user($instance3, $user2->id, $studentrole->id, 0, $now + 60*60*24*1 + 60);                  // Above threshold are not notified.
526
        $selfplugin->enrol_user($instance3, $user3->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60);               // Less than one day after threshold - should be notified.
527
 
528
        $manualplugin->enrol_user($maninstance4, $user4->id, $editingteacherrole->id);
529
        $selfplugin->enrol_user($instance4, $user5->id, $studentrole->id, 0, $now + 60*60*24*1 + 60);
530
        $selfplugin->enrol_user($instance4, $user6->id, $studentrole->id, 0, $now + 60*60*24*1 - 60*60);
531
 
532
        // The notification is sent out in fixed order first individual users,
533
        // then summary per course by enrolid, user lastname, etc.
534
        $this->assertGreaterThan($instance1->id, $instance2->id);
535
        $this->assertGreaterThan($instance2->id, $instance3->id);
536
 
537
        $sink = $this->redirectMessages();
538
 
539
        $selfplugin->send_expiry_notifications($trace);
540
 
541
        $messages = $sink->get_messages();
542
 
543
        $this->assertEquals(2+1 + 1+1 + 1 + 0, count($messages));
544
 
545
        // First individual notifications from course1.
546
        $this->assertEquals($user3->id, $messages[0]->useridto);
547
        $this->assertEquals($user8->id, $messages[0]->useridfrom);
548
        $this->assertStringContainsString('xcourse1', $messages[0]->fullmessagehtml);
549
 
550
        $this->assertEquals($user4->id, $messages[1]->useridto);
551
        $this->assertEquals($user8->id, $messages[1]->useridfrom);
552
        $this->assertStringContainsString('xcourse1', $messages[1]->fullmessagehtml);
553
 
554
        // Then summary for course1.
555
        $this->assertEquals($user8->id, $messages[2]->useridto);
556
        $this->assertEquals($admin->id, $messages[2]->useridfrom);
557
        $this->assertStringContainsString('xcourse1', $messages[2]->fullmessagehtml);
558
        $this->assertStringNotContainsString('xuser1', $messages[2]->fullmessagehtml);
559
        $this->assertStringNotContainsString('xuser2', $messages[2]->fullmessagehtml);
560
        $this->assertStringContainsString('xuser3', $messages[2]->fullmessagehtml);
561
        $this->assertStringContainsString('xuser4', $messages[2]->fullmessagehtml);
562
        $this->assertStringContainsString('xuser5', $messages[2]->fullmessagehtml);
563
        $this->assertStringNotContainsString('xuser6', $messages[2]->fullmessagehtml);
564
 
565
        // First individual notifications from course2.
566
        $this->assertEquals($user3->id, $messages[3]->useridto);
567
        $this->assertEquals($admin->id, $messages[3]->useridfrom);
568
        $this->assertStringContainsString('xcourse2', $messages[3]->fullmessagehtml);
569
 
570
        // Then summary for course2.
571
        $this->assertEquals($admin->id, $messages[4]->useridto);
572
        $this->assertEquals($admin->id, $messages[4]->useridfrom);
573
        $this->assertStringContainsString('xcourse2', $messages[4]->fullmessagehtml);
574
        $this->assertStringNotContainsString('xuser1', $messages[4]->fullmessagehtml);
575
        $this->assertStringNotContainsString('xuser2', $messages[4]->fullmessagehtml);
576
        $this->assertStringContainsString('xuser3', $messages[4]->fullmessagehtml);
577
        $this->assertStringNotContainsString('xuser4', $messages[4]->fullmessagehtml);
578
        $this->assertStringNotContainsString('xuser5', $messages[4]->fullmessagehtml);
579
        $this->assertStringNotContainsString('xuser6', $messages[4]->fullmessagehtml);
580
 
581
        // Only summary in course3.
582
        $this->assertEquals($user1->id, $messages[5]->useridto);
583
        $this->assertEquals($admin->id, $messages[5]->useridfrom);
584
        $this->assertStringContainsString('xcourse3', $messages[5]->fullmessagehtml);
585
        $this->assertStringNotContainsString('xuser1', $messages[5]->fullmessagehtml);
586
        $this->assertStringNotContainsString('xuser2', $messages[5]->fullmessagehtml);
587
        $this->assertStringContainsString('xuser3', $messages[5]->fullmessagehtml);
588
        $this->assertStringNotContainsString('xuser4', $messages[5]->fullmessagehtml);
589
        $this->assertStringNotContainsString('xuser5', $messages[5]->fullmessagehtml);
590
        $this->assertStringNotContainsString('xuser6', $messages[5]->fullmessagehtml);
591
 
592
 
593
        // Make sure that notifications are not repeated.
594
        $sink->clear();
595
 
596
        $selfplugin->send_expiry_notifications($trace);
597
        $this->assertEquals(0, $sink->count());
598
 
599
        // use invalid notification hour to verify that before the hour the notifications are not sent.
600
        $selfplugin->set_config('expirynotifylast', time() - 60*60*24);
601
        $selfplugin->set_config('expirynotifyhour', '24');
602
 
603
        $selfplugin->send_expiry_notifications($trace);
604
        $this->assertEquals(0, $sink->count());
605
 
606
        $selfplugin->set_config('expirynotifyhour', '0');
607
        $selfplugin->send_expiry_notifications($trace);
608
        $this->assertEquals(6, $sink->count());
609
    }
610
 
611
    public function test_show_enrolme_link() {
612
        global $DB, $CFG;
613
        $this->resetAfterTest();
614
        $this->preventResetByRollback(); // Messaging does not like transactions...
615
 
616
        /** @var $selfplugin enrol_self_plugin */
617
        $selfplugin = enrol_get_plugin('self');
618
 
619
        $user1 = $this->getDataGenerator()->create_user();
620
        $user2 = $this->getDataGenerator()->create_user();
621
 
622
        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
623
        $this->assertNotEmpty($studentrole);
624
 
625
        $course1 = $this->getDataGenerator()->create_course();
626
        $course2 = $this->getDataGenerator()->create_course();
627
        $course3 = $this->getDataGenerator()->create_course();
628
        $course4 = $this->getDataGenerator()->create_course();
629
        $course5 = $this->getDataGenerator()->create_course();
630
        $course6 = $this->getDataGenerator()->create_course();
631
        $course7 = $this->getDataGenerator()->create_course();
632
        $course8 = $this->getDataGenerator()->create_course();
633
        $course9 = $this->getDataGenerator()->create_course();
634
        $course10 = $this->getDataGenerator()->create_course();
635
        $course11 = $this->getDataGenerator()->create_course();
636
 
637
        $cohort1 = $this->getDataGenerator()->create_cohort();
638
        $cohort2 = $this->getDataGenerator()->create_cohort();
639
 
640
        // New enrolments are allowed and enrolment instance is enabled.
641
        $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
642
        $instance1->customint6 = 1;
643
        $DB->update_record('enrol', $instance1);
644
        $selfplugin->update_status($instance1, ENROL_INSTANCE_ENABLED);
645
 
646
        // New enrolments are not allowed, but enrolment instance is enabled.
647
        $instance2 = $DB->get_record('enrol', array('courseid'=>$course2->id, 'enrol'=>'self'), '*', MUST_EXIST);
648
        $instance2->customint6 = 0;
649
        $DB->update_record('enrol', $instance2);
650
        $selfplugin->update_status($instance2, ENROL_INSTANCE_ENABLED);
651
 
652
        // New enrolments are allowed , but enrolment instance is disabled.
653
        $instance3 = $DB->get_record('enrol', array('courseid'=>$course3->id, 'enrol'=>'self'), '*', MUST_EXIST);
654
        $instance3->customint6 = 1;
655
        $DB->update_record('enrol', $instance3);
656
        $selfplugin->update_status($instance3, ENROL_INSTANCE_DISABLED);
657
 
658
        // New enrolments are not allowed and enrolment instance is disabled.
659
        $instance4 = $DB->get_record('enrol', array('courseid'=>$course4->id, 'enrol'=>'self'), '*', MUST_EXIST);
660
        $instance4->customint6 = 0;
661
        $DB->update_record('enrol', $instance4);
662
        $selfplugin->update_status($instance4, ENROL_INSTANCE_DISABLED);
663
 
664
        // Cohort member test.
665
        $instance5 = $DB->get_record('enrol', array('courseid'=>$course5->id, 'enrol'=>'self'), '*', MUST_EXIST);
666
        $instance5->customint6 = 1;
667
        $instance5->customint5 = $cohort1->id;
668
        $DB->update_record('enrol', $instance1);
669
        $selfplugin->update_status($instance5, ENROL_INSTANCE_ENABLED);
670
 
671
        $id = $selfplugin->add_instance($course5, $selfplugin->get_instance_defaults());
672
        $instance6 = $DB->get_record('enrol', array('id'=>$id), '*', MUST_EXIST);
673
        $instance6->customint6 = 1;
674
        $instance6->customint5 = $cohort2->id;
675
        $DB->update_record('enrol', $instance1);
676
        $selfplugin->update_status($instance6, ENROL_INSTANCE_ENABLED);
677
 
678
        // Enrol start date is in future.
679
        $instance7 = $DB->get_record('enrol', array('courseid'=>$course6->id, 'enrol'=>'self'), '*', MUST_EXIST);
680
        $instance7->customint6 = 1;
681
        $instance7->enrolstartdate = time() + 60;
682
        $DB->update_record('enrol', $instance7);
683
        $selfplugin->update_status($instance7, ENROL_INSTANCE_ENABLED);
684
 
685
        // Enrol start date is in past.
686
        $instance8 = $DB->get_record('enrol', array('courseid'=>$course7->id, 'enrol'=>'self'), '*', MUST_EXIST);
687
        $instance8->customint6 = 1;
688
        $instance8->enrolstartdate = time() - 60;
689
        $DB->update_record('enrol', $instance8);
690
        $selfplugin->update_status($instance8, ENROL_INSTANCE_ENABLED);
691
 
692
        // Enrol end date is in future.
693
        $instance9 = $DB->get_record('enrol', array('courseid'=>$course8->id, 'enrol'=>'self'), '*', MUST_EXIST);
694
        $instance9->customint6 = 1;
695
        $instance9->enrolenddate = time() + 60;
696
        $DB->update_record('enrol', $instance9);
697
        $selfplugin->update_status($instance9, ENROL_INSTANCE_ENABLED);
698
 
699
        // Enrol end date is in past.
700
        $instance10 = $DB->get_record('enrol', array('courseid'=>$course9->id, 'enrol'=>'self'), '*', MUST_EXIST);
701
        $instance10->customint6 = 1;
702
        $instance10->enrolenddate = time() - 60;
703
        $DB->update_record('enrol', $instance10);
704
        $selfplugin->update_status($instance10, ENROL_INSTANCE_ENABLED);
705
 
706
        // Maximum enrolments reached.
707
        $instance11 = $DB->get_record('enrol', array('courseid'=>$course10->id, 'enrol'=>'self'), '*', MUST_EXIST);
708
        $instance11->customint6 = 1;
709
        $instance11->customint3 = 1;
710
        $DB->update_record('enrol', $instance11);
711
        $selfplugin->update_status($instance11, ENROL_INSTANCE_ENABLED);
712
        $selfplugin->enrol_user($instance11, $user2->id, $studentrole->id);
713
 
714
        // Maximum enrolments not reached.
715
        $instance12 = $DB->get_record('enrol', array('courseid'=>$course11->id, 'enrol'=>'self'), '*', MUST_EXIST);
716
        $instance12->customint6 = 1;
717
        $instance12->customint3 = 1;
718
        $DB->update_record('enrol', $instance12);
719
        $selfplugin->update_status($instance12, ENROL_INSTANCE_ENABLED);
720
 
721
        $this->setUser($user1);
722
        $this->assertTrue($selfplugin->show_enrolme_link($instance1));
723
        $this->assertFalse($selfplugin->show_enrolme_link($instance2));
724
        $this->assertFalse($selfplugin->show_enrolme_link($instance3));
725
        $this->assertFalse($selfplugin->show_enrolme_link($instance4));
726
        $this->assertFalse($selfplugin->show_enrolme_link($instance7));
727
        $this->assertTrue($selfplugin->show_enrolme_link($instance8));
728
        $this->assertTrue($selfplugin->show_enrolme_link($instance9));
729
        $this->assertFalse($selfplugin->show_enrolme_link($instance10));
730
        $this->assertFalse($selfplugin->show_enrolme_link($instance11));
731
        $this->assertTrue($selfplugin->show_enrolme_link($instance12));
732
 
733
        require_once("$CFG->dirroot/cohort/lib.php");
734
        cohort_add_member($cohort1->id, $user1->id);
735
 
736
        $this->assertTrue($selfplugin->show_enrolme_link($instance5));
737
        $this->assertFalse($selfplugin->show_enrolme_link($instance6));
738
    }
739
 
740
    /**
741
     * This will check user enrolment only, rest has been tested in test_show_enrolme_link.
742
     */
743
    public function test_can_self_enrol() {
744
        global $DB, $CFG, $OUTPUT;
745
        $this->resetAfterTest();
746
        $this->preventResetByRollback();
747
 
748
        $selfplugin = enrol_get_plugin('self');
749
 
750
        $expectederrorstring = get_string('canntenrol', 'enrol_self');
751
 
752
        $user1 = $this->getDataGenerator()->create_user();
753
        $user2 = $this->getDataGenerator()->create_user();
754
        $guest = $DB->get_record('user', array('id' => $CFG->siteguest));
755
 
756
        $studentrole = $DB->get_record('role', array('shortname'=>'student'));
757
        $this->assertNotEmpty($studentrole);
758
        $editingteacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
759
        $this->assertNotEmpty($editingteacherrole);
760
 
761
        $course1 = $this->getDataGenerator()->create_course();
762
 
763
        $instance1 = $DB->get_record('enrol', array('courseid'=>$course1->id, 'enrol'=>'self'), '*', MUST_EXIST);
764
        $instance1->customint6 = 1;
765
        $DB->update_record('enrol', $instance1);
766
        $selfplugin->update_status($instance1, ENROL_INSTANCE_ENABLED);
767
        $selfplugin->enrol_user($instance1, $user2->id, $editingteacherrole->id);
768
 
769
        $this->setUser($guest);
770
        $this->assertStringContainsString(get_string('noguestaccess', 'enrol'),
771
                $selfplugin->can_self_enrol($instance1, true));
772
 
773
        $this->setUser($user1);
774
        $this->assertTrue($selfplugin->can_self_enrol($instance1, true));
775
 
776
        // Active enroled user.
777
        $this->setUser($user2);
778
        $selfplugin->enrol_user($instance1, $user1->id, $studentrole->id);
779
        $this->setUser($user1);
780
        $this->assertSame($expectederrorstring, $selfplugin->can_self_enrol($instance1, true));
781
    }
782
 
783
    /**
784
     * Test is_self_enrol_available function behavior.
785
     *
786
     * @covers ::is_self_enrol_available
787
     */
788
    public function test_is_self_enrol_available() {
789
        global $DB, $CFG;
790
 
791
        $this->resetAfterTest();
792
        $this->preventResetByRollback(); // Messaging does not like transactions...
793
 
794
        $selfplugin = enrol_get_plugin('self');
795
 
796
        $user1 = $this->getDataGenerator()->create_user();
797
        $user2 = $this->getDataGenerator()->create_user();
798
 
799
        $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST);
800
        $course = $this->getDataGenerator()->create_course();
801
        $cohort1 = $this->getDataGenerator()->create_cohort();
802
        $cohort2 = $this->getDataGenerator()->create_cohort();
803
 
804
        // New enrolments are allowed and enrolment instance is enabled.
805
        $instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'], '*', MUST_EXIST);
806
        $instance->customint6 = 1;
807
        $DB->update_record('enrol', $instance);
808
        $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED);
809
        $this->setUser($user1);
810
        $this->assertTrue($selfplugin->is_self_enrol_available($instance));
811
        $this->setGuestUser();
812
        $this->assertTrue($selfplugin->is_self_enrol_available($instance));
813
 
814
        $canntenrolerror = get_string('canntenrol', 'enrol_self');
815
 
816
        // New enrolments are not allowed, but enrolment instance is enabled.
817
        $instance->customint6 = 0;
818
        $DB->update_record('enrol', $instance);
819
        $this->setUser($user1);
820
        $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance));
821
        $this->setGuestUser();
822
        $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance));
823
 
824
        // New enrolments are allowed, but enrolment instance is disabled.
825
        $instance->customint6 = 1;
826
        $DB->update_record('enrol', $instance);
827
        $selfplugin->update_status($instance, ENROL_INSTANCE_DISABLED);
828
        $this->setUser($user1);
829
        $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance));
830
        $this->setGuestUser();
831
        $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance));
832
 
833
        // New enrolments are not allowed and enrolment instance is disabled.
834
        $instance->customint6 = 0;
835
        $DB->update_record('enrol', $instance);
836
        $this->setUser($user1);
837
        $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance));
838
        $this->setGuestUser();
839
        $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance));
840
 
841
        // Enable enrolment instance for the rest of the tests.
842
        $selfplugin->update_status($instance, ENROL_INSTANCE_ENABLED);
843
 
844
        // Enrol start date is in future.
845
        $instance->customint6 = 1;
846
        $instance->enrolstartdate = time() + 60;
847
        $DB->update_record('enrol', $instance);
848
        $error = get_string('canntenrolearly', 'enrol_self', userdate($instance->enrolstartdate));
849
        $this->setUser($user1);
850
        $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance));
851
        $this->setGuestUser();
852
        $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance));
853
 
854
        // Enrol start date is in past.
855
        $instance->enrolstartdate = time() - 60;
856
        $DB->update_record('enrol', $instance);
857
        $this->setUser($user1);
858
        $this->assertTrue($selfplugin->is_self_enrol_available($instance));
859
        $this->setGuestUser();
860
        $this->assertTrue($selfplugin->is_self_enrol_available($instance));
861
 
862
        // Enrol end date is in future.
863
        $instance->enrolstartdate = 0;
864
        $instance->enrolenddate = time() + 60;
865
        $DB->update_record('enrol', $instance);
866
        $this->setUser($user1);
867
        $this->assertTrue($selfplugin->is_self_enrol_available($instance));
868
        $this->setGuestUser();
869
        $this->assertTrue($selfplugin->is_self_enrol_available($instance));
870
 
871
        // Enrol end date is in past.
872
        $instance->enrolenddate = time() - 60;
873
        $DB->update_record('enrol', $instance);
874
        $error = get_string('canntenrollate', 'enrol_self', userdate($instance->enrolenddate));
875
        $this->setUser($user1);
876
        $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance));
877
        $this->setGuestUser();
878
        $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance));
879
 
880
        // Maximum enrolments reached.
881
        $instance->customint3 = 1;
882
        $instance->enrolenddate = 0;
883
        $DB->update_record('enrol', $instance);
884
        $selfplugin->enrol_user($instance, $user2->id, $studentrole->id);
885
        $error = get_string('maxenrolledreached', 'enrol_self');
886
        $this->setUser($user1);
887
        $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance));
888
        $this->setGuestUser();
889
        $this->assertEquals($error, $selfplugin->is_self_enrol_available($instance));
890
 
891
        // Maximum enrolments not reached.
892
        $instance->customint3 = 3;
893
        $DB->update_record('enrol', $instance);
894
        $this->setUser($user1);
895
        $this->assertTrue($selfplugin->is_self_enrol_available($instance));
896
        $this->setGuestUser();
897
        $this->assertTrue($selfplugin->is_self_enrol_available($instance));
898
 
899
        require_once("$CFG->dirroot/cohort/lib.php");
900
        cohort_add_member($cohort1->id, $user2->id);
901
 
902
        // Cohort test.
903
        $instance->customint5 = $cohort1->id;
904
        $DB->update_record('enrol', $instance);
905
        $error = get_string('cohortnonmemberinfo', 'enrol_self', $cohort1->name);
906
        $this->setUser($user1);
907
        $this->assertStringContainsString($error, $selfplugin->is_self_enrol_available($instance));
908
        $this->setGuestUser();
909
        $this->assertStringContainsString($error, $selfplugin->is_self_enrol_available($instance));
910
        $this->setUser($user2);
911
        $this->assertEquals($canntenrolerror, $selfplugin->is_self_enrol_available($instance));
912
    }
913
 
914
    /**
915
     * Test custom validation of instance data for group enrolment key
916
     *
917
     * @covers ::edit_instance_validation
918
     */
919
    public function test_edit_instance_validation_group_enrolment_key(): void {
920
        global $DB;
921
 
922
        $this->resetAfterTest();
923
 
924
        $course = $this->getDataGenerator()->create_course();
925
        $context = context_course::instance($course->id);
926
 
927
        /** @var enrol_self_plugin $plugin */
928
        $plugin = enrol_get_plugin('self');
929
 
930
        $instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => $plugin->get_name()], '*', MUST_EXIST);
931
 
932
        // Enable group enrolment keys.
933
        $errors = $plugin->edit_instance_validation([
934
            'customint1' => 1,
935
            'password' => 'cat',
936
        ] + (array) $instance, [], $instance, $context);
937
 
938
        $this->assertEmpty($errors);
939
 
940
        // Now create a group with the same enrolment key we want to use.
941
        $this->getDataGenerator()->create_group(['courseid' => $course->id, 'enrolmentkey' => 'cat']);
942
 
943
        $errors = $plugin->edit_instance_validation([
944
            'customint1' => 1,
945
            'password' => 'cat',
946
        ] + (array) $instance, [], $instance, $context);
947
 
948
        $this->assertArrayHasKey('password', $errors);
949
        $this->assertEquals('This enrolment key is already used as a group enrolment key.', $errors['password']);
950
    }
951
 
952
    /**
953
     * Test enrol_self_check_group_enrolment_key
954
     */
955
    public function test_enrol_self_check_group_enrolment_key() {
956
        global $DB;
957
        self::resetAfterTest(true);
958
 
959
        // Test in course with groups.
960
        $course = self::getDataGenerator()->create_course(array('groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1));
961
 
962
        $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
963
        $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id, 'enrolmentkey' => 'thepassword'));
964
 
965
        $result = enrol_self_check_group_enrolment_key($course->id, 'invalidpassword');
966
        $this->assertFalse($result);
967
 
968
        $result = enrol_self_check_group_enrolment_key($course->id, 'thepassword');
969
        $this->assertTrue($result);
970
 
971
        // Test disabling group options.
972
        $course->groupmode = NOGROUPS;
973
        $course->groupmodeforce = 0;
974
        $DB->update_record('course', $course);
975
 
976
        $result = enrol_self_check_group_enrolment_key($course->id, 'invalidpassword');
977
        $this->assertFalse($result);
978
 
979
        $result = enrol_self_check_group_enrolment_key($course->id, 'thepassword');
980
        $this->assertTrue($result);
981
 
982
        // Test without groups.
983
        $othercourse = self::getDataGenerator()->create_course();
984
        $result = enrol_self_check_group_enrolment_key($othercourse->id, 'thepassword');
985
        $this->assertFalse($result);
986
 
987
    }
988
 
989
    /**
990
     * Test get_welcome_email_contact().
991
     */
992
    public function test_get_welcome_email_contact() {
993
        global $DB;
994
        self::resetAfterTest(true);
995
 
996
        $user1 = $this->getDataGenerator()->create_user(['lastname' => 'Marsh']);
997
        $user2 = $this->getDataGenerator()->create_user(['lastname' => 'Victoria']);
998
        $user3 = $this->getDataGenerator()->create_user(['lastname' => 'Burch']);
999
        $user4 = $this->getDataGenerator()->create_user(['lastname' => 'Cartman']);
1000
        $noreplyuser = \core_user::get_noreply_user();
1001
 
1002
        $course1 = $this->getDataGenerator()->create_course();
1003
        $context = \context_course::instance($course1->id);
1004
 
1005
        // Get editing teacher role.
1006
        $editingteacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
1007
        $this->assertNotEmpty($editingteacherrole);
1008
 
1009
        // Enable self enrolment plugin and set to send email from course contact.
1010
        $selfplugin = enrol_get_plugin('self');
1011
        $instance1 = $DB->get_record('enrol', ['courseid' => $course1->id, 'enrol' => 'self'], '*', MUST_EXIST);
1012
        $instance1->customint6 = 1;
1013
        $instance1->customint4 = ENROL_SEND_EMAIL_FROM_COURSE_CONTACT;
1014
        $DB->update_record('enrol', $instance1);
1015
        $selfplugin->update_status($instance1, ENROL_INSTANCE_ENABLED);
1016
 
1017
        // This should return null.
1018
        $contact = $selfplugin->get_welcome_message_contact(ENROL_DO_NOT_SEND_EMAIL, $context);
1019
        $this->assertNull($contact);
1020
 
1021
        // We do not have a teacher enrolled at this point, so it should return null.
1022
        $contact = $selfplugin->get_welcome_message_contact(ENROL_SEND_EMAIL_FROM_COURSE_CONTACT, $context);
1023
        $this->assertNull($contact);
1024
 
1025
        // By default, course contact is assigned to teacher role.
1026
        // Enrol a teacher, now it should send emails from teacher email's address.
1027
        $selfplugin->enrol_user($instance1, $user1->id, $editingteacherrole->id);
1028
 
1029
        // We should get the teacher email.
1030
        $contact = $selfplugin->get_welcome_message_contact(ENROL_SEND_EMAIL_FROM_COURSE_CONTACT, $context);
1031
        $this->assertEquals($user1->username, $contact->username);
1032
        $this->assertEquals($user1->email, $contact->email);
1033
 
1034
        // Now let's enrol another teacher.
1035
        $selfplugin->enrol_user($instance1, $user2->id, $editingteacherrole->id);
1036
        $contact = $selfplugin->get_welcome_message_contact(ENROL_SEND_EMAIL_FROM_COURSE_CONTACT, $context);
1037
        $this->assertEquals($user1->username, $contact->username);
1038
        $this->assertEquals($user1->email, $contact->email);
1039
 
1040
        // Get manager role, and enrol user as manager.
1041
        $managerrole = $DB->get_record('role', ['shortname' => 'manager']);
1042
        $this->assertNotEmpty($managerrole);
1043
        $instance1->customint4 = ENROL_SEND_EMAIL_FROM_KEY_HOLDER;
1044
        $DB->update_record('enrol', $instance1);
1045
        $selfplugin->enrol_user($instance1, $user3->id, $managerrole->id);
1046
 
1047
        // Give manager role holdkey capability.
1048
        assign_capability('enrol/self:holdkey', CAP_ALLOW, $managerrole->id, $context);
1049
 
1050
        // We should get the manager email contact.
1051
        $contact = $selfplugin->get_welcome_message_contact(ENROL_SEND_EMAIL_FROM_KEY_HOLDER, $context);
1052
        $this->assertEquals($user3->username, $contact->username);
1053
        $this->assertEquals($user3->email, $contact->email);
1054
 
1055
        // Now let's enrol another manager.
1056
        $selfplugin->enrol_user($instance1, $user4->id, $managerrole->id);
1057
        $contact = $selfplugin->get_welcome_message_contact(ENROL_SEND_EMAIL_FROM_KEY_HOLDER, $context);
1058
        $this->assertEquals($user3->username, $contact->username);
1059
        $this->assertEquals($user3->email, $contact->email);
1060
 
1061
        $instance1->customint4 = ENROL_SEND_EMAIL_FROM_NOREPLY;
1062
        $DB->update_record('enrol', $instance1);
1063
 
1064
        $contact = $selfplugin->get_welcome_message_contact(ENROL_SEND_EMAIL_FROM_NOREPLY, $context);
1065
        $this->assertEquals($noreplyuser, $contact);
1066
 
1067
        $this->expectException(\moodle_exception::class);
1068
        $this->expectExceptionMessage('Invalid send option');
1069
        $contact = $selfplugin->get_welcome_message_contact(10, $context);
1070
    }
1071
 
1072
    /**
1073
     * Test for getting user enrolment actions.
1074
     */
1075
    public function test_get_user_enrolment_actions() {
1076
        global $CFG, $DB, $PAGE;
1077
        $this->resetAfterTest();
1078
 
1079
        // Set page URL to prevent debugging messages.
1080
        $PAGE->set_url('/enrol/editinstance.php');
1081
 
1082
        $pluginname = 'self';
1083
 
1084
        // Only enable the self enrol plugin.
1085
        $CFG->enrol_plugins_enabled = $pluginname;
1086
 
1087
        $generator = $this->getDataGenerator();
1088
 
1089
        // Get the enrol plugin.
1090
        $plugin = enrol_get_plugin($pluginname);
1091
 
1092
        // Create a course.
1093
        $course = $generator->create_course();
1094
 
1095
        // Create a teacher.
1096
        $teacher = $generator->create_user();
1097
        // Enrol the teacher to the course.
1098
        $enrolresult = $generator->enrol_user($teacher->id, $course->id, 'editingteacher', $pluginname);
1099
        $this->assertTrue($enrolresult);
1100
        // Create a student.
1101
        $student = $generator->create_user();
1102
        // Enrol the student to the course.
1103
        $enrolresult = $generator->enrol_user($student->id, $course->id, 'student', $pluginname);
1104
        $this->assertTrue($enrolresult);
1105
 
1106
        // Login as the teacher.
1107
        $this->setUser($teacher);
1108
        require_once($CFG->dirroot . '/enrol/locallib.php');
1109
        $manager = new \course_enrolment_manager($PAGE, $course);
1110
        $userenrolments = $manager->get_user_enrolments($student->id);
1111
        $this->assertCount(1, $userenrolments);
1112
 
1113
        $ue = reset($userenrolments);
1114
        $actions = $plugin->get_user_enrolment_actions($manager, $ue);
1115
        // Self enrol has 2 enrol actions -- edit and unenrol.
1116
        $this->assertCount(2, $actions);
1117
    }
1118
 
1119
    /**
1120
     * Test the behaviour of find_instance().
1121
     *
1122
     * @covers ::find_instance
1123
     */
1124
    public function test_find_instance() {
1125
        global $DB;
1126
        $this->resetAfterTest();
1127
 
1128
        $cat = $this->getDataGenerator()->create_category();
1129
        // When we create a course, a self enrolment instance is also created.
1130
        $course = $this->getDataGenerator()->create_course(['category' => $cat->id, 'shortname' => 'ANON']);
1131
 
1132
        $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
1133
        $selfplugin = enrol_get_plugin('self');
1134
 
1135
        $instanceid1 = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self']);
1136
 
1137
        // Let's add a second instance.
1138
        $instanceid2 = $selfplugin->add_instance($course, ['roleid' => $teacherrole->id]);
1139
 
1140
        $enrolmentdata = [];
1141
        // The first instance should be returned - due to sorting in enrol_get_instances().
1142
        $actual = $selfplugin->find_instance($enrolmentdata, $course->id);
1143
        $this->assertEquals($instanceid1->id, $actual->id);
1144
    }
1145
 
1146
    /**
1147
     * Test the behaviour of validate_enrol_plugin_data().
1148
     *
1149
     * @covers ::validate_enrol_plugin_data
1150
     */
1151
    public function test_validate_enrol_plugin_data(): void {
1152
        global $CFG;
1153
 
1154
        $this->resetAfterTest();
1155
 
1156
        // Test in course with groups.
1157
        $course = self::getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1]);
1158
 
1159
        $selfplugin = enrol_get_plugin('self');
1160
 
1161
        $selfplugin->set_config('usepasswordpolicy', false);
1162
        $enrolmentdata = [];
1163
        $errors = $selfplugin->validate_enrol_plugin_data($enrolmentdata);
1164
        $this->assertEmpty($errors);
1165
 
1166
        // Now enable some controls, and check that the policy responds with policy text.
1167
        $selfplugin->set_config('usepasswordpolicy', true);
1168
        $CFG->minpasswordlength = 8;
1169
        $CFG->minpassworddigits = 1;
1170
        $CFG->minpasswordlower = 1;
1171
        $CFG->minpasswordupper = 1;
1172
        $CFG->minpasswordnonalphanum = 1;
1173
        $CFG->maxconsecutiveidentchars = 1;
1174
        $errors = $selfplugin->validate_enrol_plugin_data($enrolmentdata);
1175
        // If password is omitted it will be autocreated so nothing to validate.
1176
        $this->assertEmpty($errors);
1177
 
1178
        $enrolmentdata = ['password' => 'test'];
1179
        $errors = $selfplugin->validate_enrol_plugin_data($enrolmentdata);
1180
        $this->assertCount(4, $errors);
1181
        $this->assertEquals(get_string('errorminpasswordlength', 'auth', $CFG->minpasswordlength), $errors['enrol_self0']);
1182
        $this->assertEquals(get_string('errorminpassworddigits', 'auth', $CFG->minpassworddigits), $errors['enrol_self1']);
1183
        $this->assertEquals(get_string('errorminpasswordupper', 'auth', $CFG->minpasswordupper), $errors['enrol_self2']);
1184
        $this->assertEquals(get_string('errorminpasswordnonalphanum', 'auth', $CFG->minpasswordnonalphanum), $errors['enrol_self3']);
1185
 
1186
        $enrolmentdata = ['password' => 'Testingtest123@'];
1187
        $errors = $selfplugin->validate_enrol_plugin_data($enrolmentdata);
1188
        $this->assertEmpty($errors);
1189
 
1190
        $this->getDataGenerator()->create_group(['courseid' => $course->id, 'enrolmentkey' => 'Abirvalg123@']);
1191
        $instance = $selfplugin->find_instance([], $course->id);
1192
        $instance->customint1 = 1;
1193
        $selfplugin->update_instance($instance, $instance);
1194
        $enrolmentdata = ['password' => 'Abirvalg123@'];
1195
        $errors = $selfplugin->validate_enrol_plugin_data($enrolmentdata, $course->id);
1196
        $this->assertArrayHasKey('errorpasswordmatchesgroupkey', $errors);
1197
    }
1198
 
1199
    /**
1200
     * Test the behaviour of update_enrol_plugin_data().
1201
     *
1202
     * @covers ::update_enrol_plugin_data
1203
     */
1204
    public function test_update_enrol_plugin_data(): void {
1205
        global $DB;
1206
        $this->resetAfterTest();
1207
        $manualplugin = enrol_get_plugin('self');
1208
 
1209
        $admin = get_admin();
1210
        $this->setUser($admin);
1211
 
1212
        $enrolmentdata = [];
1213
 
1214
        $cat = $this->getDataGenerator()->create_category();
1215
        $course = $this->getDataGenerator()->create_course(['category' => $cat->id, 'shortname' => 'ANON']);
1216
        $instance = $DB->get_record('enrol', ['courseid' => $course->id, 'enrol' => 'self'], '*', MUST_EXIST);
1217
 
1218
        $expectedinstance = $instance;
1219
        $modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance);
1220
        $this->assertEquals($expectedinstance, $modifiedinstance);
1221
 
1222
        $enrolmentdata['password'] = 'test';
1223
        $expectedinstance->password = 'test';
1224
        $modifiedinstance = $manualplugin->update_enrol_plugin_data($course->id, $enrolmentdata, $instance);
1225
        $this->assertEquals($expectedinstance, $modifiedinstance);
1226
    }
1227
 
1228
}