Commit | Line | Data |
---|---|---|
df997f84 PS |
1 | <?php |
2 | ||
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/>. | |
17 | ||
18 | /** | |
19 | * This library includes the basic parts of enrol api. | |
20 | * It is available on each page. | |
21 | * | |
78bfb562 PS |
22 | * @package core |
23 | * @subpackage enrol | |
24 | * @copyright 2010 Petr Skoda {@link http://skodak.org} | |
25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
df997f84 PS |
26 | */ |
27 | ||
78bfb562 | 28 | defined('MOODLE_INTERNAL') || die(); |
df997f84 PS |
29 | |
30 | /** Course enrol instance enabled. (used in enrol->status) */ | |
31 | define('ENROL_INSTANCE_ENABLED', 0); | |
32 | ||
33 | /** Course enrol instance disabled, user may enter course if other enrol instance enabled. (used in enrol->status)*/ | |
34 | define('ENROL_INSTANCE_DISABLED', 1); | |
35 | ||
36 | /** User is active participant (used in user_enrolments->status)*/ | |
37 | define('ENROL_USER_ACTIVE', 0); | |
38 | ||
39 | /** User participation in course is suspended (used in user_enrolments->status) */ | |
40 | define('ENROL_USER_SUSPENDED', 1); | |
41 | ||
42 | /** Enrol info is cached for this number of seconds in require_login() */ | |
43 | define('ENROL_REQUIRE_LOGIN_CACHE_PERIOD', 1800); | |
44 | ||
34121765 PS |
45 | /** When user disappears from external source, the enrolment is completely removed */ |
46 | define('ENROL_EXT_REMOVED_UNENROL', 0); | |
47 | ||
48 | /** When user disappears from external source, the enrolment is kept as is - one way sync */ | |
49 | define('ENROL_EXT_REMOVED_KEEP', 1); | |
50 | ||
51 | /** | |
52 | * When user disappears from external source, user enrolment is suspended, roles are kept as is. | |
53 | * In some cases user needs a role with some capability to be visible in UI - suc has in gradebook, | |
54 | * assignments, etc. | |
55 | */ | |
56 | define('ENROL_EXT_REMOVED_SUSPEND', 2); | |
57 | ||
58 | /** | |
59 | * When user disappears from external source, the enrolment is suspended and roles assigned | |
60 | * by enrol instance are removed. Please note that user may "disappear" from gradebook and other areas. | |
61 | * */ | |
62 | define('ENROL_EXT_REMOVED_SUSPENDNOROLES', 3); | |
63 | ||
df997f84 PS |
64 | /** |
65 | * Returns instances of enrol plugins | |
66 | * @param bool $enable return enabled only | |
67 | * @return array of enrol plugins name=>instance | |
68 | */ | |
69 | function enrol_get_plugins($enabled) { | |
70 | global $CFG; | |
71 | ||
72 | $result = array(); | |
73 | ||
74 | if ($enabled) { | |
75 | // sorted by enabled plugin order | |
76 | $enabled = explode(',', $CFG->enrol_plugins_enabled); | |
77 | $plugins = array(); | |
78 | foreach ($enabled as $plugin) { | |
79 | $plugins[$plugin] = "$CFG->dirroot/enrol/$plugin"; | |
80 | } | |
81 | } else { | |
82 | // sorted alphabetically | |
83 | $plugins = get_plugin_list('enrol'); | |
84 | ksort($plugins); | |
85 | } | |
86 | ||
87 | foreach ($plugins as $plugin=>$location) { | |
88 | if (!file_exists("$location/lib.php")) { | |
89 | continue; | |
90 | } | |
91 | include_once("$location/lib.php"); | |
92 | $class = "enrol_{$plugin}_plugin"; | |
93 | if (!class_exists($class)) { | |
94 | continue; | |
95 | } | |
96 | ||
97 | $result[$plugin] = new $class(); | |
98 | } | |
99 | ||
100 | return $result; | |
101 | } | |
102 | ||
103 | /** | |
104 | * Returns instance of enrol plugin | |
105 | * @param string $name name of enrol plugin ('manual', 'guest', ...) | |
106 | * @return enrol_plugin | |
107 | */ | |
108 | function enrol_get_plugin($name) { | |
109 | global $CFG; | |
110 | ||
111 | if ($name !== clean_param($name, PARAM_SAFEDIR)) { | |
112 | // ignore malformed plugin names completely | |
113 | return null; | |
114 | } | |
115 | ||
116 | $location = "$CFG->dirroot/enrol/$name"; | |
117 | ||
118 | if (!file_exists("$location/lib.php")) { | |
119 | return null; | |
120 | } | |
121 | include_once("$location/lib.php"); | |
122 | $class = "enrol_{$name}_plugin"; | |
123 | if (!class_exists($class)) { | |
124 | return null; | |
125 | } | |
126 | ||
127 | return new $class(); | |
128 | } | |
129 | ||
130 | /** | |
131 | * Returns enrolment instances in given course. | |
132 | * @param int $courseid | |
133 | * @param bool $enabled | |
134 | * @return array of enrol instances | |
135 | */ | |
136 | function enrol_get_instances($courseid, $enabled) { | |
137 | global $DB, $CFG; | |
138 | ||
139 | if (!$enabled) { | |
140 | return $DB->get_records('enrol', array('courseid'=>$courseid), 'sortorder,id'); | |
141 | } | |
142 | ||
143 | $result = $DB->get_records('enrol', array('courseid'=>$courseid, 'status'=>ENROL_INSTANCE_ENABLED), 'sortorder,id'); | |
144 | ||
79721bd3 | 145 | $enabled = explode(',', $CFG->enrol_plugins_enabled); |
df997f84 PS |
146 | foreach ($result as $key=>$instance) { |
147 | if (!in_array($instance->enrol, $enabled)) { | |
148 | unset($result[$key]); | |
149 | continue; | |
150 | } | |
151 | if (!file_exists("$CFG->dirroot/enrol/$instance->enrol/lib.php")) { | |
152 | // broken plugin | |
153 | unset($result[$key]); | |
154 | continue; | |
155 | } | |
156 | } | |
157 | ||
158 | return $result; | |
159 | } | |
160 | ||
161 | /** | |
162 | * Checks if a given plugin is in the list of enabled enrolment plugins. | |
163 | * | |
164 | * @param string $enrol Enrolment plugin name | |
165 | * @return boolean Whether the plugin is enabled | |
166 | */ | |
167 | function enrol_is_enabled($enrol) { | |
168 | global $CFG; | |
169 | ||
170 | if (empty($CFG->enrol_plugins_enabled)) { | |
171 | return false; | |
172 | } | |
173 | return in_array($enrol, explode(',', $CFG->enrol_plugins_enabled)); | |
174 | } | |
175 | ||
176 | /** | |
177 | * Check all the login enrolment information for the given user object | |
178 | * by querying the enrolment plugins | |
179 | * | |
180 | * @param object $user | |
181 | * @return void | |
182 | */ | |
183 | function enrol_check_plugins($user) { | |
184 | global $CFG; | |
185 | ||
186 | if (empty($user->id) or isguestuser($user)) { | |
187 | // shortcut - there is no enrolment work for guests and not-logged-in users | |
188 | return; | |
189 | } | |
190 | ||
e384d2dc PS |
191 | if (is_siteadmin()) { |
192 | // no sync for admin user, please use admin accounts only for admin tasks like the unix root user! | |
193 | // if plugin fails on sync admins need to be able to log in | |
194 | return; | |
195 | } | |
196 | ||
df997f84 PS |
197 | static $inprogress = array(); // To prevent this function being called more than once in an invocation |
198 | ||
199 | if (!empty($inprogress[$user->id])) { | |
200 | return; | |
201 | } | |
202 | ||
203 | $inprogress[$user->id] = true; // Set the flag | |
204 | ||
205 | $enabled = enrol_get_plugins(true); | |
206 | ||
207 | foreach($enabled as $enrol) { | |
208 | $enrol->sync_user_enrolments($user); | |
209 | } | |
210 | ||
211 | unset($inprogress[$user->id]); // Unset the flag | |
212 | } | |
213 | ||
214 | /** | |
215 | * This function adds necessary enrol plugins UI into the course edit form. | |
216 | * | |
217 | * @param MoodleQuickForm $mform | |
218 | * @param object $data course edit form data | |
219 | * @param object $context context of existing course or parent category if course does not exist | |
220 | * @return void | |
221 | */ | |
222 | function enrol_course_edit_form(MoodleQuickForm $mform, $data, $context) { | |
223 | $plugins = enrol_get_plugins(true); | |
224 | if (!empty($data->id)) { | |
225 | $instances = enrol_get_instances($data->id, false); | |
226 | foreach ($instances as $instance) { | |
227 | if (!isset($plugins[$instance->enrol])) { | |
228 | continue; | |
229 | } | |
230 | $plugin = $plugins[$instance->enrol]; | |
231 | $plugin->course_edit_form($instance, $mform, $data, $context); | |
232 | } | |
233 | } else { | |
234 | foreach ($plugins as $plugin) { | |
235 | $plugin->course_edit_form(NULL, $mform, $data, $context); | |
236 | } | |
237 | } | |
238 | } | |
239 | ||
240 | /** | |
241 | * Validate course edit form data | |
242 | * | |
243 | * @param array $data raw form data | |
244 | * @param object $context context of existing course or parent category if course does not exist | |
245 | * @return array errors array | |
246 | */ | |
247 | function enrol_course_edit_validation(array $data, $context) { | |
248 | $errors = array(); | |
249 | $plugins = enrol_get_plugins(true); | |
250 | ||
251 | if (!empty($data['id'])) { | |
252 | $instances = enrol_get_instances($data['id'], false); | |
253 | foreach ($instances as $instance) { | |
254 | if (!isset($plugins[$instance->enrol])) { | |
255 | continue; | |
256 | } | |
257 | $plugin = $plugins[$instance->enrol]; | |
258 | $errors = array_merge($errors, $plugin->course_edit_validation($instance, $data, $context)); | |
259 | } | |
260 | } else { | |
261 | foreach ($plugins as $plugin) { | |
262 | $errors = array_merge($errors, $plugin->course_edit_validation(NULL, $data, $context)); | |
263 | } | |
264 | } | |
265 | ||
266 | return $errors; | |
267 | } | |
268 | ||
269 | /** | |
270 | * Update enrol instances after course edit form submission | |
271 | * @param bool $inserted true means new course added, false course already existed | |
272 | * @param object $course | |
273 | * @param object $data form data | |
274 | * @return void | |
275 | */ | |
276 | function enrol_course_updated($inserted, $course, $data) { | |
277 | global $DB, $CFG; | |
278 | ||
279 | $plugins = enrol_get_plugins(true); | |
280 | ||
281 | foreach ($plugins as $plugin) { | |
282 | $plugin->course_updated($inserted, $course, $data); | |
283 | } | |
284 | } | |
285 | ||
286 | /** | |
287 | * Add navigation nodes | |
288 | * @param navigation_node $coursenode | |
289 | * @param object $course | |
290 | * @return void | |
291 | */ | |
292 | function enrol_add_course_navigation(navigation_node $coursenode, $course) { | |
293 | ||
294 | $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); | |
295 | ||
296 | $instances = enrol_get_instances($course->id, true); | |
297 | $plugins = enrol_get_plugins(true); | |
298 | ||
299 | // we do not want to break all course pages if there is some borked enrol plugin, right? | |
300 | foreach ($instances as $k=>$instance) { | |
301 | if (!isset($plugins[$instance->enrol])) { | |
302 | unset($instances[$k]); | |
303 | } | |
304 | } | |
305 | ||
f5ce6b71 | 306 | $usersnode = $coursenode->add(get_string('users'), null, navigation_node::TYPE_CONTAINER, null, 'users'); |
df997f84 PS |
307 | |
308 | if ($course->id != SITEID) { | |
f5ce6b71 | 309 | // list all participants - allows assigning roles, groups, etc. |
df997f84 PS |
310 | if (has_capability('moodle/course:enrolreview', $coursecontext)) { |
311 | $url = new moodle_url('/enrol/users.php', array('id'=>$course->id)); | |
f5ce6b71 | 312 | $usersnode->add(get_string('enrolledusers', 'enrol'), $url, navigation_node::TYPE_SETTING, null, 'review', new pix_icon('i/users', '')); |
df997f84 PS |
313 | } |
314 | ||
315 | // manage enrol plugin instances | |
316 | if (has_capability('moodle/course:enrolconfig', $coursecontext) or has_capability('moodle/course:enrolreview', $coursecontext)) { | |
317 | $url = new moodle_url('/enrol/instances.php', array('id'=>$course->id)); | |
318 | } else { | |
319 | $url = NULL; | |
320 | } | |
f5ce6b71 | 321 | $instancesnode = $usersnode->add(get_string('enrolmentinstances', 'enrol'), $url, navigation_node::TYPE_SETTING, null, 'manageinstances'); |
df997f84 PS |
322 | |
323 | // each instance decides how to configure itself or how many other nav items are exposed | |
324 | foreach ($instances as $instance) { | |
325 | if (!isset($plugins[$instance->enrol])) { | |
326 | continue; | |
327 | } | |
328 | $plugins[$instance->enrol]->add_course_navigation($instancesnode, $instance); | |
329 | } | |
330 | ||
331 | if (!$url) { | |
332 | $instancesnode->trim_if_empty(); | |
333 | } | |
334 | } | |
335 | ||
336 | // Manage groups in this course or even frontpage | |
337 | if (($course->groupmode || !$course->groupmodeforce) && has_capability('moodle/course:managegroups', $coursecontext)) { | |
338 | $url = new moodle_url('/group/index.php', array('id'=>$course->id)); | |
339 | $usersnode->add(get_string('groups'), $url, navigation_node::TYPE_SETTING, null, 'groups', new pix_icon('i/group', '')); | |
340 | } | |
341 | ||
342 | if (has_any_capability(array( 'moodle/role:assign', 'moodle/role:safeoverride','moodle/role:override', 'moodle/role:review'), $coursecontext)) { | |
343 | // Override roles | |
344 | if (has_capability('moodle/role:review', $coursecontext)) { | |
345 | $url = new moodle_url('/admin/roles/permissions.php', array('contextid'=>$coursecontext->id)); | |
346 | } else { | |
347 | $url = NULL; | |
348 | } | |
f5ce6b71 | 349 | $permissionsnode = $usersnode->add(get_string('permissions', 'role'), $url, navigation_node::TYPE_SETTING, null, 'override'); |
df997f84 PS |
350 | |
351 | // Add assign or override roles if allowed | |
352 | if ($course->id == SITEID or (!empty($CFG->adminsassignrolesincourse) and is_siteadmin())) { | |
353 | if (has_capability('moodle/role:assign', $coursecontext)) { | |
354 | $url = new moodle_url('/admin/roles/assign.php', array('contextid'=>$coursecontext->id)); | |
f5ce6b71 | 355 | $permissionsnode->add(get_string('assignedroles', 'role'), $url, navigation_node::TYPE_SETTING, null, 'roles', new pix_icon('i/roles', '')); |
df997f84 PS |
356 | } |
357 | } | |
358 | // Check role permissions | |
359 | if (has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride','moodle/role:override', 'moodle/role:assign'), $coursecontext)) { | |
360 | $url = new moodle_url('/admin/roles/check.php', array('contextid'=>$coursecontext->id)); | |
f5ce6b71 | 361 | $permissionsnode->add(get_string('checkpermissions', 'role'), $url, navigation_node::TYPE_SETTING, null, 'permissions', new pix_icon('i/checkpermissions', '')); |
df997f84 PS |
362 | } |
363 | } | |
364 | ||
365 | // Deal somehow with users that are not enrolled but still got a role somehow | |
366 | if ($course->id != SITEID) { | |
367 | //TODO, create some new UI for role assignments at course level | |
368 | if (has_capability('moodle/role:assign', $coursecontext)) { | |
369 | $url = new moodle_url('/enrol/otherusers.php', array('id'=>$course->id)); | |
f5ce6b71 | 370 | $usersnode->add(get_string('notenrolledusers', 'enrol'), $url, navigation_node::TYPE_SETTING, null, 'otherusers', new pix_icon('i/roles', '')); |
df997f84 PS |
371 | } |
372 | } | |
373 | ||
374 | // just in case nothing was actually added | |
375 | $usersnode->trim_if_empty(); | |
376 | ||
377 | if ($course->id != SITEID) { | |
378 | // Unenrol link | |
217d0397 PS |
379 | if (is_enrolled($coursecontext)) { |
380 | foreach ($instances as $instance) { | |
381 | if (!isset($plugins[$instance->enrol])) { | |
382 | continue; | |
383 | } | |
384 | $plugin = $plugins[$instance->enrol]; | |
385 | if ($unenrollink = $plugin->get_unenrolself_link($instance)) { | |
386 | $coursenode->add(get_string('unenrolme', 'core_enrol', format_string($course->shortname)), $unenrollink, navigation_node::TYPE_SETTING, null, 'unenrolself', new pix_icon('i/user', '')); | |
387 | break; | |
388 | //TODO. deal with multiple unenrol links - not likely case, but still... | |
389 | } | |
df997f84 | 390 | } |
217d0397 PS |
391 | } else { |
392 | if (is_viewing($coursecontext)) { | |
393 | // better not show any enrol link, this is intended for managers and inspectors | |
394 | } else { | |
395 | foreach ($instances as $instance) { | |
396 | if (!isset($plugins[$instance->enrol])) { | |
397 | continue; | |
398 | } | |
399 | $plugin = $plugins[$instance->enrol]; | |
400 | if ($plugin->show_enrolme_link($instance)) { | |
401 | $url = new moodle_url('/enrol/index.php', array('id'=>$course->id)); | |
402 | $coursenode->add(get_string('enrolme', 'core_enrol', format_string($course->shortname)), $url, navigation_node::TYPE_SETTING, null, 'enrolself', new pix_icon('i/user', '')); | |
403 | break; | |
404 | } | |
405 | } | |
df997f84 PS |
406 | } |
407 | } | |
df997f84 PS |
408 | } |
409 | } | |
410 | ||
411 | /** | |
412 | * Returns list of courses current $USER is enrolled in and can access | |
413 | * | |
414 | * - $fields is an array of field names to ADD | |
415 | * so name the fields you really need, which will | |
416 | * be added and uniq'd | |
417 | * | |
418 | * @param strin|array $fields | |
419 | * @param string $sort | |
420 | * @param int $limit max number of courses | |
421 | * @return array | |
422 | */ | |
423 | function enrol_get_my_courses($fields = NULL, $sort = 'visible DESC,sortorder ASC', $limit = 0) { | |
424 | global $DB, $USER; | |
425 | ||
426 | // Guest account does not have any courses | |
427 | if (isguestuser() or !isloggedin()) { | |
428 | return(array()); | |
429 | } | |
430 | ||
431 | $basefields = array('id', 'category', 'sortorder', | |
432 | 'shortname', 'fullname', 'idnumber', | |
433 | 'startdate', 'visible', | |
434 | 'groupmode', 'groupmodeforce'); | |
435 | ||
436 | if (empty($fields)) { | |
437 | $fields = $basefields; | |
438 | } else if (is_string($fields)) { | |
439 | // turn the fields from a string to an array | |
440 | $fields = explode(',', $fields); | |
441 | $fields = array_map('trim', $fields); | |
442 | $fields = array_unique(array_merge($basefields, $fields)); | |
443 | } else if (is_array($fields)) { | |
444 | $fields = array_unique(array_merge($basefields, $fields)); | |
445 | } else { | |
446 | throw new coding_exception('Invalid $fileds parameter in enrol_get_my_courses()'); | |
447 | } | |
448 | if (in_array('*', $fields)) { | |
449 | $fields = array('*'); | |
450 | } | |
451 | ||
452 | $orderby = ""; | |
453 | $sort = trim($sort); | |
454 | if (!empty($sort)) { | |
455 | $rawsorts = explode(',', $sort); | |
456 | $sorts = array(); | |
457 | foreach ($rawsorts as $rawsort) { | |
458 | $rawsort = trim($rawsort); | |
459 | if (strpos($rawsort, 'c.') === 0) { | |
460 | $rawsort = substr($rawsort, 2); | |
461 | } | |
462 | $sorts[] = trim($rawsort); | |
463 | } | |
464 | $sort = 'c.'.implode(',c.', $sorts); | |
465 | $orderby = "ORDER BY $sort"; | |
466 | } | |
467 | ||
468 | $wheres = array("c.id <> :siteid"); | |
469 | $params = array('siteid'=>SITEID); | |
470 | ||
471 | if (isset($USER->loginascontext) and $USER->loginascontext->contextlevel == CONTEXT_COURSE) { | |
472 | // list _only_ this course - anything else is asking for trouble... | |
473 | $wheres[] = "courseid = :loginas"; | |
474 | $params['loginas'] = $USER->loginascontext->instanceid; | |
475 | } | |
476 | ||
477 | $coursefields = 'c.' .join(',c.', $fields); | |
478 | list($ccselect, $ccjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx'); | |
4129338c | 479 | $wheres = implode(" AND ", $wheres); |
df997f84 | 480 | |
4129338c PS |
481 | //note: we can not use DISTINCT + text fields due to Oracle and MS limitations, that is why we have the subselect there |
482 | $sql = "SELECT $coursefields $ccselect | |
df997f84 | 483 | FROM {course} c |
4129338c PS |
484 | JOIN (SELECT DISTINCT e.courseid |
485 | FROM {enrol} e | |
486 | JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = :userid) | |
487 | WHERE ue.status = :active AND e.status = :enabled AND ue.timestart < :now1 AND (ue.timeend = 0 OR ue.timeend > :now2) | |
488 | ) en ON (en.courseid = c.id) | |
df997f84 | 489 | $ccjoin |
4129338c | 490 | WHERE $wheres |
df997f84 PS |
491 | $orderby"; |
492 | $params['userid'] = $USER->id; | |
493 | $params['active'] = ENROL_USER_ACTIVE; | |
494 | $params['enabled'] = ENROL_INSTANCE_ENABLED; | |
495 | $params['now1'] = round(time(), -2); // improves db caching | |
496 | $params['now2'] = $params['now1']; | |
497 | ||
498 | $courses = $DB->get_records_sql($sql, $params, 0, $limit); | |
499 | ||
500 | // preload contexts and check visibility | |
501 | foreach ($courses as $id=>$course) { | |
502 | context_instance_preload($course); | |
503 | if (!$course->visible) { | |
504 | if (!$context = get_context_instance(CONTEXT_COURSE, $id)) { | |
55880bdd | 505 | unset($courses[$id]); |
df997f84 PS |
506 | continue; |
507 | } | |
508 | if (!has_capability('moodle/course:viewhiddencourses', $context)) { | |
55880bdd | 509 | unset($courses[$id]); |
df997f84 PS |
510 | continue; |
511 | } | |
512 | } | |
513 | $courses[$id] = $course; | |
514 | } | |
515 | ||
516 | //wow! Is that really all? :-D | |
517 | ||
518 | return $courses; | |
519 | } | |
520 | ||
521 | /** | |
522 | * Returns list of courses user is enrolled into. | |
523 | * | |
524 | * - $fields is an array of fieldnames to ADD | |
525 | * so name the fields you really need, which will | |
526 | * be added and uniq'd | |
527 | * | |
528 | * @param int $userid | |
529 | * @param bool $onlyactive return only active enrolments in courses user may see | |
530 | * @param strin|array $fields | |
531 | * @param string $sort | |
532 | * @return array | |
533 | */ | |
534 | function enrol_get_users_courses($userid, $onlyactive = false, $fields = NULL, $sort = 'visible DESC,sortorder ASC') { | |
535 | global $DB; | |
536 | ||
537 | // Guest account does not have any courses | |
87163782 | 538 | if (isguestuser($userid) or empty($userid)) { |
df997f84 PS |
539 | return(array()); |
540 | } | |
541 | ||
542 | $basefields = array('id', 'category', 'sortorder', | |
543 | 'shortname', 'fullname', 'idnumber', | |
544 | 'startdate', 'visible', | |
545 | 'groupmode', 'groupmodeforce'); | |
546 | ||
547 | if (empty($fields)) { | |
548 | $fields = $basefields; | |
549 | } else if (is_string($fields)) { | |
550 | // turn the fields from a string to an array | |
551 | $fields = explode(',', $fields); | |
552 | $fields = array_map('trim', $fields); | |
553 | $fields = array_unique(array_merge($basefields, $fields)); | |
554 | } else if (is_array($fields)) { | |
555 | $fields = array_unique(array_merge($basefields, $fields)); | |
556 | } else { | |
557 | throw new coding_exception('Invalid $fileds parameter in enrol_get_my_courses()'); | |
558 | } | |
559 | if (in_array('*', $fields)) { | |
560 | $fields = array('*'); | |
561 | } | |
562 | ||
563 | $orderby = ""; | |
564 | $sort = trim($sort); | |
565 | if (!empty($sort)) { | |
566 | $rawsorts = explode(',', $sort); | |
567 | $sorts = array(); | |
568 | foreach ($rawsorts as $rawsort) { | |
569 | $rawsort = trim($rawsort); | |
570 | if (strpos($rawsort, 'c.') === 0) { | |
571 | $rawsort = substr($rawsort, 2); | |
572 | } | |
573 | $sorts[] = trim($rawsort); | |
574 | } | |
575 | $sort = 'c.'.implode(',c.', $sorts); | |
576 | $orderby = "ORDER BY $sort"; | |
577 | } | |
578 | ||
df997f84 PS |
579 | $params = array('siteid'=>SITEID); |
580 | ||
581 | if ($onlyactive) { | |
4129338c | 582 | $subwhere = "WHERE ue.status = :active AND e.status = :enabled AND ue.timestart < :now1 AND (ue.timeend = 0 OR ue.timeend > :now2)"; |
df997f84 PS |
583 | $params['now1'] = round(time(), -2); // improves db caching |
584 | $params['now2'] = $params['now1']; | |
585 | $params['active'] = ENROL_USER_ACTIVE; | |
586 | $params['enabled'] = ENROL_INSTANCE_ENABLED; | |
4129338c PS |
587 | } else { |
588 | $subwhere = ""; | |
df997f84 PS |
589 | } |
590 | ||
591 | $coursefields = 'c.' .join(',c.', $fields); | |
592 | list($ccselect, $ccjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx'); | |
df997f84 | 593 | |
4129338c PS |
594 | //note: we can not use DISTINCT + text fields due to Oracle and MS limitations, that is why we have the subselect there |
595 | $sql = "SELECT $coursefields $ccselect | |
df997f84 | 596 | FROM {course} c |
4129338c PS |
597 | JOIN (SELECT DISTINCT e.courseid |
598 | FROM {enrol} e | |
599 | JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = :userid) | |
600 | $subwhere | |
601 | ) en ON (en.courseid = c.id) | |
df997f84 | 602 | $ccjoin |
4129338c | 603 | WHERE c.id <> :siteid |
df997f84 | 604 | $orderby"; |
87163782 | 605 | $params['userid'] = $userid; |
df997f84 PS |
606 | |
607 | $courses = $DB->get_records_sql($sql, $params); | |
608 | ||
609 | // preload contexts and check visibility | |
610 | foreach ($courses as $id=>$course) { | |
611 | context_instance_preload($course); | |
612 | if ($onlyactive) { | |
613 | if (!$course->visible) { | |
614 | if (!$context = get_context_instance(CONTEXT_COURSE, $id)) { | |
615 | unset($course[$id]); | |
616 | continue; | |
617 | } | |
618 | if (!has_capability('moodle/course:viewhiddencourses', $context, $userid)) { | |
619 | unset($course[$id]); | |
620 | continue; | |
621 | } | |
622 | } | |
623 | } | |
624 | $courses[$id] = $course; | |
625 | } | |
626 | ||
627 | //wow! Is that really all? :-D | |
628 | ||
629 | return $courses; | |
630 | ||
631 | } | |
632 | ||
633 | /** | |
634 | * Called when user is about to be deleted. | |
635 | * @param object $user | |
636 | * @return void | |
637 | */ | |
638 | function enrol_user_delete($user) { | |
639 | global $DB; | |
640 | ||
641 | $plugins = enrol_get_plugins(true); | |
642 | foreach ($plugins as $plugin) { | |
643 | $plugin->user_delete($user); | |
644 | } | |
645 | ||
646 | // force cleanup of all broken enrolments | |
647 | $DB->delete_records('user_enrolments', array('userid'=>$user->id)); | |
648 | } | |
649 | ||
650 | /** | |
651 | * Try to enrol user via default internal auth plugin. | |
652 | * | |
653 | * For now this is always using the manual enrol plugin... | |
654 | * | |
655 | * @param $courseid | |
656 | * @param $userid | |
657 | * @param $roleid | |
658 | * @param $timestart | |
659 | * @param $timeend | |
660 | * @return bool success | |
661 | */ | |
662 | function enrol_try_internal_enrol($courseid, $userid, $roleid = null, $timestart = 0, $timeend = 0) { | |
663 | global $DB; | |
664 | ||
665 | //note: this is hardcoded to manual plugin for now | |
666 | ||
667 | if (!enrol_is_enabled('manual')) { | |
668 | return false; | |
669 | } | |
670 | ||
671 | if (!$enrol = enrol_get_plugin('manual')) { | |
672 | return false; | |
673 | } | |
674 | if (!$instances = $DB->get_records('enrol', array('enrol'=>'manual', 'courseid'=>$courseid, 'status'=>ENROL_INSTANCE_ENABLED), 'sortorder,id ASC')) { | |
675 | return false; | |
676 | } | |
677 | $instance = reset($instances); | |
678 | ||
679 | $enrol->enrol_user($instance, $userid, $roleid, $timestart, $timeend); | |
680 | ||
681 | return true; | |
682 | } | |
683 | ||
684 | /** | |
685 | * All enrol plugins should be based on this class, | |
686 | * this is also the main source of documentation. | |
687 | */ | |
688 | abstract class enrol_plugin { | |
689 | protected $config = null; | |
690 | ||
691 | /** | |
692 | * Returns name of this enrol plugin | |
693 | * @return string | |
694 | */ | |
695 | public function get_name() { | |
696 | // second word in class is always enrol name | |
697 | $words = explode('_', get_class($this)); | |
698 | return $words[1]; | |
699 | } | |
700 | ||
701 | /** | |
702 | * Returns localised name of enrol instance | |
703 | * | |
704 | * @param object $instance (null is accepted too) | |
705 | * @return string | |
706 | */ | |
707 | public function get_instance_name($instance) { | |
708 | if (empty($instance->name)) { | |
709 | $enrol = $this->get_name(); | |
710 | return get_string('pluginname', 'enrol_'.$enrol); | |
711 | } else { | |
712 | return format_string($instance->name); | |
713 | } | |
714 | } | |
715 | ||
716 | /** | |
717 | * Makes sure config is loaded and cached. | |
718 | * @return void | |
719 | */ | |
720 | protected function load_config() { | |
721 | if (!isset($this->config)) { | |
722 | $name = $this->get_name(); | |
723 | if (!$config = get_config("enrol_$name")) { | |
724 | $config = new object(); | |
725 | } | |
726 | $this->config = $config; | |
727 | } | |
728 | } | |
729 | ||
730 | /** | |
731 | * Returns plugin config value | |
732 | * @param string $name | |
733 | * @param string $default value if config does not exist yet | |
734 | * @return string value or default | |
735 | */ | |
736 | public function get_config($name, $default = NULL) { | |
737 | $this->load_config(); | |
738 | return isset($this->config->$name) ? $this->config->$name : $default; | |
739 | } | |
740 | ||
741 | /** | |
742 | * Sets plugin config value | |
743 | * @param string $name name of config | |
744 | * @param string $value string config value, null means delete | |
745 | * @return string value | |
746 | */ | |
747 | public function set_config($name, $value) { | |
47811589 | 748 | $pluginname = $this->get_name(); |
df997f84 PS |
749 | $this->load_config(); |
750 | if ($value === NULL) { | |
751 | unset($this->config->$name); | |
752 | } else { | |
753 | $this->config->$name = $value; | |
754 | } | |
47811589 | 755 | set_config($name, $value, "enrol_$pluginname"); |
df997f84 PS |
756 | } |
757 | ||
758 | /** | |
759 | * Does this plugin assign protected roles are can they be manually removed? | |
760 | * @return bool - false means anybody may tweak roles, it does not use itemid and component when assigning roles | |
761 | */ | |
762 | public function roles_protected() { | |
763 | return true; | |
764 | } | |
765 | ||
91b99e80 PS |
766 | /** |
767 | * Does this plugin allow manual enrolments? | |
768 | * | |
769 | * @param stdClass $instance course enrol instance | |
770 | * All plugins allowing this must implement 'enrol/xxx:enrol' capability | |
771 | * | |
772 | * @return bool - true means user with 'enrol/xxx:enrol' may enrol others freely, trues means nobody may add more enrolments manually | |
773 | */ | |
774 | public function allow_enrol(stdClass $instance) { | |
775 | return false; | |
776 | } | |
777 | ||
df997f84 PS |
778 | /** |
779 | * Does this plugin allow manual unenrolments? | |
780 | * | |
781 | * @param stdClass $instance course enrol instance | |
91b99e80 | 782 | * All plugins allowing this must implement 'enrol/xxx:unenrol' capability |
df997f84 | 783 | * |
91b99e80 | 784 | * @return bool - true means user with 'enrol/xxx:unenrol' may unenrol others freely, trues means nobody may touch user_enrolments |
df997f84 PS |
785 | */ |
786 | public function allow_unenrol(stdClass $instance) { | |
787 | return false; | |
788 | } | |
789 | ||
790 | /** | |
791 | * Does this plugin allow manual changes in user_enrolments table? | |
792 | * | |
91b99e80 | 793 | * All plugins allowing this must implement 'enrol/xxx:manage' capability |
df997f84 PS |
794 | * |
795 | * @param stdClass $instance course enrol instance | |
796 | * @return bool - true means it is possible to change enrol period and status in user_enrolments table | |
797 | */ | |
798 | public function allow_manage(stdClass $instance) { | |
799 | return false; | |
800 | } | |
801 | ||
217d0397 PS |
802 | /** |
803 | * Does this plugin support some way to user to self enrol? | |
804 | * | |
805 | * @param stdClass $instance course enrol instance | |
806 | * | |
807 | * @return bool - true means show "Enrol me in this course" link in course UI | |
808 | */ | |
809 | public function show_enrolme_link(stdClass $instance) { | |
810 | return false; | |
811 | } | |
812 | ||
df997f84 PS |
813 | /** |
814 | * Attempt to automatically enrol current user in course without any interaction, | |
815 | * calling code has to make sure the plugin and instance are active. | |
816 | * | |
817 | * @param stdClass $instance course enrol instance | |
818 | * @param stdClass $user record | |
819 | * @return bool|int false means not enrolled, integer means timeend | |
820 | */ | |
821 | public function try_autoenrol(stdClass $instance) { | |
822 | global $USER; | |
823 | ||
824 | return false; | |
825 | } | |
826 | ||
827 | /** | |
828 | * Attempt to automatically gain temporary guest access to course, | |
829 | * calling code has to make sure the plugin and instance are active. | |
830 | * | |
831 | * @param stdClass $instance course enrol instance | |
832 | * @param stdClass $user record | |
833 | * @return bool|int false means no guest access, integer means timeend | |
834 | */ | |
835 | public function try_guestaccess(stdClass $instance) { | |
836 | global $USER; | |
837 | ||
838 | return false; | |
839 | } | |
840 | ||
841 | /** | |
842 | * Enrol user into course via enrol instance. | |
843 | * | |
844 | * @param stdClass $instance | |
845 | * @param int $userid | |
846 | * @param int $roleid optional role id | |
2a6dcb72 PS |
847 | * @param int $timestart 0 means unknown |
848 | * @param int $timeend 0 means forever | |
df997f84 PS |
849 | * @return void |
850 | */ | |
851 | public function enrol_user(stdClass $instance, $userid, $roleid = null, $timestart = 0, $timeend = 0) { | |
852 | global $DB, $USER, $CFG; // CFG necessary!!! | |
853 | ||
854 | if ($instance->courseid == SITEID) { | |
855 | throw new coding_exception('invalid attempt to enrol into frontpage course!'); | |
856 | } | |
857 | ||
858 | $name = $this->get_name(); | |
859 | $courseid = $instance->courseid; | |
860 | ||
861 | if ($instance->enrol !== $name) { | |
862 | throw new coding_exception('invalid enrol instance!'); | |
863 | } | |
864 | $context = get_context_instance(CONTEXT_COURSE, $instance->courseid, MUST_EXIST); | |
865 | ||
866 | $inserted = false; | |
867 | if ($ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) { | |
868 | if ($ue->timestart != $timestart or $ue->timeend != $timeend) { | |
869 | $ue->timestart = $timestart; | |
870 | $ue->timeend = $timeend; | |
871 | $ue->modifier = $USER->id; | |
872 | $ue->timemodified = time(); | |
873 | $DB->update_record('user_enrolments', $ue); | |
874 | } | |
875 | } else { | |
876 | $ue = new object(); | |
877 | $ue->enrolid = $instance->id; | |
878 | $ue->status = ENROL_USER_ACTIVE; | |
879 | $ue->userid = $userid; | |
880 | $ue->timestart = $timestart; | |
881 | $ue->timeend = $timeend; | |
882 | $ue->modifier = $USER->id; | |
2a6dcb72 PS |
883 | $ue->timecreated = time(); |
884 | $ue->timemodified = $ue->timecreated; | |
df997f84 PS |
885 | $ue->id = $DB->insert_record('user_enrolments', $ue); |
886 | ||
887 | $inserted = true; | |
888 | } | |
889 | ||
890 | if ($roleid) { | |
891 | if ($this->roles_protected()) { | |
892 | role_assign($roleid, $userid, $context->id, 'enrol_'.$name, $instance->id); | |
893 | } else { | |
894 | role_assign($roleid, $userid, $context->id); | |
895 | } | |
896 | } | |
897 | ||
898 | if ($inserted) { | |
899 | // add extra info and trigger event | |
900 | $ue->courseid = $courseid; | |
901 | $ue->enrol = $name; | |
902 | events_trigger('user_enrolled', $ue); | |
903 | } | |
904 | ||
905 | // reset primitive require_login() caching | |
906 | if ($userid == $USER->id) { | |
907 | if (isset($USER->enrol['enrolled'][$courseid])) { | |
908 | unset($USER->enrol['enrolled'][$courseid]); | |
909 | } | |
910 | if (isset($USER->enrol['tempguest'][$courseid])) { | |
911 | unset($USER->enrol['tempguest'][$courseid]); | |
912 | $USER->access = remove_temp_roles($context, $USER->access); | |
913 | } | |
914 | } | |
915 | } | |
916 | ||
917 | /** | |
918 | * Store user_enrolments changes and trigger event. | |
919 | * | |
920 | * @param object $ue | |
921 | * @param int $user id | |
922 | * @param int $status | |
923 | * @param int $timestart | |
924 | * @param int $timeend | |
925 | * @return void | |
926 | */ | |
927 | public function update_user_enrol(stdClass $instance, $userid, $status = NULL, $timestart = NULL, $timeend = NULL) { | |
928 | global $DB, $USER; | |
929 | ||
930 | $name = $this->get_name(); | |
931 | ||
932 | if ($instance->enrol !== $name) { | |
933 | throw new coding_exception('invalid enrol instance!'); | |
934 | } | |
935 | ||
936 | if (!$ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) { | |
937 | // weird, user not enrolled | |
938 | return; | |
939 | } | |
940 | ||
941 | $modified = false; | |
942 | if (isset($status) and $ue->status != $status) { | |
943 | $ue->status = $status; | |
944 | $modified = true; | |
945 | } | |
946 | if (isset($timestart) and $ue->timestart != $timestart) { | |
947 | $ue->timestart = $timestart; | |
948 | $modified = true; | |
949 | } | |
950 | if (isset($timeend) and $ue->timeend != $timeend) { | |
951 | $ue->timeend = $timeend; | |
952 | $modified = true; | |
953 | } | |
954 | ||
955 | if (!$modified) { | |
956 | // no change | |
957 | return; | |
958 | } | |
959 | ||
960 | $ue->modifierid = $USER->id; | |
961 | $DB->update_record('user_enrolments', $ue); | |
962 | ||
963 | // trigger event | |
964 | $ue->courseid = $instance->courseid; | |
965 | $ue->enrol = $instance->name; | |
966 | events_trigger('user_unenrol_modified', $ue); | |
967 | } | |
968 | ||
969 | /** | |
970 | * Unenrol user from course, | |
971 | * the last unenrolment removes all remaining roles. | |
972 | * | |
973 | * @param stdClass $instance | |
974 | * @param int $userid | |
975 | * @return void | |
976 | */ | |
977 | public function unenrol_user(stdClass $instance, $userid) { | |
978 | global $CFG, $USER, $DB; | |
979 | ||
980 | $name = $this->get_name(); | |
981 | $courseid = $instance->courseid; | |
982 | ||
983 | if ($instance->enrol !== $name) { | |
984 | throw new coding_exception('invalid enrol instance!'); | |
985 | } | |
986 | $context = get_context_instance(CONTEXT_COURSE, $instance->courseid, MUST_EXIST); | |
987 | ||
988 | if (!$ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) { | |
989 | // weird, user not enrolled | |
990 | return; | |
991 | } | |
992 | ||
993 | role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_'.$name, 'itemid'=>$instance->id)); | |
994 | $DB->delete_records('user_enrolments', array('id'=>$ue->id)); | |
995 | ||
996 | // add extra info and trigger event | |
997 | $ue->courseid = $courseid; | |
998 | $ue->enrol = $name; | |
999 | ||
1000 | $sql = "SELECT 'x' | |
1001 | FROM {user_enrolments} ue | |
1002 | JOIN {enrol} e ON (e.id = ue.enrolid) | |
1003 | WHERE ue.userid = :userid AND e.courseid = :courseid"; | |
1004 | if ($DB->record_exists_sql($sql, array('userid'=>$userid, 'courseid'=>$courseid))) { | |
1005 | $ue->lastenrol = false; | |
1006 | events_trigger('user_unenrolled', $ue); | |
1007 | // user still has some enrolments, no big cleanup yet | |
1008 | } else { | |
1009 | // the big cleanup IS necessary! | |
1010 | ||
1011 | require_once("$CFG->dirroot/group/lib.php"); | |
1012 | require_once("$CFG->libdir/gradelib.php"); | |
1013 | ||
1014 | // remove all remaining roles | |
1015 | role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id), true, false); | |
1016 | ||
1017 | //clean up ALL invisible user data from course if this is the last enrolment - groups, grades, etc. | |
1018 | groups_delete_group_members($courseid, $userid); | |
1019 | ||
1020 | grade_user_unenrol($courseid, $userid); | |
1021 | ||
1022 | $DB->delete_records('user_lastaccess', array('userid'=>$userid, 'courseid'=>$courseid)); | |
1023 | ||
7d2800fb | 1024 | $ue->lastenrol = true; // means user not enrolled any more |
df997f84 PS |
1025 | events_trigger('user_unenrolled', $ue); |
1026 | } | |
1027 | // reset primitive require_login() caching | |
1028 | if ($userid == $USER->id) { | |
1029 | if (isset($USER->enrol['enrolled'][$courseid])) { | |
1030 | unset($USER->enrol['enrolled'][$courseid]); | |
1031 | } | |
1032 | if (isset($USER->enrol['tempguest'][$courseid])) { | |
1033 | unset($USER->enrol['tempguest'][$courseid]); | |
1034 | $USER->access = remove_temp_roles($context, $USER->access); | |
1035 | } | |
1036 | } | |
1037 | } | |
1038 | ||
1039 | /** | |
1040 | * Forces synchronisation of user enrolments. | |
1041 | * | |
1042 | * This is important especially for external enrol plugins, | |
1043 | * this function is called for all enabled enrol plugins | |
1044 | * right after every user login. | |
1045 | * | |
1046 | * @param object $user user record | |
1047 | * @return void | |
1048 | */ | |
1049 | public function sync_user_enrolments($user) { | |
1050 | // override if necessary | |
1051 | } | |
1052 | ||
1053 | /** | |
1054 | * Returns link to page which may be used to add new instance of enrolment plugin in course. | |
1055 | * @param int $courseid | |
1056 | * @return moodle_url page url | |
1057 | */ | |
1058 | public function get_candidate_link($courseid) { | |
1059 | // override for most plugins, check if instance already exists in cases only one instance is supported | |
1060 | return NULL; | |
1061 | } | |
1062 | ||
1063 | /** | |
1064 | * Is it possible to delete enrol instance via standard UI? | |
1065 | * | |
1066 | * @param object $instance | |
1067 | * @return bool | |
1068 | */ | |
1069 | public function instance_deleteable($instance) { | |
1070 | return true; | |
1071 | } | |
1072 | ||
1073 | /** | |
1074 | * Returns link to manual enrol UI if exists. | |
1075 | * Does the access control tests automatically. | |
1076 | * | |
1077 | * @param object $instance | |
1078 | * @return moodle_url | |
1079 | */ | |
1080 | public function get_manual_enrol_link($instance) { | |
1081 | return NULL; | |
1082 | } | |
1083 | ||
1084 | /** | |
1085 | * Returns list of unenrol links for all enrol instances in course. | |
1086 | * | |
217d0397 PS |
1087 | * @param int $instance |
1088 | * @return moodle_url or NULL if self unernolmnet not supported | |
df997f84 PS |
1089 | */ |
1090 | public function get_unenrolself_link($instance) { | |
1091 | global $USER, $CFG, $DB; | |
1092 | ||
1093 | $name = $this->get_name(); | |
1094 | if ($instance->enrol !== $name) { | |
1095 | throw new coding_exception('invalid enrol instance!'); | |
1096 | } | |
1097 | ||
1098 | if ($instance->courseid == SITEID) { | |
1099 | return NULL; | |
1100 | } | |
1101 | ||
1102 | if (!enrol_is_enabled($name)) { | |
1103 | return NULL; | |
1104 | } | |
1105 | ||
1106 | if ($instance->status != ENROL_INSTANCE_ENABLED) { | |
1107 | return NULL; | |
1108 | } | |
1109 | ||
df997f84 PS |
1110 | if (!file_exists("$CFG->dirroot/enrol/$name/unenrolself.php")) { |
1111 | return NULL; | |
1112 | } | |
1113 | ||
217d0397 PS |
1114 | $context = get_context_instance(CONTEXT_COURSE, $instance->courseid, MUST_EXIST); |
1115 | ||
df997f84 PS |
1116 | if (!has_capability("enrol/$name:unenrolself", $context)) { |
1117 | return NULL; | |
1118 | } | |
1119 | ||
1120 | if (!$DB->record_exists('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$USER->id, 'status'=>ENROL_USER_ACTIVE))) { | |
1121 | return NULL; | |
1122 | } | |
1123 | ||
1124 | return new moodle_url("/enrol/$name/unenrolself.php", array('enrolid'=>$instance->id));; | |
1125 | } | |
1126 | ||
1127 | /** | |
1128 | * Adds enrol instance UI to course edit form | |
1129 | * | |
1130 | * @param object $instance enrol instance or null if does not exist yet | |
1131 | * @param MoodleQuickForm $mform | |
1132 | * @param object $data | |
1133 | * @param object $context context of existing course or parent category if course does not exist | |
1134 | * @return void | |
1135 | */ | |
1136 | public function course_edit_form($instance, MoodleQuickForm $mform, $data, $context) { | |
1137 | // override - usually at least enable/disable switch, has to add own form header | |
1138 | } | |
1139 | ||
1140 | /** | |
1141 | * Validates course edit form data | |
1142 | * | |
1143 | * @param object $instance enrol instance or null if does not exist yet | |
1144 | * @param array $data | |
1145 | * @param object $context context of existing course or parent category if course does not exist | |
1146 | * @return array errors array | |
1147 | */ | |
1148 | public function course_edit_validation($instance, array $data, $context) { | |
1149 | return array(); | |
1150 | } | |
1151 | ||
1152 | /** | |
1153 | * Called after updating/inserting course. | |
1154 | * | |
1155 | * @param bool $inserted true if course just inserted | |
1156 | * @param object $course | |
1157 | * @param object $data form data | |
1158 | * @return void | |
1159 | */ | |
1160 | public function course_updated($inserted, $course, $data) { | |
1161 | // override if settings on course edit page or some automatic sync needed | |
1162 | } | |
1163 | ||
1164 | /** | |
1165 | * Add new instance of enrol plugin settings. | |
1166 | * @param object $course | |
1167 | * @param array instance fields | |
1168 | * @return int id of new instance | |
1169 | */ | |
1170 | public function add_instance($course, array $fields = NULL) { | |
1171 | global $DB; | |
1172 | ||
1173 | if ($course->id == SITEID) { | |
1174 | throw new coding_exception('Invalid request to add enrol instance to frontpage.'); | |
1175 | } | |
1176 | ||
1177 | $instance = new object(); | |
1178 | $instance->enrol = $this->get_name(); | |
1179 | $instance->status = ENROL_INSTANCE_ENABLED; | |
1180 | $instance->courseid = $course->id; | |
1181 | $instance->enrolstartdate = 0; | |
1182 | $instance->enrolenddate = 0; | |
1183 | $instance->timemodified = time(); | |
1184 | $instance->timecreated = $instance->timemodified; | |
1185 | $instance->sortorder = $DB->get_field('enrol', 'COALESCE(MAX(sortorder), -1) + 1', array('courseid'=>$course->id)); | |
1186 | ||
1187 | $fields = (array)$fields; | |
1188 | unset($fields['enrol']); | |
1189 | unset($fields['courseid']); | |
1190 | unset($fields['sortorder']); | |
1191 | foreach($fields as $field=>$value) { | |
1192 | $instance->$field = $value; | |
1193 | } | |
1194 | ||
1195 | return $DB->insert_record('enrol', $instance); | |
1196 | } | |
1197 | ||
1198 | /** | |
1199 | * Add new instance of enrol plugin with default settings, | |
1200 | * called when adding new instance manually or when adding new course. | |
1201 | * | |
1202 | * Not all plugins support this. | |
1203 | * | |
1204 | * @param object $course | |
1205 | * @return int id of new instance or null if no default supported | |
1206 | */ | |
1207 | public function add_default_instance($course) { | |
1208 | return null; | |
1209 | } | |
1210 | ||
1211 | /** | |
1212 | * Delete course enrol plugin instance, unenrol all users. | |
1213 | * @param object $instance | |
1214 | * @return void | |
1215 | */ | |
1216 | public function delete_instance($instance) { | |
1217 | global $DB; | |
1218 | ||
1219 | $name = $this->get_name(); | |
1220 | if ($instance->enrol !== $name) { | |
1221 | throw new coding_exception('invalid enrol instance!'); | |
1222 | } | |
1223 | ||
1224 | //first unenrol all users | |
1225 | $participants = $DB->get_recordset('user_enrolments', array('enrolid'=>$instance->id)); | |
1226 | foreach ($participants as $participant) { | |
1227 | $this->unenrol_user($instance, $participant->userid); | |
1228 | } | |
1229 | $participants->close(); | |
1230 | ||
1231 | // now clean up all remainders that were not removed correctly | |
1232 | $DB->delete_records('role_assignments', array('itemid'=>$instance->id, 'component'=>$name)); | |
1233 | $DB->delete_records('user_enrolments', array('enrolid'=>$instance->id)); | |
1234 | ||
1235 | // finally drop the enrol row | |
1236 | $DB->delete_records('enrol', array('id'=>$instance->id)); | |
1237 | } | |
1238 | ||
1239 | /** | |
1240 | * Creates course enrol form, checks if form submitted | |
1241 | * and enrols user if necessary. It can also redirect. | |
1242 | * | |
1243 | * @param stdClass $instance | |
1244 | * @return string html text, usually a form in a text box | |
1245 | */ | |
1246 | public function enrol_page_hook(stdClass $instance) { | |
1247 | return null; | |
1248 | } | |
1249 | ||
1250 | /** | |
1251 | * Adds navigation links into course admin block. | |
1252 | * | |
1253 | * By defaults looks for manage links only. | |
1254 | * | |
1255 | * @param navigation_node $instancesnode | |
1256 | * @param object $instance | |
1257 | * @return moodle_url; | |
1258 | */ | |
1259 | public function add_course_navigation($instancesnode, stdClass $instance) { | |
1260 | if ($managelink = $this->get_manage_link($instance)) { | |
1261 | $instancesnode->add($this->get_instance_name($instance), $managelink, navigation_node::TYPE_SETTING); | |
1262 | } | |
1263 | } | |
1264 | ||
1265 | /** | |
1266 | * Returns enrolment instance manage link. | |
1267 | * | |
1268 | * By defaults looks for manage.php file and tests for manage capability. | |
1269 | * | |
1270 | * @param object $instance | |
1271 | * @return moodle_url; | |
1272 | */ | |
1273 | public function get_manage_link($instance) { | |
1274 | global $CFG, $DB; | |
1275 | ||
1276 | $name = $this->get_name(); | |
1277 | ||
1278 | if ($instance->enrol !== $name) { | |
1279 | throw new coding_exception('Invalid enrol instance type!'); | |
1280 | } | |
1281 | ||
1282 | if (!file_exists("$CFG->dirroot/enrol/$name/manage.php")) { | |
1283 | return NULL; | |
1284 | } | |
1285 | ||
1286 | if ($instance->courseid == SITEID) { | |
1287 | // no enrolments on the frontpage, only roles there allowed | |
1288 | return NULL; | |
1289 | } | |
1290 | ||
1291 | $context = get_context_instance(CONTEXT_COURSE, $instance->courseid); | |
1292 | if (!has_capability('enrol/'.$name.':manage', $context)) { | |
1293 | return NULL; | |
1294 | } | |
1295 | ||
1296 | return new moodle_url("/enrol/$name/manage.php", array('enrolid'=>$instance->id)); | |
1297 | } | |
1298 | ||
1299 | /** | |
1300 | * Reads version.php and determines if it is necessary | |
1301 | * to execute the cron job now. | |
1302 | * @return bool | |
1303 | */ | |
1304 | public function is_cron_required() { | |
1305 | global $CFG; | |
1306 | ||
1307 | $name = $this->get_name(); | |
1308 | $versionfile = "$CFG->dirroot/enrol/$name/version.php"; | |
1309 | $plugin = new object(); | |
1310 | include($versionfile); | |
1311 | if (empty($plugin->cron)) { | |
1312 | return false; | |
1313 | } | |
1314 | $lastexecuted = $this->get_config('lastcron', 0); | |
1315 | if ($lastexecuted + $plugin->cron < time()) { | |
1316 | return true; | |
1317 | } else { | |
1318 | return false; | |
1319 | } | |
1320 | } | |
1321 | ||
1322 | /** | |
1323 | * Called for all enabled enrol plugins that returned true from is_cron_required(). | |
1324 | * @return void | |
1325 | */ | |
1326 | public function cron() { | |
1327 | } | |
1328 | ||
1329 | /** | |
1330 | * Called when user is about to be deleted | |
1331 | * @param object $user | |
1332 | * @return void | |
1333 | */ | |
1334 | public function user_delete($user) { | |
1335 | global $DB; | |
1336 | ||
1337 | $sql = "SELECT e.* | |
1338 | FROM {enrol} e | |
1339 | JOIN {user_enrolments} ue ON (ue.courseid = e.courseid) | |
1340 | WHERE e.enrol = :meta AND ue.userid = :userid"; | |
1341 | $params = array('name'=>$this->get_name(), 'userid'=>$user->id); | |
1342 | ||
1343 | $rs = $DB->get_records_recordset($sql, $params); | |
1344 | foreach($rs as $instance) { | |
1345 | $this->unenrol_user($instance, $user->id); | |
1346 | } | |
1347 | $rs->close(); | |
1348 | } | |
1349 | } | |
1350 |