enrol-users MDL-24618 Enrol users search now concats firstname and lastname as reques...
[moodle.git] / enrol / locallib.php
CommitLineData
a70eb30f
SH
1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * This 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 *
5379726a
PS
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
a70eb30f
SH
26 */
27
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 */
37class course_enrolment_manager {
38
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;
54
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();
67
6db3eee0
SH
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();
74
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;
81
a70eb30f
SH
82 /**#@+
83 * These variables are used to cache the information this class uses
df4a889e 84 * please never use these directly instead use their get_ counterparts.
a70eb30f
SH
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;
9f15347e 94 private $_assignablerolesothers = null;
a70eb30f
SH
95 private $_groups = null;
96 /**#@-*/
97
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 }
109
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 }
131
6db3eee0
SH
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 }
163
a70eb30f
SH
164 /**
165 * Gets all of the users enrolled in this course.
166 *
df4a889e 167 * If a filter was specified this will be the users who were enrolled
a70eb30f
SH
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();
df4a889e
PS
185 $ufields = user_picture::fields('u', array('lastaccess', 'email'));
186 $sql = "SELECT DISTINCT $ufields, ul.timeaccess AS lastseen
a70eb30f
SH
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 }
204
6db3eee0
SH
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 }
247
a70eb30f
SH
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) {
b3df1764 260 global $DB, $CFG;
a70eb30f
SH
261
262 // Add some additional sensible conditions
b3df1764
PS
263 $tests = array("id <> :guestid", 'u.deleted = 0', 'u.confirmed = 1');
264 $params = array('guestid' => $CFG->siteguest);
a70eb30f 265 if (!empty($search)) {
9fc9de91
SH
266 $conditions = array(
267 $DB->sql_concat('u.firstname', "' '", 'u.lastname'),
268 'u.email'
269 );
a70eb30f
SH
270 if ($searchanywhere) {
271 $searchparam = '%' . $search . '%';
272 } else {
273 $searchparam = $search . '%';
274 }
275 $i = 0;
f7614bb0
PS
276 foreach ($conditions as $key=>$condition) {
277 $conditions[$key] = $DB->sql_like($condition,":con{$i}00", false);
a70eb30f
SH
278 $params["con{$i}00"] = $searchparam;
279 $i++;
280 }
281 $tests[] = '(' . implode(' OR ', $conditions) . ')';
282 }
283 $wherecondition = implode(' AND ', $tests);
284
285 $ufields = user_picture::fields('u');
286
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 }
300
6db3eee0
SH
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) {
b3df1764 312 global $DB, $CFG;
6db3eee0
SH
313
314 // Add some additional sensible conditions
b3df1764
PS
315 $tests = array("u.id <> :guestid", 'u.deleted = 0', 'u.confirmed = 1');
316 $params = array('guestid'=>$CFG->siteguest);
6db3eee0
SH
317 if (!empty($search)) {
318 $conditions = array('u.firstname','u.lastname');
6db3eee0
SH
319 if ($searchanywhere) {
320 $searchparam = '%' . $search . '%';
321 } else {
322 $searchparam = $search . '%';
323 }
324 $i = 0;
f7614bb0
PS
325 foreach ($conditions as $key=>$condition) {
326 $conditions[$key] = $DB->sql_like($condition, ":con{$i}00", false);
6db3eee0
SH
327 $params["con{$i}00"] = $searchparam;
328 $i++;
329 }
330 $tests[] = '(' . implode(' OR ', $conditions) . ')';
331 }
332 $wherecondition = implode(' AND ', $tests);
5379726a 333
6db3eee0
SH
334
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';
345
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 }
351
a70eb30f
SH
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 }
382
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 }
394
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 }
415
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 }
427
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 }
439
440 /**
441 * Gets all of the assignable roles for this course.
442 *
443 * @return array
444 */
9f15347e 445 public function get_assignable_roles($otherusers = false) {
a70eb30f
SH
446 if ($this->_assignableroles === null) {
447 $this->_assignableroles = get_assignable_roles($this->context, ROLENAME_ALIAS, false); // verifies unassign access control too
448 }
9f15347e
SH
449
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 }
a70eb30f
SH
464 }
465
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 }
480
481 /**
df4a889e 482 * Unenrols a user from the course given the users ue entry
a70eb30f
SH
483 *
484 * @global moodle_database $DB
485 * @param stdClass $ue
486 * @return bool
487 */
488 public function unenrol_user($ue) {
a942f757 489 global $DB;
a3c71984
SH
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 }
a70eb30f 497
a3c71984
SH
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;
a942f757 507 if (is_numeric($userenrolment)) {
a3c71984
SH
508 $userenrolment = $DB->get_record('user_enrolments', array('id'=>(int)$userenrolment));
509 }
a70eb30f
SH
510 $instances = $this->get_enrolment_instances();
511 $plugins = $this->get_enrolment_plugins();
a3c71984
SH
512 if (!$userenrolment || !isset($instances[$userenrolment->enrolid])) {
513 return array(false, false);
a70eb30f 514 }
a3c71984 515 $instance = $instances[$userenrolment->enrolid];
a70eb30f 516 $plugin = $plugins[$instance->enrol];
a3c71984 517 return array($instance, $plugin);
a70eb30f
SH
518 }
519
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;
a3c71984 530 require_capability('moodle/role:assign', $this->context);
a70eb30f
SH
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) {
894843b4 535 if (defined('AJAX_SCRIPT')) {
6db3eee0
SH
536 throw $e;
537 }
a70eb30f
SH
538 return false;
539 }
540 return true;
541 }
542
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);
823a807e 552 if (!array_key_exists($roleid, $this->get_assignable_roles())) {
894843b4 553 if (defined('AJAX_SCRIPT')) {
c05260de 554 throw new moodle_exception('invalidrole');
6db3eee0 555 }
823a807e
SH
556 return false;
557 }
a70eb30f
SH
558 return role_assign($roleid, $userid, $this->context->id, '', NULL);
559 }
560
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 }
576
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 }
594
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 }
608
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) {
621ee955 617 list($instance, $plugin) = $this->get_user_enrolment_components($userenrolment);
a3c71984
SH
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;
a70eb30f 624 }
a3c71984 625 return false;
a70eb30f
SH
626 }
627
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 }
635
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 }
660
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 }
683
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 }
693
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 }
709
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 }
718
719 /**
720 * Returns the course context
721 *
722 * @return stdClass
723 */
724 public function get_context() {
725 return $this->context;
726 }
727
6db3eee0
SH
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) {
5379726a 743
6db3eee0
SH
744 $userroles = $this->get_other_users($sort, $direction, $page, $perpage);
745 $roles = $this->get_all_roles();
746
747 $courseid = $this->get_course()->id;
748 $context = $this->get_context();
749
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 }
790
2ec702c9
SH
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 }
829
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 }
853
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());
2ec702c9 867 $instance = false;
a3c71984 868 $instances = $this->get_enrolment_instances();
2ec702c9
SH
869 foreach ($instances as $i) {
870 if ($i->enrol == 'manual') {
871 $instance = $i;
872 break;
873 }
874 }
a3c71984
SH
875 $plugin = enrol_get_plugin('manual');
876 if (!$instance || !$plugin || !$plugin->allow_enrol($instance) || !has_capability('enrol/'.$plugin->get_name().':enrol', $this->get_context())) {
2ec702c9
SH
877 return false;
878 }
91b99e80 879 $sql = "SELECT com.userid
2ec702c9
SH
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 }
897
a70eb30f
SH
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);
912
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');
918
919 $iconedit = $renderer->pix_url('t/edit');
920 $iconenroladd = $renderer->pix_url('t/enroladd');
921 $iconenrolremove = $renderer->pix_url('t/delete');
922
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);
929
930 $url = new moodle_url($pageurl, $this->get_url_params());
931
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 );
945
6db3eee0
SH
946 if ($user->lastaccess) {
947 $details['lastseen'] = format_time($now - $user->lastaccess);
a70eb30f
SH
948 }
949
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 }
954
955 // Users
956 $usergroups = $this->get_user_groups($user->id);
957 foreach($usergroups as $gid=>$unused) {
958 $details['groups'][$gid] = $allgroups[$gid]->name;
959 }
960
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;
a70eb30f 987 }
6db3eee0
SH
988}
989
990class 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 }
a70eb30f 1002}