|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00028 defined('MOODLE_INTERNAL') || die(); 00029 00031 define('ENROL_INSTANCE_ENABLED', 0); 00032 00034 define('ENROL_INSTANCE_DISABLED', 1); 00035 00037 define('ENROL_USER_ACTIVE', 0); 00038 00040 define('ENROL_USER_SUSPENDED', 1); 00041 00043 define('ENROL_REQUIRE_LOGIN_CACHE_PERIOD', 1800); 00044 00046 define('ENROL_MAX_TIMESTAMP', 2147483647); 00047 00049 define('ENROL_EXT_REMOVED_UNENROL', 0); 00050 00052 define('ENROL_EXT_REMOVED_KEEP', 1); 00053 00055 define('ENROL_RESTORE_TYPE', 'enrolrestore'); 00057 define('ENROL_RESTORE_CLASS', 'class'); 00059 define('ENROL_RESTORE_EXACT', 'exact'); 00061 define('ENROL_RESTORE_NOUSERS', 'nousers'); 00062 00068 define('ENROL_EXT_REMOVED_SUSPEND', 2); 00069 00074 define('ENROL_EXT_REMOVED_SUSPENDNOROLES', 3); 00075 00081 function enrol_get_plugins($enabled) { 00082 global $CFG; 00083 00084 $result = array(); 00085 00086 if ($enabled) { 00087 // sorted by enabled plugin order 00088 $enabled = explode(',', $CFG->enrol_plugins_enabled); 00089 $plugins = array(); 00090 foreach ($enabled as $plugin) { 00091 $plugins[$plugin] = "$CFG->dirroot/enrol/$plugin"; 00092 } 00093 } else { 00094 // sorted alphabetically 00095 $plugins = get_plugin_list('enrol'); 00096 ksort($plugins); 00097 } 00098 00099 foreach ($plugins as $plugin=>$location) { 00100 if (!file_exists("$location/lib.php")) { 00101 continue; 00102 } 00103 include_once("$location/lib.php"); 00104 $class = "enrol_{$plugin}_plugin"; 00105 if (!class_exists($class)) { 00106 continue; 00107 } 00108 00109 $result[$plugin] = new $class(); 00110 } 00111 00112 return $result; 00113 } 00114 00120 function enrol_get_plugin($name) { 00121 global $CFG; 00122 00123 $name = clean_param($name, PARAM_PLUGIN); 00124 00125 if (empty($name)) { 00126 // ignore malformed or missing plugin names completely 00127 return null; 00128 } 00129 00130 $location = "$CFG->dirroot/enrol/$name"; 00131 00132 if (!file_exists("$location/lib.php")) { 00133 return null; 00134 } 00135 include_once("$location/lib.php"); 00136 $class = "enrol_{$name}_plugin"; 00137 if (!class_exists($class)) { 00138 return null; 00139 } 00140 00141 return new $class(); 00142 } 00143 00150 function enrol_get_instances($courseid, $enabled) { 00151 global $DB, $CFG; 00152 00153 if (!$enabled) { 00154 return $DB->get_records('enrol', array('courseid'=>$courseid), 'sortorder,id'); 00155 } 00156 00157 $result = $DB->get_records('enrol', array('courseid'=>$courseid, 'status'=>ENROL_INSTANCE_ENABLED), 'sortorder,id'); 00158 00159 $enabled = explode(',', $CFG->enrol_plugins_enabled); 00160 foreach ($result as $key=>$instance) { 00161 if (!in_array($instance->enrol, $enabled)) { 00162 unset($result[$key]); 00163 continue; 00164 } 00165 if (!file_exists("$CFG->dirroot/enrol/$instance->enrol/lib.php")) { 00166 // broken plugin 00167 unset($result[$key]); 00168 continue; 00169 } 00170 } 00171 00172 return $result; 00173 } 00174 00181 function enrol_is_enabled($enrol) { 00182 global $CFG; 00183 00184 if (empty($CFG->enrol_plugins_enabled)) { 00185 return false; 00186 } 00187 return in_array($enrol, explode(',', $CFG->enrol_plugins_enabled)); 00188 } 00189 00199 function enrol_check_plugins($user) { 00200 global $CFG; 00201 00202 if (empty($user->id) or isguestuser($user)) { 00203 // shortcut - there is no enrolment work for guests and not-logged-in users 00204 return; 00205 } 00206 00207 if (is_siteadmin()) { 00208 // no sync for admin user, please use admin accounts only for admin tasks like the unix root user! 00209 // if plugin fails on sync admins need to be able to log in and fix the settings 00210 return; 00211 } 00212 00213 static $inprogress = array(); // To prevent this function being called more than once in an invocation 00214 00215 if (!empty($inprogress[$user->id])) { 00216 return; 00217 } 00218 00219 $inprogress[$user->id] = true; // Set the flag 00220 00221 $enabled = enrol_get_plugins(true); 00222 00223 foreach($enabled as $enrol) { 00224 $enrol->sync_user_enrolments($user); 00225 } 00226 00227 unset($inprogress[$user->id]); // Unset the flag 00228 } 00229 00243 function enrol_sharing_course($user1, $user2) { 00244 return enrol_get_shared_courses($user1, $user2, false, true); 00245 } 00246 00264 function enrol_get_shared_courses($user1, $user2, $preloadcontexts = false, $checkexistsonly = false) { 00265 global $DB, $CFG; 00266 00267 $user1 = !empty($user1->id) ? $user1->id : $user1; 00268 $user2 = !empty($user2->id) ? $user2->id : $user2; 00269 00270 if (empty($user1) or empty($user2)) { 00271 return false; 00272 } 00273 00274 if (!$plugins = explode(',', $CFG->enrol_plugins_enabled)) { 00275 return false; 00276 } 00277 00278 list($plugins, $params) = $DB->get_in_or_equal($plugins, SQL_PARAMS_NAMED, 'ee'); 00279 $params['enabled'] = ENROL_INSTANCE_ENABLED; 00280 $params['active1'] = ENROL_USER_ACTIVE; 00281 $params['active2'] = ENROL_USER_ACTIVE; 00282 $params['user1'] = $user1; 00283 $params['user2'] = $user2; 00284 00285 $ctxselect = ''; 00286 $ctxjoin = ''; 00287 if ($preloadcontexts) { 00288 list($ctxselect, $ctxjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx'); 00289 } 00290 00291 $sql = "SELECT c.* $ctxselect 00292 FROM {course} c 00293 JOIN ( 00294 SELECT DISTINCT c.id 00295 FROM {enrol} e 00296 JOIN {user_enrolments} ue1 ON (ue1.enrolid = e.id AND ue1.status = :active1 AND ue1.userid = :user1) 00297 JOIN {user_enrolments} ue2 ON (ue2.enrolid = e.id AND ue2.status = :active2 AND ue2.userid = :user2) 00298 JOIN {course} c ON (c.id = e.courseid AND c.visible = 1) 00299 WHERE e.status = :enabled AND e.enrol $plugins 00300 ) ec ON ec.id = c.id 00301 $ctxjoin"; 00302 00303 if ($checkexistsonly) { 00304 return $DB->record_exists_sql($sql, $params); 00305 } else { 00306 $courses = $DB->get_records_sql($sql, $params); 00307 if ($preloadcontexts) { 00308 array_map('context_instance_preload', $courses); 00309 } 00310 return $courses; 00311 } 00312 } 00313 00322 function enrol_course_edit_form(MoodleQuickForm $mform, $data, $context) { 00323 $plugins = enrol_get_plugins(true); 00324 if (!empty($data->id)) { 00325 $instances = enrol_get_instances($data->id, false); 00326 foreach ($instances as $instance) { 00327 if (!isset($plugins[$instance->enrol])) { 00328 continue; 00329 } 00330 $plugin = $plugins[$instance->enrol]; 00331 $plugin->course_edit_form($instance, $mform, $data, $context); 00332 } 00333 } else { 00334 foreach ($plugins as $plugin) { 00335 $plugin->course_edit_form(NULL, $mform, $data, $context); 00336 } 00337 } 00338 } 00339 00347 function enrol_course_edit_validation(array $data, $context) { 00348 $errors = array(); 00349 $plugins = enrol_get_plugins(true); 00350 00351 if (!empty($data['id'])) { 00352 $instances = enrol_get_instances($data['id'], false); 00353 foreach ($instances as $instance) { 00354 if (!isset($plugins[$instance->enrol])) { 00355 continue; 00356 } 00357 $plugin = $plugins[$instance->enrol]; 00358 $errors = array_merge($errors, $plugin->course_edit_validation($instance, $data, $context)); 00359 } 00360 } else { 00361 foreach ($plugins as $plugin) { 00362 $errors = array_merge($errors, $plugin->course_edit_validation(NULL, $data, $context)); 00363 } 00364 } 00365 00366 return $errors; 00367 } 00368 00376 function enrol_course_updated($inserted, $course, $data) { 00377 global $DB, $CFG; 00378 00379 $plugins = enrol_get_plugins(true); 00380 00381 foreach ($plugins as $plugin) { 00382 $plugin->course_updated($inserted, $course, $data); 00383 } 00384 } 00385 00392 function enrol_add_course_navigation(navigation_node $coursenode, $course) { 00393 global $CFG; 00394 00395 $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); 00396 00397 $instances = enrol_get_instances($course->id, true); 00398 $plugins = enrol_get_plugins(true); 00399 00400 // we do not want to break all course pages if there is some borked enrol plugin, right? 00401 foreach ($instances as $k=>$instance) { 00402 if (!isset($plugins[$instance->enrol])) { 00403 unset($instances[$k]); 00404 } 00405 } 00406 00407 $usersnode = $coursenode->add(get_string('users'), null, navigation_node::TYPE_CONTAINER, null, 'users'); 00408 00409 if ($course->id != SITEID) { 00410 // list all participants - allows assigning roles, groups, etc. 00411 if (has_capability('moodle/course:enrolreview', $coursecontext)) { 00412 $url = new moodle_url('/enrol/users.php', array('id'=>$course->id)); 00413 $usersnode->add(get_string('enrolledusers', 'enrol'), $url, navigation_node::TYPE_SETTING, null, 'review', new pix_icon('i/users', '')); 00414 } 00415 00416 // manage enrol plugin instances 00417 if (has_capability('moodle/course:enrolconfig', $coursecontext) or has_capability('moodle/course:enrolreview', $coursecontext)) { 00418 $url = new moodle_url('/enrol/instances.php', array('id'=>$course->id)); 00419 } else { 00420 $url = NULL; 00421 } 00422 $instancesnode = $usersnode->add(get_string('enrolmentinstances', 'enrol'), $url, navigation_node::TYPE_SETTING, null, 'manageinstances'); 00423 00424 // each instance decides how to configure itself or how many other nav items are exposed 00425 foreach ($instances as $instance) { 00426 if (!isset($plugins[$instance->enrol])) { 00427 continue; 00428 } 00429 $plugins[$instance->enrol]->add_course_navigation($instancesnode, $instance); 00430 } 00431 00432 if (!$url) { 00433 $instancesnode->trim_if_empty(); 00434 } 00435 } 00436 00437 // Manage groups in this course or even frontpage 00438 if (($course->groupmode || !$course->groupmodeforce) && has_capability('moodle/course:managegroups', $coursecontext)) { 00439 $url = new moodle_url('/group/index.php', array('id'=>$course->id)); 00440 $usersnode->add(get_string('groups'), $url, navigation_node::TYPE_SETTING, null, 'groups', new pix_icon('i/group', '')); 00441 } 00442 00443 if (has_any_capability(array( 'moodle/role:assign', 'moodle/role:safeoverride','moodle/role:override', 'moodle/role:review'), $coursecontext)) { 00444 // Override roles 00445 if (has_capability('moodle/role:review', $coursecontext)) { 00446 $url = new moodle_url('/admin/roles/permissions.php', array('contextid'=>$coursecontext->id)); 00447 } else { 00448 $url = NULL; 00449 } 00450 $permissionsnode = $usersnode->add(get_string('permissions', 'role'), $url, navigation_node::TYPE_SETTING, null, 'override'); 00451 00452 // Add assign or override roles if allowed 00453 if ($course->id == SITEID or (!empty($CFG->adminsassignrolesincourse) and is_siteadmin())) { 00454 if (has_capability('moodle/role:assign', $coursecontext)) { 00455 $url = new moodle_url('/admin/roles/assign.php', array('contextid'=>$coursecontext->id)); 00456 $permissionsnode->add(get_string('assignedroles', 'role'), $url, navigation_node::TYPE_SETTING, null, 'roles', new pix_icon('i/roles', '')); 00457 } 00458 } 00459 // Check role permissions 00460 if (has_any_capability(array('moodle/role:assign', 'moodle/role:safeoverride','moodle/role:override', 'moodle/role:assign'), $coursecontext)) { 00461 $url = new moodle_url('/admin/roles/check.php', array('contextid'=>$coursecontext->id)); 00462 $permissionsnode->add(get_string('checkpermissions', 'role'), $url, navigation_node::TYPE_SETTING, null, 'permissions', new pix_icon('i/checkpermissions', '')); 00463 } 00464 } 00465 00466 // Deal somehow with users that are not enrolled but still got a role somehow 00467 if ($course->id != SITEID) { 00468 //TODO, create some new UI for role assignments at course level 00469 if (has_capability('moodle/role:assign', $coursecontext)) { 00470 $url = new moodle_url('/enrol/otherusers.php', array('id'=>$course->id)); 00471 $usersnode->add(get_string('notenrolledusers', 'enrol'), $url, navigation_node::TYPE_SETTING, null, 'otherusers', new pix_icon('i/roles', '')); 00472 } 00473 } 00474 00475 // just in case nothing was actually added 00476 $usersnode->trim_if_empty(); 00477 00478 if ($course->id != SITEID) { 00479 // Unenrol link 00480 if (is_enrolled($coursecontext)) { 00481 foreach ($instances as $instance) { 00482 if (!isset($plugins[$instance->enrol])) { 00483 continue; 00484 } 00485 $plugin = $plugins[$instance->enrol]; 00486 if ($unenrollink = $plugin->get_unenrolself_link($instance)) { 00487 $shortname = format_string($course->shortname, true, array('context' => $coursecontext)); 00488 $coursenode->add(get_string('unenrolme', 'core_enrol', $shortname), $unenrollink, navigation_node::TYPE_SETTING, null, 'unenrolself', new pix_icon('i/user', '')); 00489 break; 00490 //TODO. deal with multiple unenrol links - not likely case, but still... 00491 } 00492 } 00493 } else { 00494 if (is_viewing($coursecontext)) { 00495 // better not show any enrol link, this is intended for managers and inspectors 00496 } else { 00497 foreach ($instances as $instance) { 00498 if (!isset($plugins[$instance->enrol])) { 00499 continue; 00500 } 00501 $plugin = $plugins[$instance->enrol]; 00502 if ($plugin->show_enrolme_link($instance)) { 00503 $url = new moodle_url('/enrol/index.php', array('id'=>$course->id)); 00504 $shortname = format_string($course->shortname, true, array('context' => $coursecontext)); 00505 $coursenode->add(get_string('enrolme', 'core_enrol', $shortname), $url, navigation_node::TYPE_SETTING, null, 'enrolself', new pix_icon('i/user', '')); 00506 break; 00507 } 00508 } 00509 } 00510 } 00511 } 00512 } 00513 00526 function enrol_get_my_courses($fields = NULL, $sort = 'visible DESC,sortorder ASC', $limit = 0) { 00527 global $DB, $USER; 00528 00529 // Guest account does not have any courses 00530 if (isguestuser() or !isloggedin()) { 00531 return(array()); 00532 } 00533 00534 $basefields = array('id', 'category', 'sortorder', 00535 'shortname', 'fullname', 'idnumber', 00536 'startdate', 'visible', 00537 'groupmode', 'groupmodeforce'); 00538 00539 if (empty($fields)) { 00540 $fields = $basefields; 00541 } else if (is_string($fields)) { 00542 // turn the fields from a string to an array 00543 $fields = explode(',', $fields); 00544 $fields = array_map('trim', $fields); 00545 $fields = array_unique(array_merge($basefields, $fields)); 00546 } else if (is_array($fields)) { 00547 $fields = array_unique(array_merge($basefields, $fields)); 00548 } else { 00549 throw new coding_exception('Invalid $fileds parameter in enrol_get_my_courses()'); 00550 } 00551 if (in_array('*', $fields)) { 00552 $fields = array('*'); 00553 } 00554 00555 $orderby = ""; 00556 $sort = trim($sort); 00557 if (!empty($sort)) { 00558 $rawsorts = explode(',', $sort); 00559 $sorts = array(); 00560 foreach ($rawsorts as $rawsort) { 00561 $rawsort = trim($rawsort); 00562 if (strpos($rawsort, 'c.') === 0) { 00563 $rawsort = substr($rawsort, 2); 00564 } 00565 $sorts[] = trim($rawsort); 00566 } 00567 $sort = 'c.'.implode(',c.', $sorts); 00568 $orderby = "ORDER BY $sort"; 00569 } 00570 00571 $wheres = array("c.id <> :siteid"); 00572 $params = array('siteid'=>SITEID); 00573 00574 if (isset($USER->loginascontext) and $USER->loginascontext->contextlevel == CONTEXT_COURSE) { 00575 // list _only_ this course - anything else is asking for trouble... 00576 $wheres[] = "courseid = :loginas"; 00577 $params['loginas'] = $USER->loginascontext->instanceid; 00578 } 00579 00580 $coursefields = 'c.' .join(',c.', $fields); 00581 list($ccselect, $ccjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx'); 00582 $wheres = implode(" AND ", $wheres); 00583 00584 //note: we can not use DISTINCT + text fields due to Oracle and MS limitations, that is why we have the subselect there 00585 $sql = "SELECT $coursefields $ccselect 00586 FROM {course} c 00587 JOIN (SELECT DISTINCT e.courseid 00588 FROM {enrol} e 00589 JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = :userid) 00590 WHERE ue.status = :active AND e.status = :enabled AND ue.timestart < :now1 AND (ue.timeend = 0 OR ue.timeend > :now2) 00591 ) en ON (en.courseid = c.id) 00592 $ccjoin 00593 WHERE $wheres 00594 $orderby"; 00595 $params['userid'] = $USER->id; 00596 $params['active'] = ENROL_USER_ACTIVE; 00597 $params['enabled'] = ENROL_INSTANCE_ENABLED; 00598 $params['now1'] = round(time(), -2); // improves db caching 00599 $params['now2'] = $params['now1']; 00600 00601 $courses = $DB->get_records_sql($sql, $params, 0, $limit); 00602 00603 // preload contexts and check visibility 00604 foreach ($courses as $id=>$course) { 00605 context_instance_preload($course); 00606 if (!$course->visible) { 00607 if (!$context = get_context_instance(CONTEXT_COURSE, $id)) { 00608 unset($courses[$id]); 00609 continue; 00610 } 00611 if (!has_capability('moodle/course:viewhiddencourses', $context)) { 00612 unset($courses[$id]); 00613 continue; 00614 } 00615 } 00616 $courses[$id] = $course; 00617 } 00618 00619 //wow! Is that really all? :-D 00620 00621 return $courses; 00622 } 00623 00631 function enrol_get_course_info_icons($course, array $instances = NULL) { 00632 $icons = array(); 00633 if (is_null($instances)) { 00634 $instances = enrol_get_instances($course->id, true); 00635 } 00636 $plugins = enrol_get_plugins(true); 00637 foreach ($plugins as $name => $plugin) { 00638 $pis = array(); 00639 foreach ($instances as $instance) { 00640 if ($instance->status != ENROL_INSTANCE_ENABLED or $instance->courseid != $course->id) { 00641 debugging('Invalid instances parameter submitted in enrol_get_info_icons()'); 00642 continue; 00643 } 00644 if ($instance->enrol == $name) { 00645 $pis[$instance->id] = $instance; 00646 } 00647 } 00648 if ($pis) { 00649 $icons = array_merge($icons, $plugin->get_info_icons($pis)); 00650 } 00651 } 00652 return $icons; 00653 } 00654 00661 function enrol_get_course_description_texts($course) { 00662 $lines = array(); 00663 $instances = enrol_get_instances($course->id, true); 00664 $plugins = enrol_get_plugins(true); 00665 foreach ($instances as $instance) { 00666 if (!isset($plugins[$instance->enrol])) { 00667 //weird 00668 continue; 00669 } 00670 $plugin = $plugins[$instance->enrol]; 00671 $text = $plugin->get_description_text($instance); 00672 if ($text !== NULL) { 00673 $lines[] = $text; 00674 } 00675 } 00676 return $lines; 00677 } 00678 00692 function enrol_get_users_courses($userid, $onlyactive = false, $fields = NULL, $sort = 'visible DESC,sortorder ASC') { 00693 global $DB; 00694 00695 // Guest account does not have any courses 00696 if (isguestuser($userid) or empty($userid)) { 00697 return(array()); 00698 } 00699 00700 $basefields = array('id', 'category', 'sortorder', 00701 'shortname', 'fullname', 'idnumber', 00702 'startdate', 'visible', 00703 'groupmode', 'groupmodeforce'); 00704 00705 if (empty($fields)) { 00706 $fields = $basefields; 00707 } else if (is_string($fields)) { 00708 // turn the fields from a string to an array 00709 $fields = explode(',', $fields); 00710 $fields = array_map('trim', $fields); 00711 $fields = array_unique(array_merge($basefields, $fields)); 00712 } else if (is_array($fields)) { 00713 $fields = array_unique(array_merge($basefields, $fields)); 00714 } else { 00715 throw new coding_exception('Invalid $fileds parameter in enrol_get_my_courses()'); 00716 } 00717 if (in_array('*', $fields)) { 00718 $fields = array('*'); 00719 } 00720 00721 $orderby = ""; 00722 $sort = trim($sort); 00723 if (!empty($sort)) { 00724 $rawsorts = explode(',', $sort); 00725 $sorts = array(); 00726 foreach ($rawsorts as $rawsort) { 00727 $rawsort = trim($rawsort); 00728 if (strpos($rawsort, 'c.') === 0) { 00729 $rawsort = substr($rawsort, 2); 00730 } 00731 $sorts[] = trim($rawsort); 00732 } 00733 $sort = 'c.'.implode(',c.', $sorts); 00734 $orderby = "ORDER BY $sort"; 00735 } 00736 00737 $params = array('siteid'=>SITEID); 00738 00739 if ($onlyactive) { 00740 $subwhere = "WHERE ue.status = :active AND e.status = :enabled AND ue.timestart < :now1 AND (ue.timeend = 0 OR ue.timeend > :now2)"; 00741 $params['now1'] = round(time(), -2); // improves db caching 00742 $params['now2'] = $params['now1']; 00743 $params['active'] = ENROL_USER_ACTIVE; 00744 $params['enabled'] = ENROL_INSTANCE_ENABLED; 00745 } else { 00746 $subwhere = ""; 00747 } 00748 00749 $coursefields = 'c.' .join(',c.', $fields); 00750 list($ccselect, $ccjoin) = context_instance_preload_sql('c.id', CONTEXT_COURSE, 'ctx'); 00751 00752 //note: we can not use DISTINCT + text fields due to Oracle and MS limitations, that is why we have the subselect there 00753 $sql = "SELECT $coursefields $ccselect 00754 FROM {course} c 00755 JOIN (SELECT DISTINCT e.courseid 00756 FROM {enrol} e 00757 JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = :userid) 00758 $subwhere 00759 ) en ON (en.courseid = c.id) 00760 $ccjoin 00761 WHERE c.id <> :siteid 00762 $orderby"; 00763 $params['userid'] = $userid; 00764 00765 $courses = $DB->get_records_sql($sql, $params); 00766 00767 // preload contexts and check visibility 00768 foreach ($courses as $id=>$course) { 00769 context_instance_preload($course); 00770 if ($onlyactive) { 00771 if (!$course->visible) { 00772 if (!$context = get_context_instance(CONTEXT_COURSE, $id)) { 00773 unset($courses[$id]); 00774 continue; 00775 } 00776 if (!has_capability('moodle/course:viewhiddencourses', $context, $userid)) { 00777 unset($courses[$id]); 00778 continue; 00779 } 00780 } 00781 } 00782 $courses[$id] = $course; 00783 } 00784 00785 //wow! Is that really all? :-D 00786 00787 return $courses; 00788 00789 } 00790 00796 function enrol_user_delete($user) { 00797 global $DB; 00798 00799 $plugins = enrol_get_plugins(true); 00800 foreach ($plugins as $plugin) { 00801 $plugin->user_delete($user); 00802 } 00803 00804 // force cleanup of all broken enrolments 00805 $DB->delete_records('user_enrolments', array('userid'=>$user->id)); 00806 } 00807 00813 function enrol_course_delete($course) { 00814 global $DB; 00815 00816 $instances = enrol_get_instances($course->id, false); 00817 $plugins = enrol_get_plugins(true); 00818 foreach ($instances as $instance) { 00819 if (isset($plugins[$instance->enrol])) { 00820 $plugins[$instance->enrol]->delete_instance($instance); 00821 } 00822 // low level delete in case plugin did not do it 00823 $DB->delete_records('user_enrolments', array('enrolid'=>$instance->id)); 00824 $DB->delete_records('role_assignments', array('itemid'=>$instance->id, 'component'=>'enrol_'.$instance->enrol)); 00825 $DB->delete_records('user_enrolments', array('enrolid'=>$instance->id)); 00826 $DB->delete_records('enrol', array('id'=>$instance->id)); 00827 } 00828 } 00829 00842 function enrol_try_internal_enrol($courseid, $userid, $roleid = null, $timestart = 0, $timeend = 0) { 00843 global $DB; 00844 00845 //note: this is hardcoded to manual plugin for now 00846 00847 if (!enrol_is_enabled('manual')) { 00848 return false; 00849 } 00850 00851 if (!$enrol = enrol_get_plugin('manual')) { 00852 return false; 00853 } 00854 if (!$instances = $DB->get_records('enrol', array('enrol'=>'manual', 'courseid'=>$courseid, 'status'=>ENROL_INSTANCE_ENABLED), 'sortorder,id ASC')) { 00855 return false; 00856 } 00857 $instance = reset($instances); 00858 00859 $enrol->enrol_user($instance, $userid, $roleid, $timestart, $timeend); 00860 00861 return true; 00862 } 00863 00869 function enrol_selfenrol_available($courseid) { 00870 $result = false; 00871 00872 $plugins = enrol_get_plugins(true); 00873 $enrolinstances = enrol_get_instances($courseid, true); 00874 foreach($enrolinstances as $instance) { 00875 if (!isset($plugins[$instance->enrol])) { 00876 continue; 00877 } 00878 if ($instance->enrol === 'guest') { 00879 // blacklist known temporary guest plugins 00880 continue; 00881 } 00882 if ($plugins[$instance->enrol]->show_enrolme_link($instance)) { 00883 $result = true; 00884 break; 00885 } 00886 } 00887 00888 return $result; 00889 } 00890 00900 function enrol_get_enrolment_end($courseid, $userid) { 00901 global $DB; 00902 00903 $sql = "SELECT ue.* 00904 FROM {user_enrolments} ue 00905 JOIN {enrol} e ON (e.id = ue.enrolid AND e.courseid = :courseid) 00906 JOIN {user} u ON u.id = ue.userid 00907 WHERE ue.userid = :userid AND ue.status = :active AND e.status = :enabled AND u.deleted = 0"; 00908 $params = array('enabled'=>ENROL_INSTANCE_ENABLED, 'active'=>ENROL_USER_ACTIVE, 'userid'=>$userid, 'courseid'=>$courseid); 00909 00910 if (!$enrolments = $DB->get_records_sql($sql, $params)) { 00911 return false; 00912 } 00913 00914 $changes = array(); 00915 00916 foreach ($enrolments as $ue) { 00917 $start = (int)$ue->timestart; 00918 $end = (int)$ue->timeend; 00919 if ($end != 0 and $end < $start) { 00920 debugging('Invalid enrolment start or end in user_enrolment id:'.$ue->id); 00921 continue; 00922 } 00923 if (isset($changes[$start])) { 00924 $changes[$start] = $changes[$start] + 1; 00925 } else { 00926 $changes[$start] = 1; 00927 } 00928 if ($end === 0) { 00929 // no end 00930 } else if (isset($changes[$end])) { 00931 $changes[$end] = $changes[$end] - 1; 00932 } else { 00933 $changes[$end] = -1; 00934 } 00935 } 00936 00937 // let's sort then enrolment starts&ends and go through them chronologically, 00938 // looking for current status and the next future end of enrolment 00939 ksort($changes); 00940 00941 $now = time(); 00942 $current = 0; 00943 $present = null; 00944 00945 foreach ($changes as $time => $change) { 00946 if ($time > $now) { 00947 if ($present === null) { 00948 // we have just went past current time 00949 $present = $current; 00950 if ($present < 1) { 00951 // no enrolment active 00952 return false; 00953 } 00954 } 00955 if ($present !== null) { 00956 // we are already in the future - look for possible end 00957 if ($current + $change < 1) { 00958 return $time; 00959 } 00960 } 00961 } 00962 $current += $change; 00963 } 00964 00965 if ($current > 0) { 00966 return 0; 00967 } else { 00968 return false; 00969 } 00970 } 00971 00972 00977 abstract class enrol_plugin { 00978 protected $config = null; 00979 00984 public function get_name() { 00985 // second word in class is always enrol name, sorry, no fancy plugin names with _ 00986 $words = explode('_', get_class($this)); 00987 return $words[1]; 00988 } 00989 00996 public function get_instance_name($instance) { 00997 if (empty($instance->name)) { 00998 $enrol = $this->get_name(); 00999 return get_string('pluginname', 'enrol_'.$enrol); 01000 } else { 01001 $context = get_context_instance(CONTEXT_COURSE, $instance->courseid); 01002 return format_string($instance->name, true, array('context'=>$context)); 01003 } 01004 } 01005 01018 public function get_info_icons(array $instances) { 01019 return array(); 01020 } 01021 01031 public function get_description_text($instance) { 01032 return null; 01033 } 01034 01039 protected function load_config() { 01040 if (!isset($this->config)) { 01041 $name = $this->get_name(); 01042 $this->config = get_config("enrol_$name"); 01043 } 01044 } 01045 01052 public function get_config($name, $default = NULL) { 01053 $this->load_config(); 01054 return isset($this->config->$name) ? $this->config->$name : $default; 01055 } 01056 01063 public function set_config($name, $value) { 01064 $pluginname = $this->get_name(); 01065 $this->load_config(); 01066 if ($value === NULL) { 01067 unset($this->config->$name); 01068 } else { 01069 $this->config->$name = $value; 01070 } 01071 set_config($name, $value, "enrol_$pluginname"); 01072 } 01073 01078 public function roles_protected() { 01079 return true; 01080 } 01081 01090 public function allow_enrol(stdClass $instance) { 01091 return false; 01092 } 01093 01101 public function allow_unenrol(stdClass $instance) { 01102 return false; 01103 } 01104 01117 public function allow_unenrol_user(stdClass $instance, stdClass $ue) { 01118 return $this->allow_unenrol($instance); 01119 } 01120 01129 public function allow_manage(stdClass $instance) { 01130 return false; 01131 } 01132 01140 public function show_enrolme_link(stdClass $instance) { 01141 return false; 01142 } 01143 01153 public function try_autoenrol(stdClass $instance) { 01154 global $USER; 01155 01156 return false; 01157 } 01158 01168 public function try_guestaccess(stdClass $instance) { 01169 global $USER; 01170 01171 return false; 01172 } 01173 01185 public function enrol_user(stdClass $instance, $userid, $roleid = NULL, $timestart = 0, $timeend = 0, $status = NULL) { 01186 global $DB, $USER, $CFG; // CFG necessary!!! 01187 01188 if ($instance->courseid == SITEID) { 01189 throw new coding_exception('invalid attempt to enrol into frontpage course!'); 01190 } 01191 01192 $name = $this->get_name(); 01193 $courseid = $instance->courseid; 01194 01195 if ($instance->enrol !== $name) { 01196 throw new coding_exception('invalid enrol instance!'); 01197 } 01198 $context = get_context_instance(CONTEXT_COURSE, $instance->courseid, MUST_EXIST); 01199 01200 $inserted = false; 01201 $updated = false; 01202 if ($ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) { 01203 //only update if timestart or timeend or status are different. 01204 if ($ue->timestart != $timestart or $ue->timeend != $timeend or (!is_null($status) and $ue->status != $status)) { 01205 $ue->timestart = $timestart; 01206 $ue->timeend = $timeend; 01207 if (!is_null($status)) { 01208 $ue->status = $status; 01209 } 01210 $ue->modifierid = $USER->id; 01211 $ue->timemodified = time(); 01212 $DB->update_record('user_enrolments', $ue); 01213 01214 $updated = true; 01215 } 01216 } else { 01217 $ue = new stdClass(); 01218 $ue->enrolid = $instance->id; 01219 $ue->status = is_null($status) ? ENROL_USER_ACTIVE : $status; 01220 $ue->userid = $userid; 01221 $ue->timestart = $timestart; 01222 $ue->timeend = $timeend; 01223 $ue->modifierid = $USER->id; 01224 $ue->timecreated = time(); 01225 $ue->timemodified = $ue->timecreated; 01226 $ue->id = $DB->insert_record('user_enrolments', $ue); 01227 01228 $inserted = true; 01229 } 01230 01231 if ($inserted) { 01232 // add extra info and trigger event 01233 $ue->courseid = $courseid; 01234 $ue->enrol = $name; 01235 events_trigger('user_enrolled', $ue); 01236 } else if ($updated) { 01237 $ue->courseid = $courseid; 01238 $ue->enrol = $name; 01239 events_trigger('user_enrol_modified', $ue); 01240 // resets current enrolment caches 01241 $context->mark_dirty(); 01242 } 01243 01244 if ($roleid) { 01245 // this must be done after the enrolment event so that the role_assigned event is triggered afterwards 01246 if ($this->roles_protected()) { 01247 role_assign($roleid, $userid, $context->id, 'enrol_'.$name, $instance->id); 01248 } else { 01249 role_assign($roleid, $userid, $context->id); 01250 } 01251 } 01252 01253 // reset current user enrolment caching 01254 if ($userid == $USER->id) { 01255 if (isset($USER->enrol['enrolled'][$courseid])) { 01256 unset($USER->enrol['enrolled'][$courseid]); 01257 } 01258 if (isset($USER->enrol['tempguest'][$courseid])) { 01259 unset($USER->enrol['tempguest'][$courseid]); 01260 remove_temp_course_roles($context); 01261 } 01262 } 01263 } 01264 01275 public function update_user_enrol(stdClass $instance, $userid, $status = NULL, $timestart = NULL, $timeend = NULL) { 01276 global $DB, $USER; 01277 01278 $name = $this->get_name(); 01279 01280 if ($instance->enrol !== $name) { 01281 throw new coding_exception('invalid enrol instance!'); 01282 } 01283 01284 if (!$ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) { 01285 // weird, user not enrolled 01286 return; 01287 } 01288 01289 $modified = false; 01290 if (isset($status) and $ue->status != $status) { 01291 $ue->status = $status; 01292 $modified = true; 01293 } 01294 if (isset($timestart) and $ue->timestart != $timestart) { 01295 $ue->timestart = $timestart; 01296 $modified = true; 01297 } 01298 if (isset($timeend) and $ue->timeend != $timeend) { 01299 $ue->timeend = $timeend; 01300 $modified = true; 01301 } 01302 01303 if (!$modified) { 01304 // no change 01305 return; 01306 } 01307 01308 $ue->modifierid = $USER->id; 01309 $DB->update_record('user_enrolments', $ue); 01310 context_course::instance($instance->courseid)->mark_dirty(); // reset enrol caches 01311 01312 // trigger event 01313 $ue->courseid = $instance->courseid; 01314 $ue->enrol = $instance->name; 01315 events_trigger('user_enrol_modified', $ue); 01316 } 01317 01326 public function unenrol_user(stdClass $instance, $userid) { 01327 global $CFG, $USER, $DB; 01328 01329 $name = $this->get_name(); 01330 $courseid = $instance->courseid; 01331 01332 if ($instance->enrol !== $name) { 01333 throw new coding_exception('invalid enrol instance!'); 01334 } 01335 $context = get_context_instance(CONTEXT_COURSE, $instance->courseid, MUST_EXIST); 01336 01337 if (!$ue = $DB->get_record('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) { 01338 // weird, user not enrolled 01339 return; 01340 } 01341 01342 role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_'.$name, 'itemid'=>$instance->id)); 01343 $DB->delete_records('user_enrolments', array('id'=>$ue->id)); 01344 01345 // add extra info and trigger event 01346 $ue->courseid = $courseid; 01347 $ue->enrol = $name; 01348 01349 $sql = "SELECT 'x' 01350 FROM {user_enrolments} ue 01351 JOIN {enrol} e ON (e.id = ue.enrolid) 01352 WHERE ue.userid = :userid AND e.courseid = :courseid"; 01353 if ($DB->record_exists_sql($sql, array('userid'=>$userid, 'courseid'=>$courseid))) { 01354 $ue->lastenrol = false; 01355 events_trigger('user_unenrolled', $ue); 01356 // user still has some enrolments, no big cleanup yet 01357 } else { 01358 // the big cleanup IS necessary! 01359 01360 require_once("$CFG->dirroot/group/lib.php"); 01361 require_once("$CFG->libdir/gradelib.php"); 01362 01363 // remove all remaining roles 01364 role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id), true, false); 01365 01366 //clean up ALL invisible user data from course if this is the last enrolment - groups, grades, etc. 01367 groups_delete_group_members($courseid, $userid); 01368 01369 grade_user_unenrol($courseid, $userid); 01370 01371 $DB->delete_records('user_lastaccess', array('userid'=>$userid, 'courseid'=>$courseid)); 01372 01373 $ue->lastenrol = true; // means user not enrolled any more 01374 events_trigger('user_unenrolled', $ue); 01375 } 01376 01377 // reset all enrol caches 01378 $context->mark_dirty(); 01379 01380 // reset current user enrolment caching 01381 if ($userid == $USER->id) { 01382 if (isset($USER->enrol['enrolled'][$courseid])) { 01383 unset($USER->enrol['enrolled'][$courseid]); 01384 } 01385 if (isset($USER->enrol['tempguest'][$courseid])) { 01386 unset($USER->enrol['tempguest'][$courseid]); 01387 remove_temp_course_roles($context); 01388 } 01389 } 01390 } 01391 01402 public function sync_user_enrolments($user) { 01403 // override if necessary 01404 } 01405 01411 public function get_newinstance_link($courseid) { 01412 // override for most plugins, check if instance already exists in cases only one instance is supported 01413 return NULL; 01414 } 01415 01422 public function instance_deleteable($instance) { 01423 return true; 01424 } 01425 01433 public function get_manual_enrol_link($instance) { 01434 return NULL; 01435 } 01436 01443 public function get_unenrolself_link($instance) { 01444 global $USER, $CFG, $DB; 01445 01446 $name = $this->get_name(); 01447 if ($instance->enrol !== $name) { 01448 throw new coding_exception('invalid enrol instance!'); 01449 } 01450 01451 if ($instance->courseid == SITEID) { 01452 return NULL; 01453 } 01454 01455 if (!enrol_is_enabled($name)) { 01456 return NULL; 01457 } 01458 01459 if ($instance->status != ENROL_INSTANCE_ENABLED) { 01460 return NULL; 01461 } 01462 01463 if (!file_exists("$CFG->dirroot/enrol/$name/unenrolself.php")) { 01464 return NULL; 01465 } 01466 01467 $context = get_context_instance(CONTEXT_COURSE, $instance->courseid, MUST_EXIST); 01468 01469 if (!has_capability("enrol/$name:unenrolself", $context)) { 01470 return NULL; 01471 } 01472 01473 if (!$DB->record_exists('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$USER->id, 'status'=>ENROL_USER_ACTIVE))) { 01474 return NULL; 01475 } 01476 01477 return new moodle_url("/enrol/$name/unenrolself.php", array('enrolid'=>$instance->id));; 01478 } 01479 01489 public function course_edit_form($instance, MoodleQuickForm $mform, $data, $context) { 01490 // override - usually at least enable/disable switch, has to add own form header 01491 } 01492 01501 public function course_edit_validation($instance, array $data, $context) { 01502 return array(); 01503 } 01504 01513 public function course_updated($inserted, $course, $data) { 01514 if ($inserted) { 01515 if ($this->get_config('defaultenrol')) { 01516 $this->add_default_instance($course); 01517 } 01518 } 01519 } 01520 01527 public function add_instance($course, array $fields = NULL) { 01528 global $DB; 01529 01530 if ($course->id == SITEID) { 01531 throw new coding_exception('Invalid request to add enrol instance to frontpage.'); 01532 } 01533 01534 $instance = new stdClass(); 01535 $instance->enrol = $this->get_name(); 01536 $instance->status = ENROL_INSTANCE_ENABLED; 01537 $instance->courseid = $course->id; 01538 $instance->enrolstartdate = 0; 01539 $instance->enrolenddate = 0; 01540 $instance->timemodified = time(); 01541 $instance->timecreated = $instance->timemodified; 01542 $instance->sortorder = $DB->get_field('enrol', 'COALESCE(MAX(sortorder), -1) + 1', array('courseid'=>$course->id)); 01543 01544 $fields = (array)$fields; 01545 unset($fields['enrol']); 01546 unset($fields['courseid']); 01547 unset($fields['sortorder']); 01548 foreach($fields as $field=>$value) { 01549 $instance->$field = $value; 01550 } 01551 01552 return $DB->insert_record('enrol', $instance); 01553 } 01554 01564 public function add_default_instance($course) { 01565 return null; 01566 } 01567 01577 public function update_status($instance, $newstatus) { 01578 global $DB; 01579 01580 $instance->status = $newstatus; 01581 $DB->update_record('enrol', $instance); 01582 01583 // invalidate all enrol caches 01584 $context = context_course::instance($instance->courseid); 01585 $context->mark_dirty(); 01586 } 01587 01593 public function delete_instance($instance) { 01594 global $DB; 01595 01596 $name = $this->get_name(); 01597 if ($instance->enrol !== $name) { 01598 throw new coding_exception('invalid enrol instance!'); 01599 } 01600 01601 //first unenrol all users 01602 $participants = $DB->get_recordset('user_enrolments', array('enrolid'=>$instance->id)); 01603 foreach ($participants as $participant) { 01604 $this->unenrol_user($instance, $participant->userid); 01605 } 01606 $participants->close(); 01607 01608 // now clean up all remainders that were not removed correctly 01609 $DB->delete_records('role_assignments', array('itemid'=>$instance->id, 'component'=>$name)); 01610 $DB->delete_records('user_enrolments', array('enrolid'=>$instance->id)); 01611 01612 // finally drop the enrol row 01613 $DB->delete_records('enrol', array('id'=>$instance->id)); 01614 01615 // invalidate all enrol caches 01616 $context = context_course::instance($instance->courseid); 01617 $context->mark_dirty(); 01618 } 01619 01627 public function enrol_page_hook(stdClass $instance) { 01628 return null; 01629 } 01630 01640 public function add_course_navigation($instancesnode, stdClass $instance) { 01641 // usually adds manage users 01642 } 01643 01649 public function get_action_icons(stdClass $instance) { 01650 return array(); 01651 } 01652 01658 public function is_cron_required() { 01659 global $CFG; 01660 01661 $name = $this->get_name(); 01662 $versionfile = "$CFG->dirroot/enrol/$name/version.php"; 01663 $plugin = new stdClass(); 01664 include($versionfile); 01665 if (empty($plugin->cron)) { 01666 return false; 01667 } 01668 $lastexecuted = $this->get_config('lastcron', 0); 01669 if ($lastexecuted + $plugin->cron < time()) { 01670 return true; 01671 } else { 01672 return false; 01673 } 01674 } 01675 01680 public function cron() { 01681 } 01682 01688 public function user_delete($user) { 01689 global $DB; 01690 01691 $sql = "SELECT e.* 01692 FROM {enrol} e 01693 JOIN {user_enrolments} ue ON (ue.enrolid = e.id) 01694 WHERE e.enrol = :name AND ue.userid = :userid"; 01695 $params = array('name'=>$this->get_name(), 'userid'=>$user->id); 01696 01697 $rs = $DB->get_recordset_sql($sql, $params); 01698 foreach($rs as $instance) { 01699 $this->unenrol_user($instance, $user->id); 01700 } 01701 $rs->close(); 01702 } 01703 01714 public function get_manual_enrol_button(course_enrolment_manager $manager) { 01715 return false; 01716 } 01717 01725 public function get_user_enrolment_actions(course_enrolment_manager $manager, $ue) { 01726 return array(); 01727 } 01728 01735 public function has_bulk_operations() { 01736 return false; 01737 } 01738 01745 public function get_bulk_operations() { 01746 return array(); 01747 } 01748 }