MDL-17457 migrated all modules to new db/install.php; added upgrade.txt file for...
[moodle.git] / enrol / manual / enrol.php
CommitLineData
f9667a5a 1<?php /// $Id$
2///////////////////////////////////////////////////////////////////////////
3// //
4// NOTICE OF COPYRIGHT //
5// //
6// Moodle - Modular Object-Oriented Dynamic Learning Environment //
7// http://moodle.org //
8// //
9// Copyright (C) 2004 Martin Dougiamas http://moodle.com //
10// //
11// This program is free software; you can redistribute it and/or modify //
12// it under the terms of the GNU General Public License as published by //
13// the Free Software Foundation; either version 2 of the License, or //
14// (at your option) any later version. //
15// //
16// This program is distributed in the hope that it will be useful, //
17// but WITHOUT ANY WARRANTY; without even the implied warranty of //
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
19// GNU General Public License for more details: //
20// //
21// http://www.gnu.org/copyleft/gpl.html //
22// //
23///////////////////////////////////////////////////////////////////////////
b8e13a57 24
778918fd 25require_once($CFG->dirroot.'/group/lib.php');
3b120e46 26require_once($CFG->libdir.'/eventslib.php');
f9667a5a 27
28/**
a51e2a7f 29* enrolment_plugin_manual is the default enrolment plugin
f9667a5a 30*
31* This class provides all the functionality for an enrolment plugin
a51e2a7f 32* In fact it includes all the code for the default, "manual" method
f9667a5a 33* so that other plugins can override these as necessary.
34*/
35
a51e2a7f 36class enrolment_plugin_manual {
f9667a5a 37
38var $errormsg;
39
f9667a5a 40/**
41* Prints the entry form/page for this enrolment
42*
43* This is only called from course/enrol.php
0be6f678 44* Most plugins will probably override this to print payment
45* forms etc, or even just a notice to say that manual enrolment
f9667a5a 46* is disabled
47*
48* @param course current course object
49*/
50function print_entry($course) {
51 global $CFG, $USER, $SESSION, $THEME;
52
27e14376 53 $strloginto = get_string('loginto', '', $course->shortname);
54 $strcourses = get_string('courses');
f9667a5a 55
56/// Automatically enrol into courses without password
57
a06694dd 58 $context = get_context_instance(CONTEXT_SYSTEM);
0be6f678 59
60 $navlinks = array();
61 $navlinks[] = array('name' => $strcourses, 'link' => ".", 'type' => 'misc');
62 $navlinks[] = array('name' => $strloginto, 'link' => null, 'type' => 'misc');
63 $navigation = build_navigation($navlinks);
f9667a5a 64
9d05e659 65 if ($course->password == '') { // no password, so enrol
66
67 if (has_capability('moodle/legacy:guest', $context, $USER->id, false)) {
68 add_to_log($course->id, 'course', 'guest', 'view.php?id='.$course->id, getremoteaddr());
f9667a5a 69
70 } else if (empty($_GET['confirm']) && empty($_GET['cancel'])) {
71
0be6f678 72 print_header($strloginto, $course->fullname, $navigation);
9d05e659 73 echo '<br />';
0be6f678 74 notice_yesno(get_string('enrolmentconfirmation'), "enrol.php?id=$course->id&amp;confirm=1",
9d05e659 75 "enrol.php?id=$course->id&amp;cancel=1");
f9667a5a 76 print_footer();
77 exit;
78
9d05e659 79 } else if (!empty($_GET['confirm'])) {
f9667a5a 80
9d05e659 81 if (!enrol_into_course($course, $USER, 'manual')) {
82 print_error('couldnotassignrole');
f9667a5a 83 }
57770b87 84 // force a refresh of mycourses
85 unset($USER->mycourses);
f9667a5a 86
bd4128e9 87 if (!empty($SESSION->wantsurl)) {
f9667a5a 88 $destination = $SESSION->wantsurl;
89 unset($SESSION->wantsurl);
90 } else {
91 $destination = "$CFG->wwwroot/course/view.php?id=$course->id";
92 }
93
94 redirect($destination);
9d05e659 95
96 } else if (!empty($_GET['cancel'])) {
f9667a5a 97 unset($SESSION->wantsurl);
bd4128e9 98 if (!empty($SESSION->enrolcancel)) {
99 $destination = $SESSION->enrolcancel;
100 unset($SESSION->enrolcancel);
101 } else {
102 $destination = $CFG->wwwroot;
103 }
104 redirect($destination);
f9667a5a 105 }
106 }
4d3145f3 107
108 // if we get here we are going to display the form asking for the enrolment key
109 // and (hopefully) provide information about who to ask for it.
f9667a5a 110 if (!isset($password)) {
9d05e659 111 $password = '';
f9667a5a 112 }
113
0be6f678 114 print_header($strloginto, $course->fullname, $navigation, "form.password");
f9667a5a 115
116 print_course($course, "80%");
117
a51e2a7f 118 include("$CFG->dirroot/enrol/manual/enrol.html");
f9667a5a 119
120 print_footer();
121
122}
123
124
125
126/**
127* The other half to print_entry, this checks the form data
128*
0be6f678 129* This function checks that the user has completed the task on the
f9667a5a 130* enrolment entry page and then enrolls them.
131*
132* @param form the form data submitted, as an object
133* @param course the current course, as an object
134*/
135function check_entry($form, $course) {
136 global $CFG, $USER, $SESSION, $THEME;
137
138 if (empty($form->password)) {
139 $form->password = '';
140 }
141
44adc903 142 if (empty($course->password)) {
143 // do not allow entry when no course password set
144 // automatic login when manual primary, no login when secondary at all!!
f945d59b 145 print_error('invalidenrol');
44adc903 146 }
147
f9667a5a 148 $groupid = $this->check_group_entry($course->id, $form->password);
f9667a5a 149
294ce987 150 if (($form->password == $course->password) or ($groupid !== false) ) {
f9667a5a 151
2b91b669 152 if (isguestuser()) { // only real user guest, do not use this for users with guest role
b1f318a6 153 $USER->enrolkey[$course->id] = true;
9d05e659 154 add_to_log($course->id, 'course', 'guest', 'view.php?id='.$course->id, getremoteaddr());
f9667a5a 155
9d05e659 156 } else { /// Update or add new enrolment
157 if (enrol_into_course($course, $USER, 'manual')) {
57770b87 158 // force a refresh of mycourses
159 unset($USER->mycourses);
9d05e659 160 if ($groupid !== false) {
5bf243d1 161 if (!groups_add_member($groupid, $USER->id)) {
9d05e659 162 print_error('couldnotassigngroup');
163 }
f9667a5a 164 }
9d05e659 165 } else {
166 print_error('couldnotassignrole');
f9667a5a 167 }
f9667a5a 168 }
9d05e659 169
f9667a5a 170 if ($SESSION->wantsurl) {
171 $destination = $SESSION->wantsurl;
172 unset($SESSION->wantsurl);
173 } else {
174 $destination = "$CFG->wwwroot/course/view.php?id=$course->id";
175 }
9d05e659 176
f9667a5a 177 redirect($destination);
178
9ab17a32 179 } else if (!isset($CFG->enrol_manual_showhint) or $CFG->enrol_manual_showhint) {
180 $this->errormsg = get_string('enrolmentkeyhint', '', substr($course->password, 0, 1));
181
f9667a5a 182 } else {
9ab17a32 183 $this->errormsg = get_string('enrolmentkeyerror', 'enrol_manual');
f9667a5a 184 }
f9667a5a 185}
186
187
188/**
189* Check if the given enrolment key matches a group enrolment key for the given course
190*
f9667a5a 191* @param courseid the current course id
192* @param password the submitted enrolment key
193*/
194function check_group_entry ($courseid, $password) {
25c3f91a 195
196 if ($groups = groups_get_all_groups($courseid)) {
9d05e659 197 foreach ($groups as $group) {
294ce987 198 if ( !empty($group->enrolmentkey) and ($password == $group->enrolmentkey) ) {
25c3f91a 199 return $group->id;
9d05e659 200 }
201 }
f9667a5a 202 }
25c3f91a 203
204 return false;
b8e13a57 205}
206
f9667a5a 207
208/**
209* Prints a form for configuring the current enrolment plugin
210*
0be6f678 211* This function is called from admin/enrol.php, and outputs a
f9667a5a 212* full page with a form for defining the current enrolment plugin.
213*
4d3145f3 214* @param frm an object containing all the data for this page
f9667a5a 215*/
4d3145f3 216function config_form($frm) {
217 global $CFG;
218
219 if (!isset( $frm->enrol_manual_keyholderrole )) {
220 $frm->enrol_manual_keyholderrole = '';
0be6f678 221 }
222
9ab17a32 223 if (!isset($frm->enrol_manual_showhint)) {
224 $frm->enrol_manual_showhint = 1;
225 }
226
82672532 227 if (!isset($frm->enrol_manual_usepasswordpolicy)) {
228 $frm->enrol_manual_usepasswordpolicy = 0;
229 }
230
231 if (!isset($frm->enrol_manual_requirekey)) {
232 $frm->enrol_manual_requirekey = 0;
233 }
234
4d3145f3 235 include ("$CFG->dirroot/enrol/manual/config.html");
f9667a5a 236}
237
238
239/**
240* Processes and stored configuration data for the enrolment plugin
241*
f9667a5a 242* @param config all the configuration data as entered by the admin
243*/
244function process_config($config) {
245
246 $return = true;
247
248 foreach ($config as $name => $value) {
249 if (!set_config($name, $value)) {
250 $return = false;
251 }
252 }
253
254 return $return;
255}
256
257
258/**
4b1b3702 259* Notify users about enrolments that are going to expire soon!
260* This function is run by admin/cron.php
261* @return void
f9667a5a 262*/
263function cron() {
50c5bef4 264 global $CFG, $USER, $SITE, $DB;
9d05e659 265
4b1b3702 266 if (!isset($CFG->lastexpirynotify)) {
267 set_config('lastexpirynotify', 0);
268 }
3a4c750b 269
4b1b3702 270 // notify once a day only - TODO: add some tz handling here, maybe use timestamps
271 if ($CFG->lastexpirynotify == date('Ymd')) {
ee2e85d4 272 return;
941308d3 273 }
0be6f678 274
50c5bef4 275 if ($rs = $DB->get_recordset_select('course', 'enrolperiod > 0 AND expirynotify > 0 AND expirythreshold > 0')) {
f9667a5a 276 $admin = get_admin();
3a4c750b 277
50c5bef4 278 foreach ($rs as $course) {
2b91b669 279 $a = new object();
4b1b3702 280 $a->coursename = $course->shortname .'/'. $course->fullname; // must be processed by format_string later
281 $a->threshold = $course->expirythreshold / 86400;
282 $a->extendurl = $CFG->wwwroot . '/user/index.php?id=' . $course->id;
283 $a->current = array();
284 $a->past = array();
285
f9667a5a 286 $expiry = time() + $course->expirythreshold;
4b1b3702 287 $cname = $course->fullname;
3a4c750b 288
4b1b3702 289 /// Get all the manual role assignments for this course that have expired.
3a4c750b 290
291 if (!$context = get_context_instance(CONTEXT_COURSE, $course->id)) {
292 continue;
293 }
294
50c5bef4 295 if ($oldenrolments = $DB->get_records_sql("
4b1b3702 296 SELECT u.*, ra.timeend
50c5bef4 297 FROM {user} u
298 JOIN {role_assignments} ra ON (ra.userid = u.id)
4b1b3702 299 WHERE ra.contextid = $context->id
300 AND ra.timeend > 0 AND ra.timeend <= $expiry
301 AND ra.enrol = 'manual'")) {
302
303 // inform user who can assign roles or admin
304 if ($teachers = get_users_by_capability($context, 'moodle/role:assign', '', '', '', '', '', '', false)) {
305 $teachers = sort_by_roleassignment_authority($teachers, $context);
306 $teacher = reset($teachers);
307 } else {
308 $teachers = array($admin);
309 $teacher = $admin;
3a4c750b 310 }
311
3a4c750b 312 $a->teacherstr = fullname($teacher, true);
313
3a4c750b 314 foreach ($oldenrolments as $user) { /// Email all users about to expire
2b91b669 315 $a->studentstr = fullname($user, true);
3a4c750b 316 if ($user->timeend < ($expiry - 86400)) {
317 $a->past[] = fullname($user) . " <$user->email>";
f9667a5a 318 } else {
3a4c750b 319 $a->current[] = fullname($user) . " <$user->email>";
320 if ($course->notifystudents) { // Send this guy notice
4b1b3702 321 // setup global $COURSE properly - needed for languages
e8b7114d 322 cron_setup_user($user, $course);
4b1b3702 323 $a->coursename = format_string($cname);
324 $a->course = $a->coursename;
325 $strexpirynotifystudentsemail = get_string('expirynotifystudentsemail', '', $a);
326 $strexpirynotify = get_string('expirynotify');
327
3b120e46 328 $eventdata = new object();
329 $eventdata->modulename = 'moodle';
330 $eventdata->userfrom = $teacher;
331 $eventdata->userto = $user;
332 $eventdata->subject = format_string($SITE->fullname) .' '. $strexpirynotify;
333 $eventdata->fullmessage = $strexpirynotifystudentsemail;
334 $eventdata->fullmessageformat = FORMAT_PLAIN;
335 $eventdata->fullmessagehtml = '';
336 $eventdata->smallmessage = '';
337 events_trigger('message_send', $eventdata);
f9667a5a 338 }
339 }
340 }
3a4c750b 341
342 $a->current = implode("\n", $a->current);
4b1b3702 343 $a->past = implode("\n", $a->past);
3a4c750b 344
345 if ($a->current || $a->past) {
4b1b3702 346 foreach ($teachers as $teacher) {
347 // setup global $COURSE properly - needed for languages
e8b7114d 348 cron_setup_user($teacher, $course);
4b1b3702 349 $a->coursename = format_string($cname);
350 $strexpirynotifyemail = get_string('expirynotifyemail', '', $a);
351 $strexpirynotify = get_string('expirynotify');
352
3b120e46 353 $eventdata = new object();
354 $eventdata->modulename = 'moodle';
355 $eventdata->userfrom = $admin;
356 $eventdata->userto = $teacher;
357 $eventdata->subject = $a->coursename .' '. $strexpirynotify;
358 $eventdata->fullmessage = $strexpirynotifyemail;
359 $eventdata->fullmessageformat = FORMAT_PLAIN;
360 $eventdata->fullmessagehtml = '';
361 $eventdata->smallmessage = '';
362 events_trigger('message_send', $eventdata);
f9667a5a 363 }
364 }
365 }
f9667a5a 366 }
50c5bef4 367 $rs->close();
e8b7114d 368 cron_setup_user();
f9667a5a 369 }
4b1b3702 370
371 set_config('lastexpirynotify', date('Ymd'));
f9667a5a 372}
373
374
375/**
376* Returns the relevant icons for a course
377*
f9667a5a 378* @param course the current course, as an object
379*/
380function get_access_icons($course) {
381 global $CFG;
382
9d05e659 383 global $strallowguests;
384 global $strrequireskey;
385
386 if (empty($strallowguests)) {
387 $strallowguests = get_string('allowguests');
388 $strrequireskey = get_string('requireskey');
389 }
f9667a5a 390
1cd85caf 391 $str = '';
392
f9667a5a 393 if (!empty($course->guest)) {
f9667a5a 394 $str .= '<a title="'.$strallowguests.'" href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">';
eb296382 395 $str .= '<img class="accessicon" alt="'.$strallowguests.'" src="'.$CFG->pixpath.'/i/guest.gif" /></a>&nbsp;&nbsp;';
f9667a5a 396 }
397 if (!empty($course->password)) {
f9667a5a 398 $str .= '<a title="'.$strrequireskey.'" href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">';
eb296382 399 $str .= '<img class="accessicon" alt="'.$strrequireskey.'" src="'.$CFG->pixpath.'/i/key.gif" /></a>';
f9667a5a 400 }
401
402 return $str;
403}
404
4d3145f3 405/**
406 * Prints the message telling you were to get the enrolment key
407 * appropriate for the prevailing circumstances
408 * A bit clunky because I didn't want to change the standard strings
409 */
410function print_enrolmentkeyfrom($course) {
411 global $CFG;
412 global $USER;
413
a06694dd 414 $context = get_context_instance(CONTEXT_SYSTEM);
4d3145f3 415 $guest = has_capability('moodle/legacy:guest', $context, $USER->id, false);
416
417 // if a keyholder role is defined we list teachers in that role (if any exist)
418 $contactslisted = false;
690c946c 419 $canseehidden = has_capability('moodle/role:viewhiddenassigns', $context);
4d3145f3 420 if (!empty($CFG->enrol_manual_keyholderrole)) {
e1eaf071 421 if ($contacts = get_role_users($CFG->enrol_manual_keyholderrole, get_context_instance(CONTEXT_COURSE, $course->id),true,'','u.lastname ASC',$canseehidden )) {
4d3145f3 422 // guest user has a slightly different message
423 if ($guest) {
424 print_string('enrolmentkeyfromguest', '', ':<br />' );
425 }
426 else {
427 print_string('enrolmentkeyfrom', '', ':<br />');
428 }
429 foreach ($contacts as $contact) {
430 $contactname = "<a href=\"../user/view.php?id=$contact->id&course=".SITEID."\">".fullname($contact)."</a>.";
431 echo "$contactname<br />";
432 }
433 $contactslisted = true;
0be6f678 434 }
4d3145f3 435 }
436
437 // if no keyholder role is defined OR nobody is in that role we do this the 'old' way
438 // (show the first person with update rights)
439 if (!$contactslisted) {
0be6f678 440 if ($teachers = get_users_by_capability(get_context_instance(CONTEXT_COURSE, $course->id), 'moodle/course:update',
0d846650 441 'u.*', 'u.id ASC', 0, 1, '', '', false, true)) {
4d3145f3 442 $teacher = array_shift($teachers);
443 }
444 if (!empty($teacher)) {
445 $teachername = "<a href=\"../user/view.php?id=$teacher->id&course=".SITEID."\">".fullname($teacher)."</a>.";
446 } else {
9101efd3 447 $teachername = strtolower( get_string('defaultcourseteacher') );
4d3145f3 448 }
449
450 // guest user has a slightly different message
451 if ($guest) {
452 print_string('enrolmentkeyfromguest', '', $teachername );
453 }
454 else {
455 print_string('enrolmentkeyfrom', '', $teachername);
456 }
457 }
458}
f9667a5a 459
460} /// end of class
461
b8e13a57 462?>