Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/enrollib.php
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Enumerations