MDL-21437 data - checkbox and multimenu fields search working + require all too
[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, $CFG;
262         // Add some additional sensible conditions
263         $tests = array("id <> :guestid", 'u.deleted = 0', 'u.confirmed = 1');
264         $params = array('guestid' => $CFG->siteguest);
265         if (!empty($search)) {
266             $conditions = array(
267                 $DB->sql_concat('u.firstname', "' '", 'u.lastname'),
268                 'u.email'
269             );
270             if ($searchanywhere) {
271                 $searchparam = '%' . $search . '%';
272             } else {
273                 $searchparam = $search . '%';
274             }
275             $i = 0;
276             foreach ($conditions as $key=>$condition) {
277                 $conditions[$key] = $DB->sql_like($condition,":con{$i}00", false);
278                 $params["con{$i}00"] = $searchparam;
279                 $i++;
280             }
281             $tests[] = '(' . implode(' OR ', $conditions) . ')';
282         }
283         $wherecondition = implode(' AND ', $tests);
285         $ufields = user_picture::fields('u');
287         $fields      = 'SELECT u.id, u.firstname, u.lastname, u.username, u.email, u.lastaccess, u.picture, u.imagealt, '.$ufields;
288         $countfields = 'SELECT COUNT(1)';
289         $sql = " FROM {user} u
290                 WHERE $wherecondition
291                       AND u.id NOT IN (SELECT ue.userid
292                                          FROM {user_enrolments} ue
293                                          JOIN {enrol} e ON (e.id = ue.enrolid AND e.id = :enrolid))";
294         $order = ' ORDER BY u.lastname ASC, u.firstname ASC';
295         $params['enrolid'] = $enrolid;
296         $totalusers = $DB->count_records_sql($countfields . $sql, $params);
297         $availableusers = $DB->get_records_sql($fields . $sql . $order, $params, $page*$perpage, $perpage);
298         return array('totalusers'=>$totalusers, 'users'=>$availableusers);
299     }
301     /**
302      * Searches other users and returns paginated results
303      *
304      * @global moodle_database $DB
305      * @param string $search
306      * @param bool $searchanywhere
307      * @param int $page Starting at 0
308      * @param int $perpage
309      * @return array
310      */
311     public function search_other_users($search='', $searchanywhere=false, $page=0, $perpage=25) {
312         global $DB, $CFG;
314         // Add some additional sensible conditions
315         $tests = array("u.id <> :guestid", 'u.deleted = 0', 'u.confirmed = 1');
316         $params = array('guestid'=>$CFG->siteguest);
317         if (!empty($search)) {
318             $conditions = array('u.firstname','u.lastname');
319             if ($searchanywhere) {
320                 $searchparam = '%' . $search . '%';
321             } else {
322                 $searchparam = $search . '%';
323             }
324             $i = 0;
325             foreach ($conditions as $key=>$condition) {
326                 $conditions[$key] = $DB->sql_like($condition, ":con{$i}00", false);
327                 $params["con{$i}00"] = $searchparam;
328                 $i++;
329             }
330             $tests[] = '(' . implode(' OR ', $conditions) . ')';
331         }
332         $wherecondition = implode(' AND ', $tests);
335         $fields      = 'SELECT u.id, u.firstname, u.lastname, u.username, u.email, u.lastaccess, u.picture, u.imagealt, '.user_picture::fields('u');;
336         $countfields = 'SELECT COUNT(u.id)';
337         $sql   = " FROM {user} u
338                   WHERE $wherecondition
339                         AND u.id NOT IN (
340                            SELECT u.id
341                              FROM {role_assignments} r, {user} u
342                             WHERE r.contextid = :contextid
343                                   AND u.id = r.userid)";
344         $order = ' ORDER BY lastname ASC, firstname ASC';
346         $params['contextid'] = $this->context->id;
347         $totalusers = $DB->count_records_sql($countfields . $sql, $params);
348         $availableusers = $DB->get_records_sql($fields . $sql . $order, $params, $page*$perpage, $perpage);
349         return array('totalusers'=>$totalusers, 'users'=>$availableusers);
350     }
352     /**
353      * Gets an array containing some SQL to user for when selecting, params for
354      * that SQL, and the filter that was used in constructing the sql.
355      *
356      * @global moodle_database $DB
357      * @return string
358      */
359     protected function get_instance_sql() {
360         global $DB;
361         if ($this->_instancessql === null) {
362             $instances = $this->get_enrolment_instances();
363             $filter = $this->get_enrolment_filter();
364             if ($filter && array_key_exists($filter, $instances)) {
365                 $sql = " = :ifilter";
366                 $params = array('ifilter'=>$filter);
367             } else {
368                 $filter = 0;
369                 if ($instances) {
370                     list($sql, $params) = $DB->get_in_or_equal(array_keys($this->get_enrolment_instances()), SQL_PARAMS_NAMED);
371                 } else {
372                     // no enabled instances, oops, we should probably say something
373                     $sql = "= :never";
374                     $params = array('never'=>-1);
375                 }
376             }
377             $this->instancefilter = $filter;
378             $this->_instancessql = array($sql, $params, $filter);
379         }
380         return $this->_instancessql;
381     }
383     /**
384      * Returns all of the enrolment instances for this course.
385      *
386      * @return array
387      */
388     public function get_enrolment_instances() {
389         if ($this->_instances === null) {
390             $this->_instances = enrol_get_instances($this->course->id, true);
391         }
392         return $this->_instances;
393     }
395     /**
396      * Returns the names for all of the enrolment instances for this course.
397      *
398      * @return array
399      */
400     public function get_enrolment_instance_names() {
401         if ($this->_inames === null) {
402             $instances = $this->get_enrolment_instances();
403             $plugins = $this->get_enrolment_plugins();
404             foreach ($instances as $key=>$instance) {
405                 if (!isset($plugins[$instance->enrol])) {
406                     // weird, some broken stuff in plugin
407                     unset($instances[$key]);
408                     continue;
409                 }
410                 $this->_inames[$key] = $plugins[$instance->enrol]->get_instance_name($instance);
411             }
412         }
413         return $this->_inames;
414     }
416     /**
417      * Gets all of the enrolment plugins that are active for this course.
418      *
419      * @return array
420      */
421     public function get_enrolment_plugins() {
422         if ($this->_plugins === null) {
423             $this->_plugins = enrol_get_plugins(true);
424         }
425         return $this->_plugins;
426     }
428     /**
429      * Gets all of the roles this course can contain.
430      *
431      * @return array
432      */
433     public function get_all_roles() {
434         if ($this->_roles === null) {
435             $this->_roles = role_fix_names(get_all_roles(), $this->context);
436         }
437         return $this->_roles;
438     }
440     /**
441      * Gets all of the assignable roles for this course.
442      *
443      * @return array
444      */
445     public function get_assignable_roles($otherusers = false) {
446         if ($this->_assignableroles === null) {
447             $this->_assignableroles = get_assignable_roles($this->context, ROLENAME_ALIAS, false); // verifies unassign access control too
448         }
450         if ($otherusers) {
451             if (!is_array($this->_assignablerolesothers)) {
452                 $this->_assignablerolesothers = array();
453                 list($courseviewroles, $ignored) = get_roles_with_cap_in_context($this->context, 'moodle/course:view');
454                 foreach ($this->_assignableroles as $roleid=>$role) {
455                     if (isset($courseviewroles[$roleid])) {
456                         $this->_assignablerolesothers[$roleid] = $role;
457                     }
458                 }
459             }
460             return $this->_assignablerolesothers;
461         } else {
462             return $this->_assignableroles;
463         }
464     }
466     /**
467      * Gets all of the groups for this course.
468      *
469      * @return array
470      */
471     public function get_all_groups() {
472         if ($this->_groups === null) {
473             $this->_groups = groups_get_all_groups($this->course->id);
474             foreach ($this->_groups as $gid=>$group) {
475                 $this->_groups[$gid]->name = format_string($group->name);
476             }
477         }
478         return $this->_groups;
479     }
481     /**
482      * Unenrols a user from the course given the users ue entry
483      *
484      * @global moodle_database $DB
485      * @param stdClass $ue
486      * @return bool
487      */
488     public function unenrol_user($ue) {
489         global $DB;
490         list ($instance, $plugin) = $this->get_user_enrolment_components($ue);
491         if ($instance && $plugin && $plugin->allow_unenrol($instance) && has_capability("enrol/$instance->enrol:unenrol", $this->context)) {
492             $plugin->unenrol_user($instance, $ue->userid);
493             return true;
494         }
495         return false;
496     }
498     /**
499      * Given a user enrolment record this method returns the plugin and enrolment
500      * instance that relate to it.
501      *
502      * @param stdClass|int $userenrolment
503      * @return array array($instance, $plugin)
504      */
505     public function get_user_enrolment_components($userenrolment) {
506         global $DB;
507         if (is_numeric($userenrolment)) {
508             $userenrolment = $DB->get_record('user_enrolments', array('id'=>(int)$userenrolment));
509         }
510         $instances = $this->get_enrolment_instances();
511         $plugins = $this->get_enrolment_plugins();
512         if (!$userenrolment || !isset($instances[$userenrolment->enrolid])) {
513             return array(false, false);
514         }
515         $instance = $instances[$userenrolment->enrolid];
516         $plugin = $plugins[$instance->enrol];
517         return array($instance, $plugin);
518     }
520     /**
521      * Removes an assigned role from a user.
522      *
523      * @global moodle_database $DB
524      * @param int $userid
525      * @param int $roleid
526      * @return bool
527      */
528     public function unassign_role_from_user($userid, $roleid) {
529         global $DB;
530         require_capability('moodle/role:assign', $this->context);
531         $user = $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
532         try {
533             role_unassign($roleid, $user->id, $this->context->id, '', NULL);
534         } catch (Exception $e) {
535             if (defined('AJAX_SCRIPT')) {
536                 throw $e;
537             }
538             return false;
539         }
540         return true;
541     }
543     /**
544      * Assigns a role to a user.
545      *
546      * @param int $roleid
547      * @param int $userid
548      * @return int|false
549      */
550     public function assign_role_to_user($roleid, $userid) {
551         require_capability('moodle/role:assign', $this->context);
552         if (!array_key_exists($roleid, $this->get_assignable_roles())) {
553             if (defined('AJAX_SCRIPT')) {
554                 throw new moodle_exception('invalidrole');
555             }
556             return false;
557         }
558         return role_assign($roleid, $userid, $this->context->id, '', NULL);
559     }
561     /**
562      * Adds a user to a group
563      *
564      * @param stdClass $user
565      * @param int $groupid
566      * @return bool
567      */
568     public function add_user_to_group($user, $groupid) {
569         require_capability('moodle/course:managegroups', $this->context);
570         $group = $this->get_group($groupid);
571         if (!$group) {
572             return false;
573         }
574         return groups_add_member($group->id, $user->id);
575     }
577     /**
578      * Removes a user from a group
579      *
580      * @global moodle_database $DB
581      * @param StdClass $user
582      * @param int $groupid
583      * @return bool
584      */
585     public function remove_user_from_group($user, $groupid) {
586         global $DB;
587         require_capability('moodle/course:managegroups', $this->context);
588         $group = $this->get_group($groupid);
589         if (!$group) {
590             return false;
591         }
592         return groups_remove_member($group, $user);
593     }
595     /**
596      * Gets the requested group
597      *
598      * @param int $groupid
599      * @return stdClass|int
600      */
601     public function get_group($groupid) {
602         $groups = $this->get_all_groups();
603         if (!array_key_exists($groupid, $groups)) {
604             return false;
605         }
606         return $groups[$groupid];
607     }
609     /**
610      * Edits an enrolment
611      *
612      * @param stdClass $userenrolment
613      * @param stdClass $data
614      * @return bool
615      */
616     public function edit_enrolment($userenrolment, $data) {
617         list($instance, $plugin) = $this->get_user_enrolment_components($userenrolment);
618         if ($instance && $plugin && $plugin->allow_manage($instance) && has_capability("enrol/$instance->enrol:manage", $this->context)) {
619             if (!isset($data->status)) {
620                 $data->status = $userenrolment->status;
621             }
622             $plugin->update_user_enrol($instance, $userenrolment->userid, $data->status, $data->timestart, $data->timeend);
623             return true;
624         }
625         return false;
626     }
628     /**
629      * Returns the current enrolment filter that is being applied by this class
630      * @return string
631      */
632     public function get_enrolment_filter() {
633         return $this->instancefilter;
634     }
636     /**
637      * Gets the roles assigned to this user that are applicable for this course.
638      *
639      * @param int $userid
640      * @return array
641      */
642     public function get_user_roles($userid) {
643         $roles = array();
644         $ras = get_user_roles($this->context, $userid, true, 'c.contextlevel DESC, r.sortorder ASC');
645         foreach ($ras as $ra) {
646             if ($ra->contextid != $this->context->id) {
647                 if (!array_key_exists($ra->roleid, $roles)) {
648                     $roles[$ra->roleid] = null;
649                 }
650                 // higher ras, course always takes precedence
651                 continue;
652             }
653             if (array_key_exists($ra->roleid, $roles) && $roles[$ra->roleid] === false) {
654                 continue;
655             }
656             $roles[$ra->roleid] = ($ra->itemid == 0 and $ra->component === '');
657         }
658         return $roles;
659     }
661     /**
662      * Gets the enrolments this user has in the course
663      *
664      * @global moodle_database $DB
665      * @param int $userid
666      * @return array
667      */
668     public function get_user_enrolments($userid) {
669         global $DB;
670         list($instancessql, $params, $filter) = $this->get_instance_sql();
671         $params['userid'] = $userid;
672         $userenrolments = $DB->get_records_select('user_enrolments', "enrolid $instancessql AND userid = :userid", $params);
673         $instances = $this->get_enrolment_instances();
674         $plugins = $this->get_enrolment_plugins();
675         $inames = $this->get_enrolment_instance_names();
676         foreach ($userenrolments as &$ue) {
677             $ue->enrolmentinstance     = $instances[$ue->enrolid];
678             $ue->enrolmentplugin       = $plugins[$ue->enrolmentinstance->enrol];
679             $ue->enrolmentinstancename = $inames[$ue->enrolmentinstance->id];
680         }
681         return $userenrolments;
682     }
684     /**
685      * Gets the groups this user belongs to
686      *
687      * @param int $userid
688      * @return array
689      */
690     public function get_user_groups($userid) {
691         return groups_get_all_groups($this->course->id, $userid, 0, 'g.id');
692     }
694     /**
695      * Retursn an array of params that would go into the URL to return to this
696      * exact page.
697      *
698      * @return array
699      */
700     public function get_url_params() {
701         $args = array(
702             'id' => $this->course->id
703         );
704         if (!empty($this->instancefilter)) {
705             $args['ifilter'] = $this->instancefilter;
706         }
707         return $args;
708     }
710     /**
711      * Returns the course this object is managing enrolments for
712      *
713      * @return stdClass
714      */
715     public function get_course() {
716         return $this->course;
717     }
719     /**
720      * Returns the course context
721      *
722      * @return stdClass
723      */
724     public function get_context() {
725         return $this->context;
726     }
728     /**
729      * Gets an array of other users in this course ready for display.
730      *
731      * Other users are users who have been assigned or inherited roles within this
732      * course but have not been enrolled.
733      *
734      * @param core_enrol_renderer $renderer
735      * @param moodle_url $pageurl
736      * @param string $sort
737      * @param string $direction ASC | DESC
738      * @param int $page Starting from 0
739      * @param int $perpage
740      * @return array
741      */
742     public function get_other_users_for_display(core_enrol_renderer $renderer, moodle_url $pageurl, $sort, $direction, $page, $perpage) {
744         $userroles = $this->get_other_users($sort, $direction, $page, $perpage);
745         $roles = $this->get_all_roles();
747         $courseid   = $this->get_course()->id;
748         $context    = $this->get_context();
750         $users = array();
751         foreach ($userroles as $userrole) {
752             if (!array_key_exists($userrole->id, $users)) {
753                 $users[$userrole->id] = array(
754                     'userid'     => $userrole->id,
755                     'courseid'   => $courseid,
756                     'picture'    => new user_picture($userrole),
757                     'firstname'  => fullname($userrole, true),
758                     'email'      => $userrole->email,
759                     'roles'      => array()
760                 );
761             }
762             $a = new stdClass;
763             $a->role = $roles[$userrole->roleid]->localname;
764             $changeable = ($userrole->component == '');
765             if ($userrole->contextid == $this->context->id) {
766                 $roletext = get_string('rolefromthiscourse', 'enrol', $a);
767             } else {
768                 $changeable = false;
769                 switch ($userrole->contextlevel) {
770                     case CONTEXT_COURSE :
771                         // Meta course
772                         $roletext = get_string('rolefrommetacourse', 'enrol', $a);
773                         break;
774                     case CONTEXT_COURSECAT :
775                         $roletext = get_string('rolefromcategory', 'enrol', $a);
776                         break;
777                     case CONTEXT_SYSTEM:
778                     default:
779                         $roletext = get_string('rolefromsystem', 'enrol', $a);
780                         break;
781                 }
782             }
783             $users[$userrole->id]['roles'][$userrole->roleid] = array(
784                 'text' => $roletext,
785                 'unchangeable' => !$changeable
786             );
787         }
788         return $users;
789     }
791     /**
792      * Gets all the cohorts the user is able to view.
793      *
794      * @global moodle_database $DB
795      * @return array
796      */
797     public function get_cohorts() {
798         global $DB;
799         $context = $this->get_context();
800         $cohorts = array();
801         $instances = $this->get_enrolment_instances();
802         $enrolled = array();
803         foreach ($instances as $instance) {
804             if ($instance->enrol == 'cohort') {
805                 $enrolled[] = $instance->customint1;
806             }
807         }
808         list($sqlparents, $params) = $DB->get_in_or_equal(get_parent_contexts($context));
809         $sql = "SELECT id, name, contextid
810                   FROM {cohort}
811                  WHERE contextid $sqlparents
812               ORDER BY name ASC";
813         $rs = $DB->get_recordset_sql($sql, $params);
814         foreach ($rs as $c) {
815             $context = get_context_instance_by_id($c->contextid);
816             if (!has_capability('moodle/cohort:view', $context)) {
817                 continue;
818             }
819             $cohorts[$c->id] = array(
820                 'cohortid'=>$c->id,
821                 'name'=>format_string($c->name),
822                 'users'=>$DB->count_records('cohort_members', array('cohortid'=>$c->id)),
823                 'enrolled'=>in_array($c->id, $enrolled)
824             );
825         }
826         $rs->close();
827         return $cohorts;
828     }
830     /**
831      * Enrols a cohort in a course.
832      *
833      * Essentially this just adds a cohort enrolment plugin instance to the course
834      *
835      * @param int $cohortid
836      * @param int $roleid
837      * @return bool
838      */
839     public function enrol_cohort($cohortid, $roleid) {
840         global $CFG;
841         require_capability('moodle/course:enrolconfig', $this->get_context());
842         require_once($CFG->dirroot.'/enrol/cohort/locallib.php');
843         $roles = $this->get_assignable_roles();
844         $cohorts = $this->get_cohorts();
845         if (!array_key_exists($cohortid, $cohorts) || !array_key_exists($roleid, $roles)) {
846             return false;
847         }
848         $enrol = enrol_get_plugin('cohort');
849         $enrol->add_instance($this->course, array('customint1'=>$cohortid, 'roleid'=>$roleid));
850         enrol_cohort_sync($this->course->id);
851         return true;
852     }
854     /**
855      * Enrols all of the users in a cohort within this course.
856      *
857      * Note this is VERY different from creating an enrolment instance for a cohort.
858      *
859      * @global moodle_database $DB
860      * @param int $cohortid
861      * @param int $roleid
862      * @return bool
863      */
864     public function enrol_cohort_users($cohortid, $roleid) {
865         global $DB;
866         require_capability('moodle/course:enrolconfig', $this->get_context());
867         $instance = false;
868         $instances = $this->get_enrolment_instances();
869         foreach ($instances as $i) {
870             if ($i->enrol == 'manual') {
871                 $instance = $i;
872                 break;
873             }
874         }
875         $plugin = enrol_get_plugin('manual');
876         if (!$instance || !$plugin || !$plugin->allow_enrol($instance) || !has_capability('enrol/'.$plugin->get_name().':enrol', $this->get_context())) {
877             return false;
878         }
879         $sql = "SELECT com.userid
880                 FROM {cohort_members} com
881                 LEFT JOIN (
882                     SELECT *
883                     FROM {user_enrolments} ue
884                     WHERE ue.enrolid = :enrolid
885                 ) ue ON ue.userid=com.userid
886                 WHERE com.cohortid = :cohortid AND ue.id IS NULL";
887         $params = array('cohortid'=>$cohortid, 'enrolid'=>$instance->id);
888         $rs = $DB->get_recordset_sql($sql, $params);
889         $count = 0;
890         foreach ($rs as $user) {
891             $count++;
892             $plugin->enrol_user($instance, $user->userid, $roleid);
893         }
894         $rs->close();
895         return $count;
896     }
898     /**
899      * Gets an array of users for display, this includes minimal user information
900      * as well as minimal information on the users roles, groups, and enrolments.
901      *
902      * @param core_enrol_renderer $renderer
903      * @param moodle_url $pageurl
904      * @param int $sort
905      * @param string $direction ASC or DESC
906      * @param int $page
907      * @param int $perpage
908      * @return array
909      */
910     public function get_users_for_display(core_enrol_renderer $renderer, moodle_url $pageurl, $sort, $direction, $page, $perpage) {
911         $users = $this->get_users($sort, $direction, $page, $perpage);
913         $now = time();
914         $strnever = get_string('never');
915         $straddgroup = get_string('addgroup', 'group');
916         $strunenrol = get_string('unenrol', 'enrol');
917         $stredit = get_string('edit');
919         $iconedit        = $renderer->pix_url('t/edit');
920         $iconenroladd    = $renderer->pix_url('t/enroladd');
921         $iconenrolremove = $renderer->pix_url('t/delete');
923         $allroles   = $this->get_all_roles();
924         $assignable = $this->get_assignable_roles();
925         $allgroups  = $this->get_all_groups();
926         $courseid   = $this->get_course()->id;
927         $context    = $this->get_context();
928         $canmanagegroups = has_capability('moodle/course:managegroups', $context);
930         $url = new moodle_url($pageurl, $this->get_url_params());
932         $userdetails = array();
933         foreach ($users as $user) {
934             $details = array(
935                 'userid'     => $user->id,
936                 'courseid'   => $courseid,
937                 'picture'    => new user_picture($user),
938                 'firstname'  => fullname($user, true),
939                 'email'      => $user->email,
940                 'lastseen'   => $strnever,
941                 'roles'      => array(),
942                 'groups'     => array(),
943                 'enrolments' => array()
944             );
946             if ($user->lastaccess) {
947                 $details['lastseen'] = format_time($now - $user->lastaccess);
948             }
950             // Roles
951             foreach ($this->get_user_roles($user->id) as $rid=>$rassignable) {
952                 $details['roles'][$rid] = array('text'=>$allroles[$rid]->localname, 'unchangeable'=>(!$rassignable || !isset($assignable[$rid])));
953             }
955             // Users
956             $usergroups = $this->get_user_groups($user->id);
957             foreach($usergroups as $gid=>$unused) {
958                 $details['groups'][$gid] = $allgroups[$gid]->name;
959             }
961             // Enrolments
962             foreach ($this->get_user_enrolments($user->id) as $ue) {
963                 if ($ue->timestart and $ue->timeend) {
964                     $period = get_string('periodstartend', 'enrol', array('start'=>userdate($ue->timestart), 'end'=>userdate($ue->timeend)));
965                     $periodoutside = ($ue->timestart && $ue->timeend && $now < $ue->timestart && $now > $ue->timeend);
966                 } else if ($ue->timestart) {
967                     $period = get_string('periodstart', 'enrol', userdate($ue->timestart));
968                     $periodoutside = ($ue->timestart && $now < $ue->timestart);
969                 } else if ($ue->timeend) {
970                     $period = get_string('periodend', 'enrol', userdate($ue->timeend));
971                     $periodoutside = ($ue->timeend && $now > $ue->timeend);
972                 } else {
973                     $period = '';
974                     $periodoutside = false;
975                 }
976                 $details['enrolments'][$ue->id] = array(
977                     'text' => $ue->enrolmentinstancename,
978                     'period' => $period,
979                     'dimmed' =>  ($periodoutside || $ue->status != ENROL_USER_ACTIVE),
980                     'canunenrol' => ($ue->enrolmentplugin->allow_unenrol($ue->enrolmentinstance) && has_capability("enrol/".$ue->enrolmentinstance->enrol.":unenrol", $context)),
981                     'canmanage' => ($ue->enrolmentplugin->allow_manage($ue->enrolmentinstance) && has_capability("enrol/".$ue->enrolmentinstance->enrol.":manage", $context))
982                 );
983             }
984             $userdetails[$user->id] = $details;
985         }
986         return $userdetails;
987     }
990 class enrol_ajax_exception extends moodle_exception {
991     /**
992      * Constructor
993      * @param string $errorcode The name of the string from error.php to print
994      * @param string $module name of module
995      * @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.
996      * @param object $a Extra words and phrases that might be required in the error string
997      * @param string $debuginfo optional debugging information
998      */
999     public function __construct($errorcode, $link = '', $a = NULL, $debuginfo = null) {
1000         parent::__construct($errorcode, 'enrol', $link, $a, $debuginfo);
1001     }