MDL-23253 plugin now may indicate if the want "Enrol me" link in navigation
[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     public function show_enrolme_link(stdClass $instance) {
71         return ($instance->status == ENROL_INSTANCE_ENABLED);
72     }
74     /**
75      * Returns link to page which may be used to add new instance of enrolment plugin in course.
76      * @param int $courseid
77      * @return moodle_url page url
78      */
79     public function get_candidate_link($courseid) {
80         if (!has_capability('moodle/course:enrolconfig', get_context_instance(CONTEXT_COURSE, $courseid, MUST_EXIST))) {
81             return NULL;
82         }
83         // multiple instances supported - different roles with different password
84         return new moodle_url('/enrol/self/addinstance.php', array('sesskey'=>sesskey(), 'id'=>$courseid));
85     }
87     /**
88      * Creates course enrol form, checks if form submitted
89      * and enrols user if necessary. It can also redirect.
90      *
91      * @param stdClass $instance
92      * @return string html text, usually a form in a text box
93      */
94     public function enrol_page_hook(stdClass $instance) {
95         global $CFG, $OUTPUT, $SESSION, $USER, $DB;
97         if (isguestuser()) {
98             // can not enrol guest!!
99             return null;
100         }
101         if ($DB->record_exists('user_enrolments', array('userid'=>$USER->id, 'enrolid'=>$instance->id))) {
102             //TODO: maybe we should tell them they are already enrolled, but can not access the course
103             return null;
104         }
106         if ($instance->enrolstartdate != 0 and $instance->enrolstartdate < time) {
107             //TODO: inform that we can not enrol yet
108             return null;
109         }
111         if ($instance->enrolenddate != 0 and $instance->enrolenddate > time) {
112             //TODO: inform that enrolment is not possible any more
113             return null;
114         }
116         require_once("$CFG->dirroot/enrol/self/locallib.php");
117         $form = new enrol_self_enrol_form(NULL, $instance);
118         $instanceid = optional_param('instance', 0, PARAM_INT);
120         if ($instance->id == $instanceid) {
121             if ($data = $form->get_data()) {
122                 $enrol = enrol_get_plugin('self');
123                 if ($instance->enrolperiod) {
124                     $timestart = time();
125                     $tineend   = $timestart + $instance->enrolperiod;
126                 } else {
127                     $timestart = 0;
128                     $tineend   = 0;
129                 }
131                 $this->enrol_user($instance, $USER->id, $instance->roleid, $timestart, $tineend);
132                 add_to_log($instance->courseid, 'course', 'enrol', '../enrol/users.php?id='.$instance->courseid, $instance->courseid); //there should be userid somewhere!
133                 // send welcome
134                 if ($this->get_config('sendcoursewelcomemessage')) {
135                     $this->email_welcome_message($instance, $USER);
136                 }
137             }
138         }
140         ob_start();
141         $form->display();
142         $output = ob_get_clean();
144         return $OUTPUT->box($output);
145     }
147     /**
148      * Adds enrol instance UI to course edit form
149      *
150      * @param object $instance enrol instance or null if does not exist yet
151      * @param MoodleQuickForm $mform
152      * @param object $data
153      * @param object $context context of existing course or parent category if course does not exist
154      * @return void
155      */
156     public function course_edit_form($instance, MoodleQuickForm $mform, $data, $context) {
158         $i = isset($instance->id) ? $instance->id : 0;
159         $plugin = enrol_get_plugin('self');
160         $header = $plugin->get_instance_name($instance);
161         $config = has_capability('enrol/self:config', $context);
163         $mform->addElement('header', 'enrol_self_header_'.$i, $header);
166         $options = array(ENROL_INSTANCE_ENABLED  => get_string('yes'),
167                          ENROL_INSTANCE_DISABLED => get_string('no'));
168         $mform->addElement('select', 'enrol_self_status_'.$i, get_string('status', 'enrol_self'), $options);
169         $mform->setDefault('enrol_self_status_'.$i, $this->get_config('status'));
170         $mform->setAdvanced('enrol_self_status_'.$i, $this->get_config('status_adv'));
171         if (!$config) {
172             $mform->hardFreeze('enrol_self_status_'.$i);
173         }
176         $mform->addElement('passwordunmask', 'enrol_self_password_'.$i, get_string('password', 'enrol_self'));
177         if (!$config) {
178             $mform->hardFreeze('enrol_self_password_'.$i);
179         } else {
180             $mform->disabledIf('enrol_self_password_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
181         }
184         $options = array(1 => get_string('yes'),
185                          0 => get_string('no'));
186         $mform->addElement('select', 'enrol_self_customint1_'.$i, get_string('groupkey', 'enrol_self'), $options);
187         $mform->setDefault('enrol_self_customint1_'.$i, $this->get_config('groupkey'));
188         $mform->setAdvanced('enrol_self_customint1_'.$i, $this->get_config('groupkey_adv'));
189         if (!$config) {
190             $mform->hardFreeze('enrol_self_customint1_'.$i);
191         } else {
192             $mform->disabledIf('enrol_self_customint1_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
193         }
196         if ($instance) {
197             $roles = get_default_enrol_roles($context, $instance->roleid);
198         } else {
199             $roles = get_default_enrol_roles($context, $this->get_config('roleid'));
200         }
201         $mform->addElement('select', 'enrol_self_roleid_'.$i, get_string('role', 'enrol_self'), $roles);
202         $mform->setDefault('enrol_self_roleid_'.$i, $this->get_config('roleid'));
203         $mform->setAdvanced('enrol_self_roleid_'.$i, $this->get_config('roleid_adv'));
204         if (!$config) {
205             $mform->hardFreeze('enrol_self_roleid_'.$i);
206         } else {
207             $mform->disabledIf('enrol_self_roleid_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
208         }
211         $mform->addElement('duration', 'enrol_self_enrolperiod_'.$i, get_string('enrolperiod', 'enrol_self'), array('optional' => true, 'defaultunit' => 86400));
212         $mform->setDefault('enrol_self_enrolperiod_'.$i, $this->get_config('enrolperiod'));
213         $mform->setAdvanced('enrol_self_enrolperiod_'.$i, $this->get_config('enrolperiod_adv'));
214         if (!$config) {
215             $mform->hardFreeze('enrol_self_enrolperiod_'.$i);
216         } else {
217             $mform->disabledIf('enrol_self_enrolperiod_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
218         }
221         $mform->addElement('date_selector', 'enrol_self_enrolstartdate_'.$i, get_string('enrolstartdate', 'enrol_self'), array('optional' => true));
222         $mform->setDefault('enrol_self_enrolstartdate_'.$i, 0);
223         $mform->setAdvanced('enrol_self_enrolstartdate_'.$i, 1);
224         if (!$config) {
225             $mform->hardFreeze('enrol_self_enrolstartdate_'.$i);
226         } else {
227             $mform->disabledIf('enrol_self_enrolstartdate_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
228         }
231         $mform->addElement('date_selector', 'enrol_self_enrolenddate_'.$i, get_string('enrolenddate', 'enrol_self'), array('optional' => true));
232         $mform->setDefault('enrol_self_enrolenddate_'.$i, 0);
233         $mform->setAdvanced('enrol_self_enrolenddate_'.$i, 1);
234         if (!$config) {
235             $mform->hardFreeze('enrol_self_enrolenddate_'.$i);
236         } else {
237             $mform->disabledIf('enrol_self_enrolenddate_'.$i, 'enrol_self_status_'.$i, 'noteq', ENROL_INSTANCE_ENABLED);
238         }
241         // now add all values from enrol table
242         if ($instance) {
243             foreach($instance as $key=>$val) {
244                 $data->{'enrol_self_'.$key.'_'.$i} = $val;
245             }
246         }
247     }
250     /**
251      * Validates course edit form data
252      *
253      * @param object $instance enrol instance or null if does not exist yet
254      * @param array $data
255      * @param object $context context of existing course or parent category if course does not exist
256      * @return array errors array
257      */
258     public function course_edit_validation($instance, array $data, $context) {
259         $errors = array();
261         if (!has_capability('enrol/self:config', $context)) {
262             // we are going to ignore the data later anyway, they would not be able to fix the form anyway
263             return $errors;
264         }
266         $i = isset($instance->id) ? $instance->id : 0;
268         $password = empty($data['enrol_self_password_'.$i]) ? '' : $data['enrol_self_password_'.$i];
269         $checkpassword = false;
271         if ($instance) {
272             if ($data['enrol_self_status_'.$i] == ENROL_INSTANCE_ENABLED) {
273                 if ($instance->password !== $password) {
274                     $checkpassword = true;
275                 }
276             }
277         } else {
278             if ($data['enrol_self_status_'.$i] == ENROL_INSTANCE_ENABLED) {
279                 $checkpassword = true;
280             }
281         }
283         if ($checkpassword) {
284             $require = $this->get_config('requirepassword');
285             $policy  = $this->get_config('usepasswordpolicy');
286             if ($require and empty($password)) {
287                 $errors['enrol_self_password_'.$i] = get_string('required');
288             } else if ($policy) {
289                 $errmsg = '';//prevent eclipse warning
290                 if (!check_password_policy($password, $errmsg)) {
291                     $errors['enrol_self_password_'.$i] = $errmsg;
292                 }
293             }
294         }
296         if ($data['enrol_self_status_'.$i] == ENROL_INSTANCE_ENABLED) {
297             if (!empty($data['enrol_self_enrolenddate_'.$i]) and $data['enrol_self_enrolenddate_'.$i] < $data['enrol_self_enrolstartdate_'.$i]) {
298                 $errors['enrol_self_enrolenddate_'.$i] = get_string('enrolenddaterror', 'enrol_self');
299             }
300         }
302         return $errors;
303     }
306     /**
307      * Called after updating/inserting course.
308      *
309      * @param bool $inserted true if course just inserted
310      * @param object $course
311      * @param object $data form data
312      * @return void
313      */
314     public function course_updated($inserted, $course, $data) {
315         global $DB;
317         $context = get_context_instance(CONTEXT_COURSE, $course->id);
319         if (has_capability('enrol/self:config', $context)) {
320             if ($inserted) {
321                 if (isset($data->enrol_self_status_0)) {
322                     $fields = array('status'=>$data->enrol_self_status_0);
323                     if ($fields['status'] == ENROL_INSTANCE_ENABLED) {
324                         $fields['password']       = $data->enrol_self_password_0;
325                         $fields['customint1']     = $data->enrol_self_customint1_0;
326                         $fields['roleid']         = $data->enrol_self_roleid_0;
327                         $fields['enrolperiod']    = $data->enrol_self_enrolperiod_0;
328                         $fields['enrolstartdate'] = $data->enrol_self_enrolstartdate_0;
329                         $fields['enrolenddate']   = $data->enrol_self_enrolenddate_0;
330                     } else {
331                         if ($this->get_config('requirepassword')) {
332                             // make sure some password is set after enabling this plugin
333                             $fields['password']   = generate_password(20);
334                         }
335                         $fields['customint1']     = $this->get_config('groupkey');
336                         $fields['roleid']         = $this->get_config('roleid');
337                         $fields['enrolperiod']    = $this->get_config('enrolperiod');
338                         $fields['enrolstartdate'] = 0;
339                         $fields['enrolenddate']   = 0;
340                     }
341                     $this->add_instance($course, $fields);
342                 }
344             } else {
345                 $instances = $DB->get_records('enrol', array('courseid'=>$course->id, 'enrol'=>'self'));
346                 foreach ($instances as $instance) {
347                     $i = $instance->id;
349                     if (isset($data->{'enrol_self_status_'.$i})) {
350                         $instance->status       = $data->{'enrol_self_status_'.$i};
351                         $instance->timemodified = time();
352                         if ($instance->status == ENROL_INSTANCE_ENABLED) {
353                             $instance->password       = $data->{'enrol_self_password_'.$i};
354                             $instance->customint1     = $data->{'enrol_self_customint1_'.$i};
355                             $instance->roleid         = $data->{'enrol_self_roleid_'.$i};
356                             $instance->enrolperiod    = $data->{'enrol_self_enrolperiod_'.$i};
357                             $instance->enrolstartdate = $data->{'enrol_self_enrolstartdate_'.$i};
358                             $instance->enrolenddate   = $data->{'enrol_self_enrolenddate_'.$i};
359                         }
360                         $DB->update_record('enrol', $instance);
361                     }
362                 }
363             }
365         } else {
366             if ($inserted) {
367                 if ($this->get_config('defaultenrol')) {
368                     $this->add_default_instance($course);
369                 }
370             } else {
371                 // bad luck, user can not change anything
372             }
373         }
374     }
376     /**
377      * Add new instance of enrol plugin with default settings.
378      * @param object $course
379      * @return int id of new instance
380      */
381     public function add_default_instance($course) {
382         global $DB;
384         $exists = $DB->record_exists('enrol', array('courseid'=>$course->id, 'enrol'=>'self'));
386         $fields = array('customint1'=>$this->get_config('groupkey'), 'enrolperiod'=>$this->get_config('enrolperiod', 0), 'roleid'=>$this->get_config('roleid', 0));
388         $fields['status'] = $exists ? ENROL_INSTANCE_DISABLED : $this->get_config('status');
390         if ($this->get_config('requirepassword')) {
391             $fields['password'] = generate_password(20);
392         }
394         return $this->add_instance($course, $fields);
395     }
397     /**
398      * Send welcome email to specified user
399      *
400      * @param object $instance
401      * @param object $user user record
402      * @return void
403      */
404     protected function email_welcome_message($instance, $user) {
405         global $CFG, $DB;
407         $course = $DB->get_record('course', array('id'=>$instance->courseid), '*', MUST_EXIST);
409         if (!empty($instance->customtext1)) {
410             //note: there is no gui for this yet, do we really need it?
411             $message = formaat_string($instance->customtext1);
412         } else {
413             $a = new object();
414             $a->coursename = format_string($course->fullname);
415             $a->profileurl = "$CFG->wwwroot/user/view.php?id=$user->id&course=$course->id";
416             $message = get_string("welcometocoursetext", 'enrol_self', $a);
417         }
419         $subject = get_string('welcometocourse', 'enrol_self', format_string($course->fullname));
421         $context = get_context_instance(CONTEXT_COURSE, $course->id);
422         $rusers = null;
423         if (!empty($CFG->coursecontact)) {
424             $croles = explode(',', $CFG->coursecontact);
425             $rusers = get_role_users($croles, $context, true, '', 'r.sortorder ASC, u.lastname ASC');
426         }
427         if ($rusers) {
428             $contact = reset($rusers);
429         } else {
430             $contact = get_admin();
431         }
433         email_to_user($user, $contact, $subject, $message);
434     }