weekly release 2.1dev
[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) {
cf717dc2 144 list($ctxcondition, $params) = $DB->get_in_or_equal(get_parent_contexts($this->context, true), SQL_PARAMS_NAMED, 'ctx');
6db3eee0
SH
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)) {
cf717dc2 225 list($ctxcondition, $params) = $DB->get_in_or_equal(get_parent_contexts($this->context, true), SQL_PARAMS_NAMED, 'ctx');
6db3eee0
SH
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
93b4ecb2 285 $ufields = user_picture::fields('u', array('username', 'lastaccess'));
a70eb30f 286
93b4ecb2 287 $fields = 'SELECT '.$ufields;
a70eb30f
SH
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
603087b8 334 $fields = 'SELECT '.user_picture::fields('u', array('username','lastaccess'));
6db3eee0
SH
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';
344
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 }
350
a70eb30f
SH
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 }
381
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 }
393
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 }
414
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 }
426
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 }
438
439 /**
440 * Gets all of the assignable roles for this course.
441 *
442 * @return array
443 */
9f15347e 444 public function get_assignable_roles($otherusers = false) {
a70eb30f
SH
445 if ($this->_assignableroles === null) {
446 $this->_assignableroles = get_assignable_roles($this->context, ROLENAME_ALIAS, false); // verifies unassign access control too
447 }
9f15347e
SH
448
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 }
a70eb30f
SH
463 }
464
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 }
479
480 /**
df4a889e 481 * Unenrols a user from the course given the users ue entry
a70eb30f
SH
482 *
483 * @global moodle_database $DB
484 * @param stdClass $ue
485 * @return bool
486 */
487 public function unenrol_user($ue) {
a942f757 488 global $DB;
a3c71984
SH
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 }
a70eb30f 496
a3c71984
SH
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;
a942f757 506 if (is_numeric($userenrolment)) {
a3c71984
SH
507 $userenrolment = $DB->get_record('user_enrolments', array('id'=>(int)$userenrolment));
508 }
a70eb30f
SH
509 $instances = $this->get_enrolment_instances();
510 $plugins = $this->get_enrolment_plugins();
a3c71984
SH
511 if (!$userenrolment || !isset($instances[$userenrolment->enrolid])) {
512 return array(false, false);
a70eb30f 513 }
a3c71984 514 $instance = $instances[$userenrolment->enrolid];
a70eb30f 515 $plugin = $plugins[$instance->enrol];
a3c71984 516 return array($instance, $plugin);
a70eb30f
SH
517 }
518
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;
a3c71984 529 require_capability('moodle/role:assign', $this->context);
a70eb30f
SH
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) {
894843b4 534 if (defined('AJAX_SCRIPT')) {
6db3eee0
SH
535 throw $e;
536 }
a70eb30f
SH
537 return false;
538 }
539 return true;
540 }
541
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);
823a807e 551 if (!array_key_exists($roleid, $this->get_assignable_roles())) {
894843b4 552 if (defined('AJAX_SCRIPT')) {
c05260de 553 throw new moodle_exception('invalidrole');
6db3eee0 554 }
823a807e
SH
555 return false;
556 }
a70eb30f
SH
557 return role_assign($roleid, $userid, $this->context->id, '', NULL);
558 }
559
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 }
575
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 }
593
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 }
607
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) {
13ba9036
AD
616 //Only allow editing if the user has the appropriate capability
617 //Already checked in /enrol/users.php but checking again in case this function is called from elsewhere
621ee955 618 list($instance, $plugin) = $this->get_user_enrolment_components($userenrolment);
a3c71984
SH
619 if ($instance && $plugin && $plugin->allow_manage($instance) && has_capability("enrol/$instance->enrol:manage", $this->context)) {
620 if (!isset($data->status)) {
621 $data->status = $userenrolment->status;
622 }
623 $plugin->update_user_enrol($instance, $userenrolment->userid, $data->status, $data->timestart, $data->timeend);
624 return true;
a70eb30f 625 }
a3c71984 626 return false;
a70eb30f
SH
627 }
628
629 /**
630 * Returns the current enrolment filter that is being applied by this class
631 * @return string
632 */
633 public function get_enrolment_filter() {
634 return $this->instancefilter;
635 }
636
637 /**
638 * Gets the roles assigned to this user that are applicable for this course.
639 *
640 * @param int $userid
641 * @return array
642 */
643 public function get_user_roles($userid) {
644 $roles = array();
645 $ras = get_user_roles($this->context, $userid, true, 'c.contextlevel DESC, r.sortorder ASC');
646 foreach ($ras as $ra) {
647 if ($ra->contextid != $this->context->id) {
648 if (!array_key_exists($ra->roleid, $roles)) {
649 $roles[$ra->roleid] = null;
650 }
651 // higher ras, course always takes precedence
652 continue;
653 }
654 if (array_key_exists($ra->roleid, $roles) && $roles[$ra->roleid] === false) {
655 continue;
656 }
657 $roles[$ra->roleid] = ($ra->itemid == 0 and $ra->component === '');
658 }
659 return $roles;
660 }
661
662 /**
663 * Gets the enrolments this user has in the course
664 *
665 * @global moodle_database $DB
666 * @param int $userid
667 * @return array
668 */
669 public function get_user_enrolments($userid) {
670 global $DB;
671 list($instancessql, $params, $filter) = $this->get_instance_sql();
672 $params['userid'] = $userid;
673 $userenrolments = $DB->get_records_select('user_enrolments', "enrolid $instancessql AND userid = :userid", $params);
674 $instances = $this->get_enrolment_instances();
675 $plugins = $this->get_enrolment_plugins();
676 $inames = $this->get_enrolment_instance_names();
677 foreach ($userenrolments as &$ue) {
678 $ue->enrolmentinstance = $instances[$ue->enrolid];
679 $ue->enrolmentplugin = $plugins[$ue->enrolmentinstance->enrol];
680 $ue->enrolmentinstancename = $inames[$ue->enrolmentinstance->id];
681 }
682 return $userenrolments;
683 }
684
685 /**
686 * Gets the groups this user belongs to
687 *
688 * @param int $userid
689 * @return array
690 */
691 public function get_user_groups($userid) {
692 return groups_get_all_groups($this->course->id, $userid, 0, 'g.id');
693 }
694
695 /**
696 * Retursn an array of params that would go into the URL to return to this
697 * exact page.
698 *
699 * @return array
700 */
701 public function get_url_params() {
702 $args = array(
703 'id' => $this->course->id
704 );
705 if (!empty($this->instancefilter)) {
706 $args['ifilter'] = $this->instancefilter;
707 }
708 return $args;
709 }
710
711 /**
712 * Returns the course this object is managing enrolments for
713 *
714 * @return stdClass
715 */
716 public function get_course() {
717 return $this->course;
718 }
719
720 /**
721 * Returns the course context
722 *
723 * @return stdClass
724 */
725 public function get_context() {
726 return $this->context;
727 }
728
6db3eee0
SH
729 /**
730 * Gets an array of other users in this course ready for display.
731 *
732 * Other users are users who have been assigned or inherited roles within this
733 * course but have not been enrolled.
734 *
735 * @param core_enrol_renderer $renderer
736 * @param moodle_url $pageurl
737 * @param string $sort
738 * @param string $direction ASC | DESC
739 * @param int $page Starting from 0
740 * @param int $perpage
741 * @return array
742 */
743 public function get_other_users_for_display(core_enrol_renderer $renderer, moodle_url $pageurl, $sort, $direction, $page, $perpage) {
5379726a 744
6db3eee0
SH
745 $userroles = $this->get_other_users($sort, $direction, $page, $perpage);
746 $roles = $this->get_all_roles();
747
748 $courseid = $this->get_course()->id;
749 $context = $this->get_context();
750
751 $users = array();
752 foreach ($userroles as $userrole) {
753 if (!array_key_exists($userrole->id, $users)) {
754 $users[$userrole->id] = array(
755 'userid' => $userrole->id,
756 'courseid' => $courseid,
757 'picture' => new user_picture($userrole),
758 'firstname' => fullname($userrole, true),
759 'email' => $userrole->email,
760 'roles' => array()
761 );
762 }
763 $a = new stdClass;
764 $a->role = $roles[$userrole->roleid]->localname;
765 $changeable = ($userrole->component == '');
766 if ($userrole->contextid == $this->context->id) {
767 $roletext = get_string('rolefromthiscourse', 'enrol', $a);
768 } else {
769 $changeable = false;
770 switch ($userrole->contextlevel) {
771 case CONTEXT_COURSE :
772 // Meta course
773 $roletext = get_string('rolefrommetacourse', 'enrol', $a);
774 break;
775 case CONTEXT_COURSECAT :
776 $roletext = get_string('rolefromcategory', 'enrol', $a);
777 break;
778 case CONTEXT_SYSTEM:
779 default:
780 $roletext = get_string('rolefromsystem', 'enrol', $a);
781 break;
782 }
783 }
784 $users[$userrole->id]['roles'][$userrole->roleid] = array(
785 'text' => $roletext,
786 'unchangeable' => !$changeable
787 );
788 }
789 return $users;
790 }
791
2ec702c9
SH
792 /**
793 * Gets all the cohorts the user is able to view.
794 *
795 * @global moodle_database $DB
796 * @return array
797 */
798 public function get_cohorts() {
799 global $DB;
800 $context = $this->get_context();
801 $cohorts = array();
802 $instances = $this->get_enrolment_instances();
803 $enrolled = array();
804 foreach ($instances as $instance) {
805 if ($instance->enrol == 'cohort') {
806 $enrolled[] = $instance->customint1;
807 }
808 }
809 list($sqlparents, $params) = $DB->get_in_or_equal(get_parent_contexts($context));
810 $sql = "SELECT id, name, contextid
811 FROM {cohort}
812 WHERE contextid $sqlparents
813 ORDER BY name ASC";
814 $rs = $DB->get_recordset_sql($sql, $params);
815 foreach ($rs as $c) {
816 $context = get_context_instance_by_id($c->contextid);
817 if (!has_capability('moodle/cohort:view', $context)) {
818 continue;
819 }
820 $cohorts[$c->id] = array(
821 'cohortid'=>$c->id,
822 'name'=>format_string($c->name),
823 'users'=>$DB->count_records('cohort_members', array('cohortid'=>$c->id)),
824 'enrolled'=>in_array($c->id, $enrolled)
825 );
826 }
827 $rs->close();
828 return $cohorts;
829 }
830
831 /**
832 * Enrols a cohort in a course.
833 *
834 * Essentially this just adds a cohort enrolment plugin instance to the course
835 *
836 * @param int $cohortid
837 * @param int $roleid
838 * @return bool
839 */
840 public function enrol_cohort($cohortid, $roleid) {
841 global $CFG;
842 require_capability('moodle/course:enrolconfig', $this->get_context());
843 require_once($CFG->dirroot.'/enrol/cohort/locallib.php');
844 $roles = $this->get_assignable_roles();
845 $cohorts = $this->get_cohorts();
846 if (!array_key_exists($cohortid, $cohorts) || !array_key_exists($roleid, $roles)) {
847 return false;
848 }
849 $enrol = enrol_get_plugin('cohort');
850 $enrol->add_instance($this->course, array('customint1'=>$cohortid, 'roleid'=>$roleid));
851 enrol_cohort_sync($this->course->id);
852 return true;
853 }
854
855 /**
856 * Enrols all of the users in a cohort within this course.
857 *
858 * Note this is VERY different from creating an enrolment instance for a cohort.
859 *
860 * @global moodle_database $DB
861 * @param int $cohortid
862 * @param int $roleid
863 * @return bool
864 */
865 public function enrol_cohort_users($cohortid, $roleid) {
866 global $DB;
867 require_capability('moodle/course:enrolconfig', $this->get_context());
2ec702c9 868 $instance = false;
a3c71984 869 $instances = $this->get_enrolment_instances();
2ec702c9
SH
870 foreach ($instances as $i) {
871 if ($i->enrol == 'manual') {
872 $instance = $i;
873 break;
874 }
875 }
a3c71984
SH
876 $plugin = enrol_get_plugin('manual');
877 if (!$instance || !$plugin || !$plugin->allow_enrol($instance) || !has_capability('enrol/'.$plugin->get_name().':enrol', $this->get_context())) {
2ec702c9
SH
878 return false;
879 }
91b99e80 880 $sql = "SELECT com.userid
2ec702c9
SH
881 FROM {cohort_members} com
882 LEFT JOIN (
883 SELECT *
884 FROM {user_enrolments} ue
885 WHERE ue.enrolid = :enrolid
886 ) ue ON ue.userid=com.userid
887 WHERE com.cohortid = :cohortid AND ue.id IS NULL";
888 $params = array('cohortid'=>$cohortid, 'enrolid'=>$instance->id);
889 $rs = $DB->get_recordset_sql($sql, $params);
890 $count = 0;
891 foreach ($rs as $user) {
892 $count++;
893 $plugin->enrol_user($instance, $user->userid, $roleid);
894 }
895 $rs->close();
896 return $count;
897 }
898
a70eb30f
SH
899 /**
900 * Gets an array of users for display, this includes minimal user information
901 * as well as minimal information on the users roles, groups, and enrolments.
902 *
903 * @param core_enrol_renderer $renderer
904 * @param moodle_url $pageurl
905 * @param int $sort
906 * @param string $direction ASC or DESC
907 * @param int $page
908 * @param int $perpage
909 * @return array
910 */
911 public function get_users_for_display(core_enrol_renderer $renderer, moodle_url $pageurl, $sort, $direction, $page, $perpage) {
912 $users = $this->get_users($sort, $direction, $page, $perpage);
913
914 $now = time();
915 $strnever = get_string('never');
916 $straddgroup = get_string('addgroup', 'group');
917 $strunenrol = get_string('unenrol', 'enrol');
918 $stredit = get_string('edit');
919
920 $iconedit = $renderer->pix_url('t/edit');
921 $iconenroladd = $renderer->pix_url('t/enroladd');
922 $iconenrolremove = $renderer->pix_url('t/delete');
923
924 $allroles = $this->get_all_roles();
925 $assignable = $this->get_assignable_roles();
926 $allgroups = $this->get_all_groups();
927 $courseid = $this->get_course()->id;
928 $context = $this->get_context();
929 $canmanagegroups = has_capability('moodle/course:managegroups', $context);
930
931 $url = new moodle_url($pageurl, $this->get_url_params());
932
933 $userdetails = array();
934 foreach ($users as $user) {
935 $details = array(
936 'userid' => $user->id,
937 'courseid' => $courseid,
938 'picture' => new user_picture($user),
939 'firstname' => fullname($user, true),
940 'email' => $user->email,
941 'lastseen' => $strnever,
942 'roles' => array(),
943 'groups' => array(),
944 'enrolments' => array()
945 );
946
6db3eee0
SH
947 if ($user->lastaccess) {
948 $details['lastseen'] = format_time($now - $user->lastaccess);
a70eb30f
SH
949 }
950
951 // Roles
952 foreach ($this->get_user_roles($user->id) as $rid=>$rassignable) {
953 $details['roles'][$rid] = array('text'=>$allroles[$rid]->localname, 'unchangeable'=>(!$rassignable || !isset($assignable[$rid])));
954 }
955
956 // Users
957 $usergroups = $this->get_user_groups($user->id);
958 foreach($usergroups as $gid=>$unused) {
959 $details['groups'][$gid] = $allgroups[$gid]->name;
960 }
961
962 // Enrolments
963 foreach ($this->get_user_enrolments($user->id) as $ue) {
964 if ($ue->timestart and $ue->timeend) {
965 $period = get_string('periodstartend', 'enrol', array('start'=>userdate($ue->timestart), 'end'=>userdate($ue->timeend)));
966 $periodoutside = ($ue->timestart && $ue->timeend && $now < $ue->timestart && $now > $ue->timeend);
967 } else if ($ue->timestart) {
968 $period = get_string('periodstart', 'enrol', userdate($ue->timestart));
969 $periodoutside = ($ue->timestart && $now < $ue->timestart);
970 } else if ($ue->timeend) {
971 $period = get_string('periodend', 'enrol', userdate($ue->timeend));
972 $periodoutside = ($ue->timeend && $now > $ue->timeend);
973 } else {
974 $period = '';
975 $periodoutside = false;
976 }
977 $details['enrolments'][$ue->id] = array(
978 'text' => $ue->enrolmentinstancename,
979 'period' => $period,
980 'dimmed' => ($periodoutside || $ue->status != ENROL_USER_ACTIVE),
981 'canunenrol' => ($ue->enrolmentplugin->allow_unenrol($ue->enrolmentinstance) && has_capability("enrol/".$ue->enrolmentinstance->enrol.":unenrol", $context)),
982 'canmanage' => ($ue->enrolmentplugin->allow_manage($ue->enrolmentinstance) && has_capability("enrol/".$ue->enrolmentinstance->enrol.":manage", $context))
983 );
984 }
985 $userdetails[$user->id] = $details;
986 }
987 return $userdetails;
a70eb30f 988 }
6db3eee0
SH
989}
990
991class enrol_ajax_exception extends moodle_exception {
992 /**
993 * Constructor
994 * @param string $errorcode The name of the string from error.php to print
995 * @param string $module name of module
996 * @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.
997 * @param object $a Extra words and phrases that might be required in the error string
998 * @param string $debuginfo optional debugging information
999 */
1000 public function __construct($errorcode, $link = '', $a = NULL, $debuginfo = null) {
1001 parent::__construct($errorcode, 'enrol', $link, $a, $debuginfo);
1002 }
a70eb30f 1003}