MDL-23532 enrol - separated AJAX functions from enrol/ajax.php to their respective...
[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
a70eb30f
SH
792 /**
793 * Gets an array of users for display, this includes minimal user information
794 * as well as minimal information on the users roles, groups, and enrolments.
795 *
796 * @param core_enrol_renderer $renderer
797 * @param moodle_url $pageurl
798 * @param int $sort
799 * @param string $direction ASC or DESC
800 * @param int $page
801 * @param int $perpage
802 * @return array
803 */
804 public function get_users_for_display(core_enrol_renderer $renderer, moodle_url $pageurl, $sort, $direction, $page, $perpage) {
805 $users = $this->get_users($sort, $direction, $page, $perpage);
806
807 $now = time();
808 $strnever = get_string('never');
809 $straddgroup = get_string('addgroup', 'group');
810 $strunenrol = get_string('unenrol', 'enrol');
811 $stredit = get_string('edit');
812
813 $iconedit = $renderer->pix_url('t/edit');
814 $iconenroladd = $renderer->pix_url('t/enroladd');
815 $iconenrolremove = $renderer->pix_url('t/delete');
816
817 $allroles = $this->get_all_roles();
818 $assignable = $this->get_assignable_roles();
819 $allgroups = $this->get_all_groups();
820 $courseid = $this->get_course()->id;
821 $context = $this->get_context();
822 $canmanagegroups = has_capability('moodle/course:managegroups', $context);
823
824 $url = new moodle_url($pageurl, $this->get_url_params());
825
826 $userdetails = array();
827 foreach ($users as $user) {
828 $details = array(
829 'userid' => $user->id,
830 'courseid' => $courseid,
831 'picture' => new user_picture($user),
832 'firstname' => fullname($user, true),
833 'email' => $user->email,
834 'lastseen' => $strnever,
835 'roles' => array(),
836 'groups' => array(),
837 'enrolments' => array()
838 );
839
6db3eee0
SH
840 if ($user->lastaccess) {
841 $details['lastseen'] = format_time($now - $user->lastaccess);
a70eb30f
SH
842 }
843
844 // Roles
845 foreach ($this->get_user_roles($user->id) as $rid=>$rassignable) {
846 $details['roles'][$rid] = array('text'=>$allroles[$rid]->localname, 'unchangeable'=>(!$rassignable || !isset($assignable[$rid])));
847 }
848
849 // Users
850 $usergroups = $this->get_user_groups($user->id);
851 foreach($usergroups as $gid=>$unused) {
852 $details['groups'][$gid] = $allgroups[$gid]->name;
853 }
854
855 // Enrolments
856 foreach ($this->get_user_enrolments($user->id) as $ue) {
857 if ($ue->timestart and $ue->timeend) {
858 $period = get_string('periodstartend', 'enrol', array('start'=>userdate($ue->timestart), 'end'=>userdate($ue->timeend)));
859 $periodoutside = ($ue->timestart && $ue->timeend && $now < $ue->timestart && $now > $ue->timeend);
860 } else if ($ue->timestart) {
861 $period = get_string('periodstart', 'enrol', userdate($ue->timestart));
862 $periodoutside = ($ue->timestart && $now < $ue->timestart);
863 } else if ($ue->timeend) {
864 $period = get_string('periodend', 'enrol', userdate($ue->timeend));
865 $periodoutside = ($ue->timeend && $now > $ue->timeend);
866 } else {
867 $period = '';
868 $periodoutside = false;
869 }
870 $details['enrolments'][$ue->id] = array(
871 'text' => $ue->enrolmentinstancename,
872 'period' => $period,
873 'dimmed' => ($periodoutside || $ue->status != ENROL_USER_ACTIVE),
874 'canunenrol' => ($ue->enrolmentplugin->allow_unenrol($ue->enrolmentinstance) && has_capability("enrol/".$ue->enrolmentinstance->enrol.":unenrol", $context)),
875 'canmanage' => ($ue->enrolmentplugin->allow_manage($ue->enrolmentinstance) && has_capability("enrol/".$ue->enrolmentinstance->enrol.":manage", $context))
876 );
877 }
878 $userdetails[$user->id] = $details;
879 }
880 return $userdetails;
a70eb30f 881 }
b69ca6be
SH
882
883 public function get_manual_enrol_buttons() {
884 $plugins = $this->get_enrolment_plugins();
885 $buttons = array();
886 foreach ($plugins as $plugin) {
887 $newbutton = $plugin->get_manual_enrol_button($this);
888 if (is_array($newbutton)) {
889 $buttons += $newbutton;
890 } else if ($newbutton instanceof enrol_user_button) {
891 $buttons[] = $newbutton;
892 }
893 }
894 return $buttons;
895 }
896
897 public function has_instance($enrolpluginname) {
898 // Make sure manual enrolments instance exists
899 foreach ($this->get_enrolment_instances() as $instance) {
900 if ($instance->enrol == $enrolpluginname) {
901 return true;
902 }
903 }
904 return false;
905 }
906}
907
908/**
909 * A button that is used to enrol users in a course
910 *
911 * @copyright 2010 Sam Hemelryk
912 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
913 */
914class enrol_user_button extends single_button {
915
916 /**
917 * An array containing JS YUI modules required by this button
918 * @var array
919 */
920 protected $jsyuimodules = array();
921
922 /**
923 * An array containing JS initialisation calls required by this button
924 * @var array
925 */
926 protected $jsinitcalls = array();
927
928 /**
929 * An array strings required by JS for this button
930 * @var array
931 */
932 protected $jsstrings = array();
933
934 /**
935 * Initialises the new enrol_user_button
936 *
937 * @staticvar int $count The number of enrol user buttons already created
938 * @param moodle_url $url
939 * @param string $label The text to display in the button
940 * @param string $method Either post or get
941 */
942 public function __construct(moodle_url $url, $label, $method = 'post') {
943 static $count = 0;
944 $count ++;
945 parent::__construct($url, $label, $method);
946 $this->class = 'singlebutton enrolusersbutton';
947 $this->formid = 'enrolusersbutton-'.$count;
948 }
949
950 /**
951 * Adds a YUI module call that will be added to the page when the button is used.
952 *
953 * @param string|array $modules One or more modules to require
954 * @param string $function The JS function to call
955 * @param array $arguments An array of arguments to pass to the function
956 * @param string $galleryversion The YUI gallery version of any modules required
957 * @param bool $ondomready If true the call is postponed until the DOM is finished loading
958 */
959 public function require_yui_module($modules, $function, array $arguments = null, $galleryversion = '2010.04.08-12-35', $ondomready = false) {
960 $js = new stdClass;
961 $js->modules = (array)$modules;
962 $js->function = $function;
963 $js->arguments = $arguments;
964 $js->galleryversion = $galleryversion;
965 $js->ondomready = $ondomready;
966 $this->jsyuimodules[] = $js;
967 }
968
969 /**
970 * Adds a JS initialisation call to the page when the button is used.
971 *
972 * @param string $function The function to call
973 * @param array $extraarguments An array of arguments to pass to the function
974 * @param bool $ondomready If true the call is postponed until the DOM is finished loading
975 * @param array $module A module definition
976 */
977 public function require_js_init_call($function, array $extraarguments = null, $ondomready = false, array $module = null) {
978 $js = new stdClass;
979 $js->function = $function;
980 $js->extraarguments = $extraarguments;
981 $js->ondomready = $ondomready;
982 $js->module = $module;
983 $this->jsinitcalls[] = $js;
984 }
985
986 /**
987 * Requires strings for JS that will be loaded when the button is used.
988 *
989 * @param type $identifiers
990 * @param string $component
991 * @param mixed $a
992 */
993 public function strings_for_js($identifiers, $component = 'moodle', $a = null) {
994 $string = new stdClass;
995 $string->identifiers = (array)$identifiers;
996 $string->component = $component;
997 $string->a = $a;
998 $this->jsstrings[] = $string;
999 }
1000
1001 /**
1002 * Initialises the JS that is required by this button
1003 *
1004 * @param moodle_page $page
1005 */
1006 public function initialise_js(moodle_page $page) {
1007 foreach ($this->jsyuimodules as $js) {
1008 $page->requires->yui_module($js->modules, $js->function, $js->arguments, $js->galleryversion, $js->ondomready);
1009 }
1010 foreach ($this->jsinitcalls as $js) {
1011 $page->requires->js_init_call($js->function, $js->extraarguments, $js->ondomready, $js->module);
1012 }
1013 foreach ($this->jsstrings as $string) {
1014 $page->requires->strings_for_js($string->identifiers, $string->component, $string->a);
1015 }
1016 }
6db3eee0
SH
1017}
1018
1019class enrol_ajax_exception extends moodle_exception {
1020 /**
1021 * Constructor
1022 * @param string $errorcode The name of the string from error.php to print
1023 * @param string $module name of module
1024 * @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.
1025 * @param object $a Extra words and phrases that might be required in the error string
1026 * @param string $debuginfo optional debugging information
1027 */
1028 public function __construct($errorcode, $link = '', $a = NULL, $debuginfo = null) {
1029 parent::__construct($errorcode, 'enrol', $link, $a, $debuginfo);
1030 }
a70eb30f 1031}