9883fc870dcf9bcb7a02e9ae798b3d5bca7134b2
[moodle.git] / enrol / locallib.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * This file contains the course_enrolment_manager class which is used to interface
20  * with the functions that exist in enrollib.php in relation to a single course.
21  *
22  * @package    core
23  * @subpackage enrol
24  * @copyright  2010 Sam Hemelryk
25  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26  */
28 /**
29  * This class provides a targeted tied together means of interfacing the enrolment
30  * tasks together with a course.
31  *
32  * It is provided as a convenience more than anything else.
33  *
34  * @copyright 2010 Sam Hemelryk
35  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36  */
37 class course_enrolment_manager {
39     /**
40      * The course context
41      * @var stdClass
42      */
43     protected $context;
44     /**
45      * The course we are managing enrolments for
46      * @var stdClass
47      */
48     protected $course = null;
49     /**
50      * Limits the focus of the manager to one enrolment plugin instance
51      * @var string
52      */
53     protected $instancefilter = null;
55     /**
56      * The total number of users enrolled in the course
57      * Populated by course_enrolment_manager::get_total_users
58      * @var int
59      */
60     protected $totalusers = null;
61     /**
62      * An array of users currently enrolled in the course
63      * Populated by course_enrolment_manager::get_users
64      * @var array
65      */
66     protected $users = array();
68     /**
69      * An array of users who have roles within this course but who have not
70      * been enrolled in the course
71      * @var array
72      */
73     protected $otherusers = array();
75     /**
76      * The total number of users who hold a role within the course but who
77      * arn't enrolled.
78      * @var int
79      */
80     protected $totalotherusers = null;
82     /**#@+
83      * These variables are used to cache the information this class uses
84      * please never use these directly instead use their get_ counterparts.
85      * @access private
86      * @var array
87      */
88     private $_instancessql = null;
89     private $_instances = null;
90     private $_inames = null;
91     private $_plugins = null;
92     private $_roles = null;
93     private $_assignableroles = null;
94     private $_assignablerolesothers = null;
95     private $_groups = null;
96     /**#@-*/
98     /**
99      * Constructs the course enrolment manager
100      *
101      * @param stdClass $course
102      * @param string $instancefilter
103      */
104     public function __construct($course, $instancefilter = null) {
105         $this->context = get_context_instance(CONTEXT_COURSE, $course->id);
106         $this->course = $course;
107         $this->instancefilter = $instancefilter;
108     }
110     /**
111      * Returns the total number of enrolled users in the course.
112      *
113      * If a filter was specificed this will be the total number of users enrolled
114      * in this course by means of that instance.
115      *
116      * @global moodle_database $DB
117      * @return int
118      */
119     public function get_total_users() {
120         global $DB;
121         if ($this->totalusers === null) {
122             list($instancessql, $params, $filter) = $this->get_instance_sql();
123             $sqltotal = "SELECT COUNT(DISTINCT u.id)
124                            FROM {user} u
125                            JOIN {user_enrolments} ue ON (ue.userid = u.id  AND ue.enrolid $instancessql)
126                            JOIN {enrol} e ON (e.id = ue.enrolid)";
127             $this->totalusers = (int)$DB->count_records_sql($sqltotal, $params);
128         }
129         return $this->totalusers;
130     }
132     /**
133      * Returns the total number of enrolled users in the course.
134      *
135      * If a filter was specificed this will be the total number of users enrolled
136      * in this course by means of that instance.
137      *
138      * @global moodle_database $DB
139      * @return int
140      */
141     public function get_total_other_users() {
142         global $DB;
143         if ($this->totalotherusers === null) {
144             list($ctxcondition, $params) = $DB->get_in_or_equal(get_parent_contexts($this->context, true), SQL_PARAMS_NAMED, 'ctx00');
145             $params['courseid'] = $this->course->id;
146             $sql = "SELECT COUNT(DISTINCT u.id)
147                     FROM {role_assignments} ra
148                     JOIN {user} u ON u.id = ra.userid
149                     JOIN {context} ctx ON ra.contextid = ctx.id
150                     LEFT JOIN (
151                         SELECT ue.id, ue.userid
152                         FROM {user_enrolments} ue
153                         LEFT JOIN {enrol} e ON e.id=ue.enrolid
154                         WHERE e.courseid = :courseid
155                     ) ue ON ue.userid=u.id
156                     WHERE
157                         ctx.id $ctxcondition AND
158                         ue.id IS NULL";
159             $this->totalotherusers = (int)$DB->count_records_sql($sql, $params);
160         }
161         return $this->totalotherusers;
162     }
164     /**
165      * Gets all of the users enrolled in this course.
166      *
167      * If a filter was specified this will be the users who were enrolled
168      * in this course by means of that instance.
169      *
170      * @global moodle_database $DB
171      * @param string $sort
172      * @param string $direction ASC or DESC
173      * @param int $page First page should be 0
174      * @param int $perpage Defaults to 25
175      * @return array
176      */
177     public function get_users($sort, $direction='ASC', $page=0, $perpage=25) {
178         global $DB;
179         if ($direction !== 'ASC') {
180             $direction = 'DESC';
181         }
182         $key = md5("$sort-$direction-$page-$perpage");
183         if (!array_key_exists($key, $this->users)) {
184             list($instancessql, $params, $filter) = $this->get_instance_sql();
185             $ufields = user_picture::fields('u', array('lastaccess', 'email'));
186             $sql = "SELECT DISTINCT $ufields, ul.timeaccess AS lastseen
187                       FROM {user} u
188                       JOIN {user_enrolments} ue ON (ue.userid = u.id  AND ue.enrolid $instancessql)
189                       JOIN {enrol} e ON (e.id = ue.enrolid)
190                  LEFT JOIN {user_lastaccess} ul ON (ul.courseid = e.courseid AND ul.userid = u.id)";
191             if ($sort === 'firstname') {
192                 $sql .= " ORDER BY u.firstname $direction, u.lastname $direction";
193             } else if ($sort === 'lastname') {
194                 $sql .= " ORDER BY u.lastname $direction, u.firstname $direction";
195             } else if ($sort === 'email') {
196                 $sql .= " ORDER BY u.email $direction, u.lastname $direction, u.firstname $direction";
197             } else if ($sort === 'lastseen') {
198                 $sql .= " ORDER BY ul.timeaccess $direction, u.lastname $direction, u.firstname $direction";
199             }
200             $this->users[$key] = $DB->get_records_sql($sql, $params, $page*$perpage, $perpage);
201         }
202         return $this->users[$key];
203     }
205     /**
206      * Gets and array of other users.
207      *
208      * Other users are users who have been assigned roles or inherited roles
209      * within this course but who have not been enrolled in the course
210      *
211      * @global moodle_database $DB
212      * @param string $sort
213      * @param string $direction
214      * @param int $page
215      * @param int $perpage
216      * @return array
217      */
218     public function get_other_users($sort, $direction='ASC', $page=0, $perpage=25) {
219         global $DB;
220         if ($direction !== 'ASC') {
221             $direction = 'DESC';
222         }
223         $key = md5("$sort-$direction-$page-$perpage");
224         if (!array_key_exists($key, $this->otherusers)) {
225             list($ctxcondition, $params) = $DB->get_in_or_equal(get_parent_contexts($this->context, true), SQL_PARAMS_NAMED, 'ctx00');
226             $params['courseid'] = $this->course->id;
227             $params['cid'] = $this->course->id;
228             $sql = "SELECT ra.id as raid, ra.contextid, ra.component, ctx.contextlevel, ra.roleid, u.*, ue.lastseen
229                     FROM {role_assignments} ra
230                     JOIN {user} u ON u.id = ra.userid
231                     JOIN {context} ctx ON ra.contextid = ctx.id
232                     LEFT JOIN (
233                         SELECT ue.id, ue.userid, ul.timeaccess AS lastseen
234                         FROM {user_enrolments} ue
235                         LEFT JOIN {enrol} e ON e.id=ue.enrolid
236                         LEFT JOIN {user_lastaccess} ul ON (ul.courseid = e.courseid AND ul.userid = ue.userid)
237                         WHERE e.courseid = :courseid
238                     ) ue ON ue.userid=u.id
239                     WHERE
240                         ctx.id $ctxcondition AND
241                         ue.id IS NULL
242                     ORDER BY u.$sort $direction, ctx.depth DESC";
243             $this->otherusers[$key] = $DB->get_records_sql($sql, $params, $page*$perpage, $perpage);
244         }
245         return $this->otherusers[$key];
246     }
248     /**
249      * Gets an array of the users that can be enrolled in this course.
250      *
251      * @global moodle_database $DB
252      * @param int $enrolid
253      * @param string $search
254      * @param bool $searchanywhere
255      * @param int $page Defaults to 0
256      * @param int $perpage Defaults to 25
257      * @return array Array(totalusers => int, users => array)
258      */
259     public function get_potential_users($enrolid, $search='', $searchanywhere=false, $page=0, $perpage=25) {
260         global $DB;
262         // Add some additional sensible conditions
263         $tests = array("u.username <> 'guest'", 'u.deleted = 0', 'u.confirmed = 1');
264         $params = array();
265         if (!empty($search)) {
266             $conditions = array('u.firstname','u.lastname');
267             $ilike = ' ' . $DB->sql_ilike();
268             if ($searchanywhere) {
269                 $searchparam = '%' . $search . '%';
270             } else {
271                 $searchparam = $search . '%';
272             }
273             $i = 0;
274             foreach ($conditions as &$condition) {
275                 $condition .= "$ilike :con{$i}00";
276                 $params["con{$i}00"] = $searchparam;
277                 $i++;
278             }
279             $tests[] = '(' . implode(' OR ', $conditions) . ')';
280         }
281         $wherecondition = implode(' AND ', $tests);
283         $ufields = user_picture::fields('u');
285         $fields      = 'SELECT u.id, u.firstname, u.lastname, u.username, u.email, u.lastaccess, u.picture, u.imagealt, '.$ufields;
286         $countfields = 'SELECT COUNT(1)';
287         $sql = " FROM {user} u
288                 WHERE $wherecondition
289                       AND u.id NOT IN (SELECT ue.userid
290                                          FROM {user_enrolments} ue
291                                          JOIN {enrol} e ON (e.id = ue.enrolid AND e.id = :enrolid))";
292         $order = ' ORDER BY u.lastname ASC, u.firstname ASC';
293         $params['enrolid'] = $enrolid;
294         $totalusers = $DB->count_records_sql($countfields . $sql, $params);
295         $availableusers = $DB->get_records_sql($fields . $sql . $order, $params, $page*$perpage, $perpage);
296         return array('totalusers'=>$totalusers, 'users'=>$availableusers);
297     }
299     /**
300      * Searches other users and returns paginated results
301      *
302      * @global moodle_database $DB
303      * @param string $search
304      * @param bool $searchanywhere
305      * @param int $page Starting at 0
306      * @param int $perpage
307      * @return array
308      */
309     public function search_other_users($search='', $searchanywhere=false, $page=0, $perpage=25) {
310         global $DB;
312         // Add some additional sensible conditions
313         $tests = array("u.username <> 'guest'", 'u.deleted = 0', 'u.confirmed = 1');
314         $params = array();
315         if (!empty($search)) {
316             $conditions = array('u.firstname','u.lastname');
317             $ilike = ' ' . $DB->sql_ilike();
318             if ($searchanywhere) {
319                 $searchparam = '%' . $search . '%';
320             } else {
321                 $searchparam = $search . '%';
322             }
323             $i = 0;
324             foreach ($conditions as &$condition) {
325                 $condition .= "$ilike :con{$i}00";
326                 $params["con{$i}00"] = $searchparam;
327                 $i++;
328             }
329             $tests[] = '(' . implode(' OR ', $conditions) . ')';
330         }
331         $wherecondition = implode(' AND ', $tests);
334         $fields      = 'SELECT u.id, u.firstname, u.lastname, u.username, u.email, u.lastaccess, u.picture, u.imagealt, '.user_picture::fields('u');;
335         $countfields = 'SELECT COUNT(u.id)';
336         $sql   = " FROM {user} u
337                   WHERE $wherecondition
338                         AND u.id NOT IN (
339                            SELECT u.id
340                              FROM {role_assignments} r, {user} u
341                             WHERE r.contextid = :contextid
342                                   AND u.id = r.userid)";
343         $order = ' ORDER BY lastname ASC, firstname ASC';
345         $params['contextid'] = $this->context->id;
346         $totalusers = $DB->count_records_sql($countfields . $sql, $params);
347         $availableusers = $DB->get_records_sql($fields . $sql . $order, $params, $page*$perpage, $perpage);
348         return array('totalusers'=>$totalusers, 'users'=>$availableusers);
349     }
351     /**
352      * Gets an array containing some SQL to user for when selecting, params for
353      * that SQL, and the filter that was used in constructing the sql.
354      *
355      * @global moodle_database $DB
356      * @return string
357      */
358     protected function get_instance_sql() {
359         global $DB;
360         if ($this->_instancessql === null) {
361             $instances = $this->get_enrolment_instances();
362             $filter = $this->get_enrolment_filter();
363             if ($filter && array_key_exists($filter, $instances)) {
364                 $sql = " = :ifilter";
365                 $params = array('ifilter'=>$filter);
366             } else {
367                 $filter = 0;
368                 if ($instances) {
369                     list($sql, $params) = $DB->get_in_or_equal(array_keys($this->get_enrolment_instances()), SQL_PARAMS_NAMED);
370                 } else {
371                     // no enabled instances, oops, we should probably say something
372                     $sql = "= :never";
373                     $params = array('never'=>-1);
374                 }
375             }
376             $this->instancefilter = $filter;
377             $this->_instancessql = array($sql, $params, $filter);
378         }
379         return $this->_instancessql;
380     }
382     /**
383      * Returns all of the enrolment instances for this course.
384      *
385      * @return array
386      */
387     public function get_enrolment_instances() {
388         if ($this->_instances === null) {
389             $this->_instances = enrol_get_instances($this->course->id, true);
390         }
391         return $this->_instances;
392     }
394     /**
395      * Returns the names for all of the enrolment instances for this course.
396      *
397      * @return array
398      */
399     public function get_enrolment_instance_names() {
400         if ($this->_inames === null) {
401             $instances = $this->get_enrolment_instances();
402             $plugins = $this->get_enrolment_plugins();
403             foreach ($instances as $key=>$instance) {
404                 if (!isset($plugins[$instance->enrol])) {
405                     // weird, some broken stuff in plugin
406                     unset($instances[$key]);
407                     continue;
408                 }
409                 $this->_inames[$key] = $plugins[$instance->enrol]->get_instance_name($instance);
410             }
411         }
412         return $this->_inames;
413     }
415     /**
416      * Gets all of the enrolment plugins that are active for this course.
417      *
418      * @return array
419      */
420     public function get_enrolment_plugins() {
421         if ($this->_plugins === null) {
422             $this->_plugins = enrol_get_plugins(true);
423         }
424         return $this->_plugins;
425     }
427     /**
428      * Gets all of the roles this course can contain.
429      *
430      * @return array
431      */
432     public function get_all_roles() {
433         if ($this->_roles === null) {
434             $this->_roles = role_fix_names(get_all_roles(), $this->context);
435         }
436         return $this->_roles;
437     }
439     /**
440      * Gets all of the assignable roles for this course.
441      *
442      * @return array
443      */
444     public function get_assignable_roles($otherusers = false) {
445         if ($this->_assignableroles === null) {
446             $this->_assignableroles = get_assignable_roles($this->context, ROLENAME_ALIAS, false); // verifies unassign access control too
447         }
449         if ($otherusers) {
450             if (!is_array($this->_assignablerolesothers)) {
451                 $this->_assignablerolesothers = array();
452                 list($courseviewroles, $ignored) = get_roles_with_cap_in_context($this->context, 'moodle/course:view');
453                 foreach ($this->_assignableroles as $roleid=>$role) {
454                     if (isset($courseviewroles[$roleid])) {
455                         $this->_assignablerolesothers[$roleid] = $role;
456                     }
457                 }
458             }
459             return $this->_assignablerolesothers;
460         } else {
461             return $this->_assignableroles;
462         }
463     }
465     /**
466      * Gets all of the groups for this course.
467      *
468      * @return array
469      */
470     public function get_all_groups() {
471         if ($this->_groups === null) {
472             $this->_groups = groups_get_all_groups($this->course->id);
473             foreach ($this->_groups as $gid=>$group) {
474                 $this->_groups[$gid]->name = format_string($group->name);
475             }
476         }
477         return $this->_groups;
478     }
480     /**
481      * Unenrols a user from the course given the users ue entry
482      *
483      * @global moodle_database $DB
484      * @param stdClass $ue
485      * @return bool
486      */
487     public function unenrol_user($ue) {
488         global $DB;
489         list ($instance, $plugin) = $this->get_user_enrolment_components($ue);
490         if ($instance && $plugin && $plugin->allow_unenrol($instance) && has_capability("enrol/$instance->enrol:unenrol", $this->context)) {
491             $plugin->unenrol_user($instance, $ue->userid);
492             return true;
493         }
494         return false;
495     }
497     /**
498      * Given a user enrolment record this method returns the plugin and enrolment
499      * instance that relate to it.
500      *
501      * @param stdClass|int $userenrolment
502      * @return array array($instance, $plugin)
503      */
504     public function get_user_enrolment_components($userenrolment) {
505         global $DB;
506         if (is_numeric($userenrolment)) {
507             $userenrolment = $DB->get_record('user_enrolments', array('id'=>(int)$userenrolment));
508         }
509         $instances = $this->get_enrolment_instances();
510         $plugins = $this->get_enrolment_plugins();
511         if (!$userenrolment || !isset($instances[$userenrolment->enrolid])) {
512             return array(false, false);
513         }
514         $instance = $instances[$userenrolment->enrolid];
515         $plugin = $plugins[$instance->enrol];
516         return array($instance, $plugin);
517     }
519     /**
520      * Removes an assigned role from a user.
521      *
522      * @global moodle_database $DB
523      * @param int $userid
524      * @param int $roleid
525      * @return bool
526      */
527     public function unassign_role_from_user($userid, $roleid) {
528         global $DB;
529         require_capability('moodle/role:assign', $this->context);
530         $user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
531         try {
532             role_unassign($roleid, $user->id, $this->context->id, '', NULL);
533         } catch (Exception $e) {
534             if (is_defined('AJAX_SCRIPT')) {
535                 throw $e;
536             }
537             return false;
538         }
539         return true;
540     }
542     /**
543      * Assigns a role to a user.
544      *
545      * @param int $roleid
546      * @param int $userid
547      * @return int|false
548      */
549     public function assign_role_to_user($roleid, $userid) {
550         require_capability('moodle/role:assign', $this->context);
551         if (!array_key_exists($roleid, $this->get_assignable_roles())) {
552             if (is_defined('AJAX_SCRIPT')) {
553                 throw new moodle_;
554             }
555             return false;
556         }
557         return role_assign($roleid, $userid, $this->context->id, '', NULL);
558     }
560     /**
561      * Adds a user to a group
562      *
563      * @param stdClass $user
564      * @param int $groupid
565      * @return bool
566      */
567     public function add_user_to_group($user, $groupid) {
568         require_capability('moodle/course:managegroups', $this->context);
569         $group = $this->get_group($groupid);
570         if (!$group) {
571             return false;
572         }
573         return groups_add_member($group->id, $user->id);
574     }
576     /**
577      * Removes a user from a group
578      *
579      * @global moodle_database $DB
580      * @param StdClass $user
581      * @param int $groupid
582      * @return bool
583      */
584     public function remove_user_from_group($user, $groupid) {
585         global $DB;
586         require_capability('moodle/course:managegroups', $this->context);
587         $group = $this->get_group($groupid);
588         if (!$group) {
589             return false;
590         }
591         return groups_remove_member($group, $user);
592     }
594     /**
595      * Gets the requested group
596      *
597      * @param int $groupid
598      * @return stdClass|int
599      */
600     public function get_group($groupid) {
601         $groups = $this->get_all_groups();
602         if (!array_key_exists($groupid, $groups)) {
603             return false;
604         }
605         return $groups[$groupid];
606     }
608     /**
609      * Edits an enrolment
610      *
611      * @param stdClass $userenrolment
612      * @param stdClass $data
613      * @return bool
614      */
615     public function edit_enrolment($userenrolment, $data) {
616         list($instance, $plugin) = $this->get_user_enrolment_components($ue);
617         if ($instance && $plugin && $plugin->allow_manage($instance) && has_capability("enrol/$instance->enrol:manage", $this->context)) {
618             if (!isset($data->status)) {
619                 $data->status = $userenrolment->status;
620             }
621             $plugin->update_user_enrol($instance, $userenrolment->userid, $data->status, $data->timestart, $data->timeend);
622             return true;
623         }
624         return false;
625     }
627     /**
628      * Returns the current enrolment filter that is being applied by this class
629      * @return string
630      */
631     public function get_enrolment_filter() {
632         return $this->instancefilter;
633     }
635     /**
636      * Gets the roles assigned to this user that are applicable for this course.
637      *
638      * @param int $userid
639      * @return array
640      */
641     public function get_user_roles($userid) {
642         $roles = array();
643         $ras = get_user_roles($this->context, $userid, true, 'c.contextlevel DESC, r.sortorder ASC');
644         foreach ($ras as $ra) {
645             if ($ra->contextid != $this->context->id) {
646                 if (!array_key_exists($ra->roleid, $roles)) {
647                     $roles[$ra->roleid] = null;
648                 }
649                 // higher ras, course always takes precedence
650                 continue;
651             }
652             if (array_key_exists($ra->roleid, $roles) && $roles[$ra->roleid] === false) {
653                 continue;
654             }
655             $roles[$ra->roleid] = ($ra->itemid == 0 and $ra->component === '');
656         }
657         return $roles;
658     }
660     /**
661      * Gets the enrolments this user has in the course
662      *
663      * @global moodle_database $DB
664      * @param int $userid
665      * @return array
666      */
667     public function get_user_enrolments($userid) {
668         global $DB;
669         list($instancessql, $params, $filter) = $this->get_instance_sql();
670         $params['userid'] = $userid;
671         $userenrolments = $DB->get_records_select('user_enrolments', "enrolid $instancessql AND userid = :userid", $params);
672         $instances = $this->get_enrolment_instances();
673         $plugins = $this->get_enrolment_plugins();
674         $inames = $this->get_enrolment_instance_names();
675         foreach ($userenrolments as &$ue) {
676             $ue->enrolmentinstance     = $instances[$ue->enrolid];
677             $ue->enrolmentplugin       = $plugins[$ue->enrolmentinstance->enrol];
678             $ue->enrolmentinstancename = $inames[$ue->enrolmentinstance->id];
679         }
680         return $userenrolments;
681     }
683     /**
684      * Gets the groups this user belongs to
685      *
686      * @param int $userid
687      * @return array
688      */
689     public function get_user_groups($userid) {
690         return groups_get_all_groups($this->course->id, $userid, 0, 'g.id');
691     }
693     /**
694      * Retursn an array of params that would go into the URL to return to this
695      * exact page.
696      *
697      * @return array
698      */
699     public function get_url_params() {
700         $args = array(
701             'id' => $this->course->id
702         );
703         if (!empty($this->instancefilter)) {
704             $args['ifilter'] = $this->instancefilter;
705         }
706         return $args;
707     }
709     /**
710      * Returns the course this object is managing enrolments for
711      *
712      * @return stdClass
713      */
714     public function get_course() {
715         return $this->course;
716     }
718     /**
719      * Returns the course context
720      *
721      * @return stdClass
722      */
723     public function get_context() {
724         return $this->context;
725     }
727     /**
728      * Gets an array of other users in this course ready for display.
729      *
730      * Other users are users who have been assigned or inherited roles within this
731      * course but have not been enrolled.
732      *
733      * @param core_enrol_renderer $renderer
734      * @param moodle_url $pageurl
735      * @param string $sort
736      * @param string $direction ASC | DESC
737      * @param int $page Starting from 0
738      * @param int $perpage
739      * @return array
740      */
741     public function get_other_users_for_display(core_enrol_renderer $renderer, moodle_url $pageurl, $sort, $direction, $page, $perpage) {
743         $userroles = $this->get_other_users($sort, $direction, $page, $perpage);
744         $roles = $this->get_all_roles();
746         $courseid   = $this->get_course()->id;
747         $context    = $this->get_context();
749         $users = array();
750         foreach ($userroles as $userrole) {
751             if (!array_key_exists($userrole->id, $users)) {
752                 $users[$userrole->id] = array(
753                     'userid'     => $userrole->id,
754                     'courseid'   => $courseid,
755                     'picture'    => new user_picture($userrole),
756                     'firstname'  => fullname($userrole, true),
757                     'email'      => $userrole->email,
758                     'roles'      => array()
759                 );
760             }
761             $a = new stdClass;
762             $a->role = $roles[$userrole->roleid]->localname;
763             $changeable = ($userrole->component == '');
764             if ($userrole->contextid == $this->context->id) {
765                 $roletext = get_string('rolefromthiscourse', 'enrol', $a);
766             } else {
767                 $changeable = false;
768                 switch ($userrole->contextlevel) {
769                     case CONTEXT_COURSE :
770                         // Meta course
771                         $roletext = get_string('rolefrommetacourse', 'enrol', $a);
772                         break;
773                     case CONTEXT_COURSECAT :
774                         $roletext = get_string('rolefromcategory', 'enrol', $a);
775                         break;
776                     case CONTEXT_SYSTEM:
777                     default:
778                         $roletext = get_string('rolefromsystem', 'enrol', $a);
779                         break;
780                 }
781             }
782             $users[$userrole->id]['roles'][$userrole->roleid] = array(
783                 'text' => $roletext,
784                 'unchangeable' => !$changeable
785             );
786         }
787         return $users;
788     }
790     /**
791      * Gets all the cohorts the user is able to view.
792      *
793      * @global moodle_database $DB
794      * @return array
795      */
796     public function get_cohorts() {
797         global $DB;
798         $context = $this->get_context();
799         $cohorts = array();
800         $instances = $this->get_enrolment_instances();
801         $enrolled = array();
802         foreach ($instances as $instance) {
803             if ($instance->enrol == 'cohort') {
804                 $enrolled[] = $instance->customint1;
805             }
806         }
807         list($sqlparents, $params) = $DB->get_in_or_equal(get_parent_contexts($context));
808         $sql = "SELECT id, name, contextid
809                   FROM {cohort}
810                  WHERE contextid $sqlparents
811               ORDER BY name ASC";
812         $rs = $DB->get_recordset_sql($sql, $params);
813         foreach ($rs as $c) {
814             $context = get_context_instance_by_id($c->contextid);
815             if (!has_capability('moodle/cohort:view', $context)) {
816                 continue;
817             }
818             $cohorts[$c->id] = array(
819                 'cohortid'=>$c->id,
820                 'name'=>format_string($c->name),
821                 'users'=>$DB->count_records('cohort_members', array('cohortid'=>$c->id)),
822                 'enrolled'=>in_array($c->id, $enrolled)
823             );
824         }
825         $rs->close();
826         return $cohorts;
827     }
829     /**
830      * Enrols a cohort in a course.
831      *
832      * Essentially this just adds a cohort enrolment plugin instance to the course
833      *
834      * @param int $cohortid
835      * @param int $roleid
836      * @return bool
837      */
838     public function enrol_cohort($cohortid, $roleid) {
839         global $CFG;
840         require_capability('moodle/course:enrolconfig', $this->get_context());
841         require_once($CFG->dirroot.'/enrol/cohort/locallib.php');
842         $roles = $this->get_assignable_roles();
843         $cohorts = $this->get_cohorts();
844         if (!array_key_exists($cohortid, $cohorts) || !array_key_exists($roleid, $roles)) {
845             return false;
846         }
847         $enrol = enrol_get_plugin('cohort');
848         $enrol->add_instance($this->course, array('customint1'=>$cohortid, 'roleid'=>$roleid));
849         enrol_cohort_sync($this->course->id);
850         return true;
851     }
853     /**
854      * Enrols all of the users in a cohort within this course.
855      *
856      * Note this is VERY different from creating an enrolment instance for a cohort.
857      *
858      * @global moodle_database $DB
859      * @param int $cohortid
860      * @param int $roleid
861      * @return bool
862      */
863     public function enrol_cohort_users($cohortid, $roleid) {
864         global $DB;
865         require_capability('moodle/course:enrolconfig', $this->get_context());
866         $instance = false;
867         $instances = $this->get_enrolment_instances();
868         foreach ($instances as $i) {
869             if ($i->enrol == 'manual') {
870                 $instance = $i;
871                 break;
872             }
873         }
874         $plugin = enrol_get_plugin('manual');
875         if (!$instance || !$plugin || !$plugin->allow_enrol($instance) || !has_capability('enrol/'.$plugin->get_name().':enrol', $this->get_context())) {
876             return false;
877         }
878         $sql = "SELECT com.userid
879                 FROM {cohort_members} com
880                 LEFT JOIN (
881                     SELECT *
882                     FROM {user_enrolments} ue
883                     WHERE ue.enrolid = :enrolid
884                 ) ue ON ue.userid=com.userid
885                 WHERE com.cohortid = :cohortid AND ue.id IS NULL";
886         $params = array('cohortid'=>$cohortid, 'enrolid'=>$instance->id);
887         $rs = $DB->get_recordset_sql($sql, $params);
888         $count = 0;
889         foreach ($rs as $user) {
890             $count++;
891             $plugin->enrol_user($instance, $user->userid, $roleid);
892         }
893         $rs->close();
894         return $count;
895     }
897     /**
898      * Gets an array of users for display, this includes minimal user information
899      * as well as minimal information on the users roles, groups, and enrolments.
900      *
901      * @param core_enrol_renderer $renderer
902      * @param moodle_url $pageurl
903      * @param int $sort
904      * @param string $direction ASC or DESC
905      * @param int $page
906      * @param int $perpage
907      * @return array
908      */
909     public function get_users_for_display(core_enrol_renderer $renderer, moodle_url $pageurl, $sort, $direction, $page, $perpage) {
910         $users = $this->get_users($sort, $direction, $page, $perpage);
912         $now = time();
913         $strnever = get_string('never');
914         $straddgroup = get_string('addgroup', 'group');
915         $strunenrol = get_string('unenrol', 'enrol');
916         $stredit = get_string('edit');
918         $iconedit        = $renderer->pix_url('t/edit');
919         $iconenroladd    = $renderer->pix_url('t/enroladd');
920         $iconenrolremove = $renderer->pix_url('t/delete');
922         $allroles   = $this->get_all_roles();
923         $assignable = $this->get_assignable_roles();
924         $allgroups  = $this->get_all_groups();
925         $courseid   = $this->get_course()->id;
926         $context    = $this->get_context();
927         $canmanagegroups = has_capability('moodle/course:managegroups', $context);
929         $url = new moodle_url($pageurl, $this->get_url_params());
931         $userdetails = array();
932         foreach ($users as $user) {
933             $details = array(
934                 'userid'     => $user->id,
935                 'courseid'   => $courseid,
936                 'picture'    => new user_picture($user),
937                 'firstname'  => fullname($user, true),
938                 'email'      => $user->email,
939                 'lastseen'   => $strnever,
940                 'roles'      => array(),
941                 'groups'     => array(),
942                 'enrolments' => array()
943             );
945             if ($user->lastaccess) {
946                 $details['lastseen'] = format_time($now - $user->lastaccess);
947             }
949             // Roles
950             foreach ($this->get_user_roles($user->id) as $rid=>$rassignable) {
951                 $details['roles'][$rid] = array('text'=>$allroles[$rid]->localname, 'unchangeable'=>(!$rassignable || !isset($assignable[$rid])));
952             }
954             // Users
955             $usergroups = $this->get_user_groups($user->id);
956             foreach($usergroups as $gid=>$unused) {
957                 $details['groups'][$gid] = $allgroups[$gid]->name;
958             }
960             // Enrolments
961             foreach ($this->get_user_enrolments($user->id) as $ue) {
962                 if ($ue->timestart and $ue->timeend) {
963                     $period = get_string('periodstartend', 'enrol', array('start'=>userdate($ue->timestart), 'end'=>userdate($ue->timeend)));
964                     $periodoutside = ($ue->timestart && $ue->timeend && $now < $ue->timestart && $now > $ue->timeend);
965                 } else if ($ue->timestart) {
966                     $period = get_string('periodstart', 'enrol', userdate($ue->timestart));
967                     $periodoutside = ($ue->timestart && $now < $ue->timestart);
968                 } else if ($ue->timeend) {
969                     $period = get_string('periodend', 'enrol', userdate($ue->timeend));
970                     $periodoutside = ($ue->timeend && $now > $ue->timeend);
971                 } else {
972                     $period = '';
973                     $periodoutside = false;
974                 }
975                 $details['enrolments'][$ue->id] = array(
976                     'text' => $ue->enrolmentinstancename,
977                     'period' => $period,
978                     'dimmed' =>  ($periodoutside || $ue->status != ENROL_USER_ACTIVE),
979                     'canunenrol' => ($ue->enrolmentplugin->allow_unenrol($ue->enrolmentinstance) && has_capability("enrol/".$ue->enrolmentinstance->enrol.":unenrol", $context)),
980                     'canmanage' => ($ue->enrolmentplugin->allow_manage($ue->enrolmentinstance) && has_capability("enrol/".$ue->enrolmentinstance->enrol.":manage", $context))
981                 );
982             }
983             $userdetails[$user->id] = $details;
984         }
985         return $userdetails;
986     }
989 class enrol_ajax_exception extends moodle_exception {
990     /**
991      * Constructor
992      * @param string $errorcode The name of the string from error.php to print
993      * @param string $module name of module
994      * @param string $link The url where the user will be prompted to continue. If no url is provided the user will be directed to the site index page.
995      * @param object $a Extra words and phrases that might be required in the error string
996      * @param string $debuginfo optional debugging information
997      */
998     public function __construct($errorcode, $link = '', $a = NULL, $debuginfo = null) {
999         parent::__construct($errorcode, 'enrol', $link, $a, $debuginfo);
1000     }