4383537fbaf3409efba8ddd1c94adb8b6a42b6ae
[moodle.git] / enrol / self / lib.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * Self enrolment plugin.
20  *
21  * @package   enrol_self
22  * @copyright 2010 Petr Skoda  {@link http://skodak.org}
23  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 /**
27  * Self enrolment plugin implementation.
28  * @author Petr Skoda
29  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30  */
31 class enrol_self_plugin extends enrol_plugin {
33     /**
34      * Returns localised name of enrol instance
35      *
36      * @param object $instance (null is accepted too)
37      * @return string
38      */
39     public function get_instance_name($instance) {
40         global $DB;
42         if (empty($instance->name)) {
43             if (!empty($instance->roleid) and $role = $DB->get_record('role', array('id'=>$instance->roleid))) {
44                 $role = ' (' . role_get_name($role, get_context_instance(CONTEXT_COURSE, $instance->courseid)) . ')';
45             } else {
46                 $role = '';
47             }
48             $enrol = $this->get_name();
49             return get_string('pluginname', 'enrol_'.$enrol) . $role;
50         } else {
51             return format_string($instance->name);
52         }
53     }
55     public function roles_protected() {
56         // users may tweak the roles later
57         return false;
58     }
60     public function allow_unenrol(stdClass $instance) {
61         // users with unenrol cap may unenrol other users manually manually
62         return true;
63     }
65     public function allow_manage(stdClass $instance) {
66         // users with manage cap may tweak period and status
67         return true;
68     }
70     /**
71      * Returns link to page which may be used to add new instance of enrolment plugin in course.
72      * @param int $courseid
73      * @return moodle_url page url
74      */
75     public function get_candidate_link($courseid) {
76         if (!has_capability('moodle/course:enrolconfig', get_context_instance(CONTEXT_COURSE, $courseid, MUST_EXIST))) {
77             return NULL;
78         }
79         // multiple instances supported - different roles with different password
80         return new moodle_url('/enrol/self/addinstance.php', array('sesskey'=>sesskey(), 'id'=>$courseid));
81     }
83     /**
84      * Creates course enrol form, checks if form submitted
85      * and enrols user if necessary. It can also redirect.
86      *
87      * @param stdClass $instance
88      * @return string html text, usually a form in a text box
89      */
90     public function enrol_page_hook(stdClass $instance) {
91         global $CFG, $OUTPUT, $SESSION, $USER, $DB;
93         if (isguestuser()) {
94             // can not enrol guest!!
95             return null;
96         }
97         if ($DB->record_exists('user_enrolments', array('userid'=>$USER->id, 'enrolid'=>$instance->id))) {
98             //TODO: maybe we should tell them they are already enrolled, but can not access the course
99             return null;
100         }
102         if ($instance->enrolstartdate != 0 and $instance->enrolstartdate < time) {
103             //TODO: inform that we can not enrol yet
104             return null;
105         }
107         if ($instance->enrolenddate != 0 and $instance->enrolenddate > time) {
108             //TODO: inform that enrolment is not possible any more
109             return null;
110         }
112         require_once("$CFG->dirroot/enrol/self/locallib.php");
113         $form = new enrol_self_enrol_form(NULL, $instance);
114         $instanceid = optional_param('instance', 0, PARAM_INT);
116         if ($instance->id == $instanceid) {
117             if ($data = $form->get_data()) {
118                 $enrol = enrol_get_plugin('self');
119                 if ($instance->enrolperiod) {
120                     $timestart = time();
121                     $tineend   = $timestart + $instance->enrolperiod;
122                 } else {
123                     $timestart = 0;
124                     $tineend   = 0;
125                 }
127                 $this->enrol_user($instance, $USER->id, $instance->roleid, $timestart, $tineend);
128                 add_to_log($instance->courseid, 'course', 'enrol', '../enrol/users.php?id='.$instance->courseid, $instance->courseid); //there should be userid somewhere!
129                 // send welcome
130                 if ($this->get_config('sendcoursewelcomemessage')) {
131                     $this->email_welcome_message($instance, $USER);
132                 }
133             }
134         }
136         ob_start();
137         $form->display();
138         $output = ob_get_clean();
140         return $OUTPUT->box($output);
141     }
143     /**
144      * Adds enrol instance UI to course edit form
145      *
146      * @param object $instance enrol instance or null if does not exist yet
147      * @param MoodleQuickForm $mform
148      * @param object $data
149      * @param object $context context of existing course or parent category if course does not exist
150      * @return void
151      */
152     public function course_edit_form($instance, MoodleQuickForm $mform, $data, $context) {
154         $i = isset($instance->id) ? $instance->id : 0;
155         $plugin = enrol_get_plugin('self');
156         $header = $plugin->get_instance_name($instance);
157         $config = has_capability('enrol/self:config', $context);
159         $mform->addElement('header', 'enrol_self_header_'.$i, $header);
162         $options = array(ENROL_INSTANCE_ENABLED  => get_string('yes'),
163                          ENROL_INSTANCE_DISABLED => get_string('no'));
164         $mform->addElement('select', 'enrol_self_status_'.$i, get_string('status', 'enrol_self'), $options);
165         $mform->setDefault('enrol_self_status_'.$i, $this->get_config('status'));
166         $mform->setAdvanced('enrol_self_status_'.$i, $this->get_config('status_adv'));
167         if (!$config) {
168             $mform->hardFreeze('enrol_self_status_'.$i);
169         }
172         $mform->addElement('passwordunmask', 'enrol_self_password_'.$i, get_string('password', 'enrol_self'));
173         if (!$config) {
174             $mform->hardFreeze('enrol_self_password_'.$i);
175         } else {
176             $mform->disabledIf('enrol_self_password_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
177         }
180         $options = array(1 => get_string('yes'),
181                          0 => get_string('no'));
182         $mform->addElement('select', 'enrol_self_customint1_'.$i, get_string('groupkey', 'enrol_self'), $options);
183         $mform->setDefault('enrol_self_customint1_'.$i, $this->get_config('groupkey'));
184         $mform->setAdvanced('enrol_self_customint1_'.$i, $this->get_config('groupkey_adv'));
185         if (!$config) {
186             $mform->hardFreeze('enrol_self_customint1_'.$i);
187         } else {
188             $mform->disabledIf('enrol_self_customint1_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
189         }
192         if ($instance) {
193             $roles = get_default_enrol_roles($context, $instance->roleid);
194         } else {
195             $roles = get_default_enrol_roles($context, $this->get_config('roleid'));
196         }
197         $mform->addElement('select', 'enrol_self_roleid_'.$i, get_string('role', 'enrol_self'), $roles);
198         $mform->setDefault('enrol_self_roleid_'.$i, $this->get_config('roleid'));
199         $mform->setAdvanced('enrol_self_roleid_'.$i, $this->get_config('roleid_adv'));
200         if (!$config) {
201             $mform->hardFreeze('enrol_self_roleid_'.$i);
202         } else {
203             $mform->disabledIf('enrol_self_roleid_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
204         }
207         $mform->addElement('duration', 'enrol_self_enrolperiod_'.$i, get_string('enrolperiod', 'enrol_self'), array('optional' => true, 'defaultunit' => 86400));
208         $mform->setDefault('enrol_self_enrolperiod_'.$i, $this->get_config('enrolperiod'));
209         $mform->setAdvanced('enrol_self_enrolperiod_'.$i, $this->get_config('enrolperiod_adv'));
210         if (!$config) {
211             $mform->hardFreeze('enrol_self_enrolperiod_'.$i);
212         } else {
213             $mform->disabledIf('enrol_self_enrolperiod_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
214         }
217         $mform->addElement('date_selector', 'enrol_self_enrolstartdate_'.$i, get_string('enrolstartdate', 'enrol_self'), array('optional' => true));
218         $mform->setDefault('enrol_self_enrolstartdate_'.$i, 0);
219         $mform->setAdvanced('enrol_self_enrolstartdate_'.$i, 1);
220         if (!$config) {
221             $mform->hardFreeze('enrol_self_enrolstartdate_'.$i);
222         } else {
223             $mform->disabledIf('enrol_self_enrolstartdate_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
224         }
227         $mform->addElement('date_selector', 'enrol_self_enrolenddate_'.$i, get_string('enrolenddate', 'enrol_self'), array('optional' => true));
228         $mform->setDefault('enrol_self_enrolenddate_'.$i, 0);
229         $mform->setAdvanced('enrol_self_enrolenddate_'.$i, 1);
230         if (!$config) {
231             $mform->hardFreeze('enrol_self_enrolenddate_'.$i);
232         } else {
233             $mform->disabledIf('enrol_self_enrolenddate_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
234         }
237         // now add all values from enrol table
238         if ($instance) {
239             foreach($instance as $key=>$val) {
240                 $data->{'enrol_self_'.$key.'_'.$i} = $val;
241             }
242         }
243     }
246     /**
247      * Validates course edit form data
248      *
249      * @param object $instance enrol instance or null if does not exist yet
250      * @param array $data
251      * @param object $context context of existing course or parent category if course does not exist
252      * @return array errors array
253      */
254     public function course_edit_validation($instance, array $data, $context) {
255         $errors = array();
257         if (!has_capability('enrol/self:config', $context)) {
258             // we are going to ignore the data later anyway, they would not be able to fix the form anyway
259             return $errors;
260         }
262         $i = isset($instance->id) ? $instance->id : 0;
264         $password = empty($data['enrol_self_password_'.$i]) ? '' : $data['enrol_self_password_'.$i];
265         $checkpassword = false;
267         if ($instance) {
268             if ($data['enrol_self_status_'.$i] == ENROL_INSTANCE_ENABLED) {
269                 if ($instance->password !== $password) {
270                     $checkpassword = true;
271                 }
272             }
273         } else {
274             if ($data['enrol_self_status_'.$i] == ENROL_INSTANCE_ENABLED) {
275                 $checkpassword = true;
276             }
277         }
279         if ($checkpassword) {
280             $require = $this->get_config('requirepassword');
281             $policy  = $this->get_config('usepasswordpolicy');
282             if ($require and empty($password)) {
283                 $errors['enrol_self_password_'.$i] = get_string('required');
284             } else if ($policy) {
285                 $errmsg = '';//prevent eclipse warning
286                 if (!check_password_policy($password, $errmsg)) {
287                     $errors['enrol_self_password_'.$i] = $errmsg;
288                 }
289             }
290         }
292         if ($data['enrol_self_status_'.$i] == ENROL_INSTANCE_ENABLED) {
293             if (!empty($data['enrol_self_enrolenddate_'.$i]) and $data['enrol_self_enrolenddate_'.$i] < $data['enrol_self_enrolstartdate_'.$i]) {
294                 $errors['enrol_self_enrolenddate_'.$i] = get_string('enrolenddaterror', 'enrol_self');
295             }
296         }
298         return $errors;
299     }
302     /**
303      * Called after updating/inserting course.
304      *
305      * @param bool $inserted true if course just inserted
306      * @param object $course
307      * @param object $data form data
308      * @return void
309      */
310     public function course_updated($inserted, $course, $data) {
311         global $DB;
313         $context = get_context_instance(CONTEXT_COURSE, $course->id);
315         if (has_capability('enrol/self:config', $context)) {
316             if ($inserted) {
317                 if (isset($data->enrol_self_status_0)) {
318                     $fields = array('status'=>$data->enrol_self_status_0);
319                     if ($fields['status'] == ENROL_INSTANCE_ENABLED) {
320                         $fields['password']       = $data->enrol_self_password_0;
321                         $fields['customint1']     = $data->enrol_self_customint1_0;
322                         $fields['roleid']         = $data->enrol_self_roleid_0;
323                         $fields['enrolperiod']    = $data->enrol_self_enrolperiod_0;
324                         $fields['enrolstartdate'] = $data->enrol_self_enrolstartdate_0;
325                         $fields['enrolenddate']   = $data->enrol_self_enrolenddate_0;
326                     } else {
327                         if ($this->get_config('requirepassword')) {
328                             // make sure some password is set after enabling this plugin
329                             $fields['password']   = generate_password(20);
330                         }
331                         $fields['customint1']     = $this->get_config('groupkey');
332                         $fields['roleid']         = $this->get_config('roleid');
333                         $fields['enrolperiod']    = $this->get_config('enrolperiod');
334                         $fields['enrolstartdate'] = 0;
335                         $fields['enrolenddate']   = 0;
336                     }
337                     $this->add_instance($course, $fields);
338                 }
340             } else {
341                 $instances = $DB->get_records('enrol', array('courseid'=>$course->id, 'enrol'=>'self'));
342                 foreach ($instances as $instance) {
343                     $i = $instance->id;
345                     if (isset($data->{'enrol_self_status_'.$i})) {
346                         $instance->status       = $data->{'enrol_self_status_'.$i};
347                         $instance->timemodified = time();
348                         if ($instance->status == ENROL_INSTANCE_ENABLED) {
349                             $instance->password       = $data->{'enrol_self_password_'.$i};
350                             $instance->customint1     = $data->{'enrol_self_customint1_'.$i};
351                             $instance->roleid         = $data->{'enrol_self_roleid_'.$i};
352                             $instance->enrolperiod    = $data->{'enrol_self_enrolperiod_'.$i};
353                             $instance->enrolstartdate = $data->{'enrol_self_enrolstartdate_'.$i};
354                             $instance->enrolenddate   = $data->{'enrol_self_enrolenddate_'.$i};
355                         }
356                         $DB->update_record('enrol', $instance);
357                     }
358                 }
359             }
361         } else {
362             if ($inserted) {
363                 if ($this->get_config('defaultenrol')) {
364                     $this->add_default_instance($course);
365                 }
366             } else {
367                 // bad luck, user can not change anything
368             }
369         }
370     }
372     /**
373      * Add new instance of enrol plugin with default settings.
374      * @param object $course
375      * @return int id of new instance
376      */
377     public function add_default_instance($course) {
378         global $DB;
380         $exists = $DB->record_exists('enrol', array('courseid'=>$course->id, 'enrol'=>'self'));
382         $fields = array('customint1'=>$this->get_config('groupkey'), 'enrolperiod'=>$this->get_config('enrolperiod', 0), 'roleid'=>$this->get_config('roleid', 0));
384         $fields['status'] = $exists ? ENROL_INSTANCE_DISABLED : $this->get_config('status');
386         if ($this->get_config('requirepassword')) {
387             $fields['password'] = generate_password(20);
388         }
390         return $this->add_instance($course, $fields);
391     }
393     /**
394      * Send welcome email to specified user
395      *
396      * @param object $instance
397      * @param object $user user record
398      * @return void
399      */
400     protected function email_welcome_message($instance, $user) {
401         global $CFG, $DB;
403         $course = $DB->get_record('course', array('id'=>$instance->courseid), '*', MUST_EXIST);
405         if (!empty($instance->customtext1)) {
406             //note: there is no gui for this yet, do we really need it?
407             $message = formaat_string($instance->customtext1);
408         } else {
409             $a = new object();
410             $a->coursename = format_string($course->fullname);
411             $a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id&course=$course->id";
412             $message = get_string("welcometocoursetext", 'enrol_self', $a);
413         }
415         $subject = get_string('welcometocourse', 'enrol_self', format_string($course->fullname));
417         $context = get_context_instance(CONTEXT_COURSE, $course->id);
418         $rusers = null;
419         if (!empty($CFG->coursecontact)) {
420             $croles = explode(',', $CFG->coursecontact);
421             $rusers = get_role_users($croles, $context, true, '', 'r.sortorder ASC, u.lastname ASC');
422         }
423         if ($rusers) {
424             $contact = reset($rusers);
425         } else {
426             $contact = get_admin();
427         }
429         email_to_user($user, $contact, $subject, $message);
430     }