NOMDL edit icon at the course participants page now links to the enrolments page...
[moodle.git] / user / index.php
CommitLineData
aa6c1ced 1<?php
f9903ed0 2
3// Lists all the users within a given course
4
cc038b47 5 require_once('../config.php');
68b38e8d 6 require_once($CFG->libdir.'/tablelib.php');
951b22a8 7
8 define('USER_SMALL_CLASS', 20); // Below this is considered small
9 define('USER_LARGE_CLASS', 200); // Above this is considered large
cc038b47 10 define('DEFAULT_PAGE_SIZE', 20);
36075e09 11 define('SHOW_ALL_PAGE_SIZE', 5000);
073af1a6 12 define('MODE_BRIEF', 0);
13 define('MODE_USERDETAILS', 1);
f9903ed0 14
cc038b47 15 $page = optional_param('page', 0, PARAM_INT); // which page to show
16 $perpage = optional_param('perpage', DEFAULT_PAGE_SIZE, PARAM_INT); // how many per page
0f21a964 17 $mode = optional_param('mode', NULL, PARAM_INT); // use the MODE_ constants
5f9e296a 18 $accesssince = optional_param('accesssince',0,PARAM_INT); // filter by last access. -1 = never
93de0ac2
PS
19 $search = optional_param('search','',PARAM_RAW); // make sure it is processed with p() or s() when sending to output!
20 $roleid = optional_param('roleid', 0, PARAM_INT); // optional roleid, 0 means all enrolled users (or all on the frontpage)
e957cc26 21
5f9e296a 22 $contextid = optional_param('contextid', 0, PARAM_INT); // one of this or
23 $courseid = optional_param('id', 0, PARAM_INT); // this are required
3aac07d8 24
a6855934 25 $PAGE->set_url('/user/index.php', array(
aa6c1ced
PS
26 'page' => $page,
27 'perpage' => $perpage,
28 'mode' => $mode,
29 'accesssince' => $accesssince,
30 'search' => $search,
31 'roleid' => $roleid,
32 'contextid' => $contextid,
4e487ce2 33 'courseid' => $courseid));
f1e24e7a 34
e957cc26 35 if ($contextid) {
4f0c2d00
PS
36 $context = get_context_instance_by_id($contextid, MUST_EXIST);
37 if ($context->contextlevel != CONTEXT_COURSE) {
06e84d52 38 print_error('invalidcontext');
e957cc26 39 }
4f0c2d00 40 $course = $DB->get_record('course', array('id'=>$context->instanceid), '*', MUST_EXIST);
e957cc26 41 } else {
4f0c2d00
PS
42 $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
43 $context = get_context_instance(CONTEXT_COURSE, $course->id, MUST_EXIST);
f9903ed0 44 }
87a13824 45 // not needed anymore
46 unset($contextid);
47 unset($courseid);
f9903ed0 48
224aa44a 49 require_login($course);
f9903ed0 50
1118434a 51 $systemcontext = get_context_instance(CONTEXT_SYSTEM);
4f0c2d00
PS
52 $isfrontpage = ($course->id == SITEID);
53
165088f6 54 $frontpagectx = get_context_instance(CONTEXT_COURSE, SITEID);
224aa44a 55
4f0c2d00 56 if ($isfrontpage) {
c07dfe70 57 $PAGE->set_pagelayout('admin');
1118434a 58 require_capability('moodle/site:viewparticipants', $systemcontext);
4f0c2d00 59 } else {
c07dfe70 60 $PAGE->set_pagelayout('incourse');
4f0c2d00 61 require_capability('moodle/course:viewparticipants', $context);
6d3c57f4 62 }
63
d7270311 64 $rolenamesurl = new moodle_url("$CFG->wwwroot/user/index.php?contextid=$context->id&sifirst=&silast=");
65
4f0c2d00
PS
66 $allroles = get_all_roles();
67 $roles = get_profile_roles($context);
68 $allrolenames = array();
69 if ($isfrontpage) {
70 $rolenames = array(0=>get_string('allsiteusers', 'role'));
71 } else {
72 $rolenames = array(0=>get_string('allparticipants'));
73 }
5f9e296a 74
4f0c2d00
PS
75 foreach ($allroles as $role) {
76 $allrolenames[$role->id] = strip_tags(role_get_name($role, $context)); // Used in menus etc later on
77 if (isset($roles[$role->id])) {
78 $rolenames[$role->id] = $allrolenames[$role->id];
41d7209c 79 }
6d3c57f4 80 }
81
4f0c2d00
PS
82 // make sure other roles may not be selected by any means
83 if (empty($rolenames[$roleid])) {
84 print_error('noparticipants');
5f9e296a 85 }
86
87 // no roles to display yet?
165088f6 88 // frontpage course is an exception, on the front page course we should display all users
4f0c2d00 89 if (empty($rolenames) && !$isfrontpage) {
294a176f 90 if (has_capability('moodle/role:assign', $context)) {
87a13824 91 redirect($CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.$context->id);
41d7209c 92 } else {
06e84d52 93 print_error('noparticipants');
41d7209c 94 }
95 }
96
cc038b47 97 add_to_log($course->id, 'user', 'view all', 'index.php?id='.$course->id, '');
f9903ed0 98
77c645df 99 $bulkoperations = has_capability('moodle/course:bulkmessaging', $context);
f1e24e7a 100
0aa759b0 101 $countries = get_string_manager()->get_list_of_countries();
68b38e8d 102
cc038b47 103 $strnever = get_string('never');
68b38e8d 104
a59e5a1c 105 $datestring->year = get_string('year');
106 $datestring->years = get_string('years');
cc038b47 107 $datestring->day = get_string('day');
108 $datestring->days = get_string('days');
109 $datestring->hour = get_string('hour');
110 $datestring->hours = get_string('hours');
111 $datestring->min = get_string('min');
112 $datestring->mins = get_string('mins');
113 $datestring->sec = get_string('sec');
114 $datestring->secs = get_string('secs');
d578afc8 115
ff3caf30 116 if ($mode !== NULL) {
073af1a6 117 $mode = (int)$mode;
118 $SESSION->userindexmode = $mode;
ff3caf30 119 } else if (isset($SESSION->userindexmode)) {
073af1a6 120 $mode = (int)$SESSION->userindexmode;
ff3caf30 121 } else {
073af1a6 122 $mode = MODE_BRIEF;
ff3caf30 123 }
124
4cd0d3a0 125/// Check to see if groups are being used in this course
ff3caf30 126/// and if so, set $currentgroup to reflect the current group
127
ffc536af 128 $groupmode = groups_get_course_groupmode($course); // Groups are being used
129 $currentgroup = groups_get_course_group($course, true);
ff3caf30 130
cc038b47 131 if (!$currentgroup) { // To make some other functions work better later
132 $currentgroup = NULL;
133 }
ff3caf30 134
728a4ebe 135 $isseparategroups = ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context));
2cb2ce61 136
ee8aca27 137 if ($course->id===SITEID) {
138 $PAGE->navbar->ignore_active();
139 }
140
caa8363f 141 $PAGE->navbar->add(get_string('participants'));
142 $PAGE->set_title("$course->shortname: ".get_string('participants'));
143 $PAGE->set_heading($course->fullname);
03d9401e 144 $PAGE->set_pagetype('course-view-' . $course->format);
99cca847 145 $PAGE->add_body_class('path-user'); // So we can style it independently
03d9401e 146 $PAGE->set_other_editing_capability('moodle/course:manageactivities');
caa8363f 147
148 echo $OUTPUT->header();
0be6f678 149
99cca847
MD
150 echo '<div class="userlist">';
151
caa8363f 152 if ($isseparategroups and (!$currentgroup) ) {
153 // The user is not in the group so show message and exit
8fa89bfd 154 echo $OUTPUT->heading(get_string("notingroup"));
0ab75c34 155 echo $OUTPUT->footer();
ff3caf30 156 exit;
157 }
158
03d9401e 159
cc038b47 160 // Should use this variable so that we don't break stuff every time a variable is added or changed.
a6855934 161 $baseurl = new moodle_url('/user/index.php', array(
d7270311 162 'contextid' => $context->id,
163 'roleid' => $roleid,
164 'id' => $course->id,
165 'perpage' => $perpage,
166 'accesssince' => $accesssince,
167 'search' => s($search)));
ff3caf30 168
224aa44a 169/// setting up tags
e957cc26 170 if ($course->id == SITEID) {
1242eb8f 171 $filtertype = 'site';
e957cc26 172 } else if ($course->id && !$currentgroup) {
1242eb8f 173 $filtertype = 'course';
e957cc26 174 $filterselect = $course->id;
1242eb8f 175 } else {
176 $filtertype = 'group';
177 $filterselect = $currentgroup;
178 }
1242eb8f 179
03d9401e 180
1242eb8f 181
3468d58a 182/// Get the hidden field list
224aa44a 183 if (has_capability('moodle/course:viewhiddenuserfields', $context)) {
3468d58a 184 $hiddenfields = array(); // teachers and admins are allowed to see everything
185 } else {
186 $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
187 }
188
5ff311f0 189 if (isset($hiddenfields['lastaccess'])) {
190 // do not allow access since filtering
191 $accesssince = 0;
192 }
bbbf2d40 193
ff3caf30 194/// Print settings and things in a table across the top
4e487ce2 195 $controlstable = new html_table();
16be8974 196 $controlstable->attributes['class'] = 'controls';
4e487ce2 197 $controlstable->cellspacing = 0;
198 $controlstable->data[] = new html_table_row();
ff3caf30 199
a72784d3 200/// Print my course menus
df997f84 201 if ($mycourses = enrol_get_my_courses()) {
7da0af9f 202 $courselist = array();
a6855934 203 $popupurl = new moodle_url('/user/index.php?roleid='.$roleid.'&sifirst=&silast=');
7da0af9f 204 foreach ($mycourses as $mycourse) {
364eef74 205 $courselist[$mycourse->id] = format_string($mycourse->shortname);
7da0af9f 206 }
1118434a 207 if (has_capability('moodle/site:viewparticipants', $systemcontext)) {
5f9e296a 208 unset($courselist[SITEID]);
209 $courselist = array(SITEID => format_string($SITE->shortname)) + $courselist;
210 }
f8dab966 211 $select = new single_select($popupurl, 'id', $courselist, $course->id, array(''=>'choosedots'), 'courseform');
d7270311 212 $select->set_label(get_string('mycourses'));
f8dab966 213 $controlstable->data[0]->cells[] = $OUTPUT->render($select);
7da0af9f 214 }
87a13824 215
b60cae86 216 $controlstable->data[0]->cells[] = groups_print_course_menu($course, $baseurl->out(), true);
ff3caf30 217
5ff311f0 218 if (!isset($hiddenfields['lastaccess'])) {
219 // get minimum lastaccess for this course and display a dropbox to filter by lastaccess going back this far.
220 // we need to make it diferently for normal courses and site course
4f0c2d00 221 if (!$isfrontpage) {
5ff311f0 222 $minlastaccess = $DB->get_field_sql('SELECT min(timeaccess)
223 FROM {user_lastaccess}
224 WHERE courseid = ?
225 AND timeaccess != 0', array($course->id));
226 $lastaccess0exists = $DB->record_exists('user_lastaccess', array('courseid'=>$course->id, 'timeaccess'=>0));
227 } else {
228 $minlastaccess = $DB->get_field_sql('SELECT min(lastaccess)
229 FROM {user}
230 WHERE lastaccess != 0');
231 $lastaccess0exists = $DB->record_exists('user', array('lastaccess'=>0));
232 }
0749caef 233
5ff311f0 234 $now = usergetmidnight(time());
235 $timeaccess = array();
d7270311 236 $baseurl->remove_params('accesssince');
87a13824 237
5ff311f0 238 // makes sense for this to go first.
239 $timeoptions[0] = get_string('selectperiod');
87a13824 240
5ff311f0 241 // days
242 for ($i = 1; $i < 7; $i++) {
243 if (strtotime('-'.$i.' days',$now) >= $minlastaccess) {
244 $timeoptions[strtotime('-'.$i.' days',$now)] = get_string('numdays','moodle',$i);
245 }
ca792680 246 }
5ff311f0 247 // weeks
248 for ($i = 1; $i < 10; $i++) {
249 if (strtotime('-'.$i.' weeks',$now) >= $minlastaccess) {
250 $timeoptions[strtotime('-'.$i.' weeks',$now)] = get_string('numweeks','moodle',$i);
251 }
ca792680 252 }
5ff311f0 253 // months
254 for ($i = 2; $i < 12; $i++) {
255 if (strtotime('-'.$i.' months',$now) >= $minlastaccess) {
256 $timeoptions[strtotime('-'.$i.' months',$now)] = get_string('nummonths','moodle',$i);
257 }
258 }
259 // try a year
260 if (strtotime('-1 year',$now) >= $minlastaccess) {
261 $timeoptions[strtotime('-1 year',$now)] = get_string('lastyear');
31b71336 262 }
87a13824 263
5ff311f0 264 if (!empty($lastaccess0exists)) {
265 $timeoptions[-1] = get_string('never');
266 }
87a13824 267
5ff311f0 268 if (count($timeoptions) > 1) {
f8dab966 269 $select = new single_select($baseurl, 'accesssince', $timeoptions, $accesssince, null, 'timeoptions');
d7270311 270 $select->set_label(get_string('usersnoaccesssince'));
f8dab966 271 $controlstable->data[0]->cells[] = $OUTPUT->render($select);
5ff311f0 272 }
77c645df 273 }
87a13824 274
073af1a6 275 $formatmenu = array( '0' => get_string('brief'),
276 '1' => get_string('userdetails'));
f8dab966 277 $select = new single_select($baseurl, 'mode', $formatmenu, $mode, null, 'formatmenu');
d7270311 278 $select->set_label(get_string('userlist'));
4e487ce2 279 $userlistcell = new html_table_cell();
16be8974 280 $userlistcell->attributes['class'] = 'right';
f8dab966 281 $userlistcell->text = $OUTPUT->render($select);
4e487ce2 282 $controlstable->data[0]->cells[] = $userlistcell;
283
16be8974 284 echo html_writer::table($controlstable);
ff3caf30 285
224aa44a 286 if ($currentgroup and (!$isseparategroups or has_capability('moodle/site:accessallgroups', $context))) { /// Display info about the group
ffc536af 287 if ($group = groups_get_group($currentgroup)) {
87a13824 288 if (!empty($group->description) or (!empty($group->picture) and empty($group->hidepicture))) {
4e487ce2 289 $groupinfotable = new html_table();
16be8974 290 $groupinfotable->attributes['class'] = 'groupinfobox';
4e487ce2 291 $picturecell = new html_table_cell();
16be8974 292 $picturecell->attributes['class'] = 'left side picture';
b60cae86 293 $picturecell->text = print_group_picture($group, $course->id, true, true, false);
aa6c1ced 294
4e487ce2 295 $contentcell = new html_table_cell();
16be8974 296 $contentcell->attributes['class'] = 'content';
4e487ce2 297
298 $contentheading = $group->name;
224aa44a 299 if (has_capability('moodle/course:managegroups', $context)) {
a6855934 300 $aurl = new moodle_url('/group/group.php', array('id' => $group->id, 'courseid' => $group->courseid));
c63923bd 301 $contentheading .= '&nbsp;' . $OUTPUT->action_icon($aurl, new pix_icon('t/edit', get_string('editgroupprofile')));
2c27cd19 302 }
8bdc9cac 303
64f93798 304 $group->description = file_rewrite_pluginfile_urls($group->description, 'pluginfile.php', $context->id, 'group', 'description', $group->id);
8bdc9cac
SH
305 if (!isset($group->descriptionformat)) {
306 $group->descriptionformat = FORMAT_MOODLE;
307 }
308 $contentcell->text = $OUTPUT->heading($contentheading, 3) . format_text($group->description, $group->descriptionformat);
8cea545e 309 $groupinfotable->data[] = new html_table_row(array($picturecell, $contentcell));
16be8974 310 echo html_writer::table($groupinfotable);
ff3caf30 311 }
312 }
313 }
314
77c645df 315 /// Define a table showing a list of users in the current role selection
316
1d40c70b 317 $tablecolumns = array('userpic', 'fullname');
d6cc2341 318 $tableheaders = array(get_string('userpic'), get_string('fullnameuser'));
073af1a6 319 if ($mode === MODE_BRIEF && !isset($hiddenfields['city'])) {
77c645df 320 $tablecolumns[] = 'city';
321 $tableheaders[] = get_string('city');
322 }
073af1a6 323 if ($mode === MODE_BRIEF && !isset($hiddenfields['country'])) {
77c645df 324 $tablecolumns[] = 'country';
325 $tableheaders[] = get_string('country');
326 }
327 if (!isset($hiddenfields['lastaccess'])) {
328 $tablecolumns[] = 'lastaccess';
329 $tableheaders[] = get_string('lastaccess');
330 }
331
77c645df 332 if ($bulkoperations) {
664fe87f 333 $tablecolumns[] = 'select';
77c645df 334 $tableheaders[] = get_string('select');
335 }
336
04186cd9 337 $table = new flexible_table('user-index-participants-'.$course->id);
77c645df 338
339 $table->define_columns($tablecolumns);
340 $table->define_headers($tableheaders);
d7270311 341 $table->define_baseurl($baseurl->out());
0be6f678 342
5ff311f0 343 if (!isset($hiddenfields['lastaccess'])) {
344 $table->sortable(true, 'lastaccess', SORT_DESC);
345 }
346
664fe87f 347 $table->no_sorting('roles');
348 $table->no_sorting('groups');
349 $table->no_sorting('groupings');
350 $table->no_sorting('select');
77c645df 351
352 $table->set_attribute('cellspacing', '0');
04186cd9 353 $table->set_attribute('id', 'participants');
77c645df 354 $table->set_attribute('class', 'generaltable generalbox');
355
356 $table->set_control_variables(array(
357 TABLE_VAR_SORT => 'ssort',
358 TABLE_VAR_HIDE => 'shide',
359 TABLE_VAR_SHOW => 'sshow',
360 TABLE_VAR_IFIRST => 'sifirst',
361 TABLE_VAR_ILAST => 'silast',
362 TABLE_VAR_PAGE => 'spage'
363 ));
364 $table->setup();
365
77c645df 366 // we are looking for all users with this role assigned in this context or higher
4f0c2d00 367 $contextlist = get_related_contexts_string($context);
5f9e296a 368
df997f84 369 list($esql, $params) = get_enrolled_sql($context, NULL, $currentgroup);
4f0c2d00
PS
370 $joins = array("FROM {user} u");
371 $wheres = array();
372
373 if ($isfrontpage) {
374 $select = "SELECT u.id, u.username, u.firstname, u.lastname,
5f9e296a 375 u.email, u.city, u.country, u.picture,
376 u.lang, u.timezone, u.emailstop, u.maildisplay, u.imagealt,
4f0c2d00
PS
377 u.lastaccess";
378 $joins[] = "JOIN ($esql) e ON e.id = u.id"; // everybody on the frontpage usually
379 if ($accesssince) {
380 $wheres[] = get_user_lastaccess_sql($accesssince);
381 }
382
383 } else {
384 $select = "SELECT u.id, u.username, u.firstname, u.lastname,
5f9e296a 385 u.email, u.city, u.country, u.picture,
386 u.lang, u.timezone, u.emailstop, u.maildisplay, u.imagealt,
4f0c2d00
PS
387 COALESCE(ul.timeaccess, 0) AS lastaccess";
388 $joins[] = "JOIN ($esql) e ON e.id = u.id"; // course enrolled users only
389 $joins[] = "LEFT JOIN {user_lastaccess} ul ON (ul.userid = u.id AND ul.courseid = :courseid)"; // not everybody accessed course yet
390 $params['courseid'] = $course->id;
391 if ($accesssince) {
392 $wheres[] = get_course_lastaccess_sql($accesssince);
5f9e296a 393 }
165088f6 394 }
5f9e296a 395
4f0c2d00
PS
396 // performance hacks - we preload user contexts together with accounts
397 list($ccselect, $ccjoin) = context_instance_preload_sql('u.id', CONTEXT_USER, 'ctx');
398 $select .= $ccselect;
399 $joins[] = $ccjoin;
c0527567 400
4f0c2d00
PS
401
402 // limit list to users with some role only
403 if ($roleid) {
404 $wheres[] = "u.id IN (SELECT userid FROM {role_assignments} WHERE roleid = :roleid AND contextid $contextlist)";
405 $params['roleid'] = $roleid;
c0527567 406 }
0be6f678 407
4f0c2d00
PS
408 $from = implode("\n", $joins);
409 if ($wheres) {
410 $where = "WHERE " . implode(" AND ", $wheres);
165088f6 411 } else {
4f0c2d00 412 $where = "";
165088f6 413 }
4f0c2d00
PS
414
415 $totalcount = $DB->count_records_sql("SELECT COUNT(u.id) $from $where", $params);
77c645df 416
417 if (!empty($search)) {
ce8c75ee 418 $fullname = $DB->sql_fullname('u.firstname','u.lastname');
f63ac65a
PS
419 $wheres[] = "(". $DB->sql_like($fullname, ':search1', false, false) .
420 " OR ". $DB->sql_like('email', ':search2', false, false) .
421 " OR ". $DB->sql_like('idnumber', ':search3', false, false) .") ";
ce8c75ee 422 $params['search1'] = "%$search%";
423 $params['search2'] = "%$search%";
424 $params['search3'] = "%$search%";
77c645df 425 }
426
0f21a964
PS
427 list($twhere, $tparams) = $table->get_sql_where();
428 if ($twhere) {
429 $wheres[] = $twhere;
430 $params = array_merge($params, $tparams);
77c645df 431 }
432
4f0c2d00
PS
433 $from = implode("\n", $joins);
434 if ($wheres) {
435 $where = "WHERE " . implode(" AND ", $wheres);
436 } else {
437 $where = "";
77c645df 438 }
439
440 if ($table->get_sql_sort()) {
4d93bc9e 441 $sort = ' ORDER BY '.$table->get_sql_sort();
77c645df 442 } else {
4d93bc9e 443 $sort = '';
77c645df 444 }
445
4f0c2d00 446 $matchcount = $DB->count_records_sql("SELECT COUNT(u.id) $from $where", $params);
77c645df 447
281917e9 448 $table->initialbars(true);
77c645df 449 $table->pagesize($perpage, $matchcount);
450
4f0c2d00
PS
451 // list of users at the current visible page - paging makes it relatively short
452 $userlist = $DB->get_recordset_sql("$select $from $where $sort", $params, $table->get_page_start(), $table->get_page_size());
3e219038 453
5f9e296a 454 /// If there are multiple Roles in the course, then show a drop down menu for switching
6d3c57f4 455 if (count($rolenames) > 1) {
77c645df 456 echo '<div class="rolesform">';
5f9e296a 457 echo '<label for="rolesform_jump">'.get_string('currentrole', 'role').'&nbsp;</label>';
f8dab966 458 echo $OUTPUT->single_select($rolenamesurl, 'roleid', $rolenames, $roleid, null, 'rolesform');
0f870a49 459 echo '</div>';
5f9e296a 460
461 } else if (count($rolenames) == 1) {
462 // when all users with the same role - print its name
463 echo '<div class="rolesform">';
995f2d51 464 echo get_string('role').get_string('labelsep', 'langconfig');
5f9e296a 465 $rolename = reset($rolenames);
466 echo $rolename;
467 echo '</div>';
77c645df 468 }
3e219038 469
5f9e296a 470 if ($roleid > 0) {
b90e2f19 471 $a->number = $totalcount;
4f0c2d00 472 $a->role = $rolenames[$roleid];
5f9e296a 473 $heading = format_string(get_string('xuserswiththerole', 'role', $a));
f642a21a 474
475 if ($currentgroup and $group) {
476 $a->group = $group->name;
5f9e296a 477 $heading .= ' ' . format_string(get_string('ingroup', 'role', $a));
478 }
f642a21a 479
480 if ($accesssince) {
481 $a->timeperiod = $timeoptions[$accesssince];
5f9e296a 482 $heading .= ' ' . format_string(get_string('inactiveformorethan', 'role', $a));
f642a21a 483 }
484
485 $heading .= ": $a->number";
d02eeded 486 if (user_can_assign($context, $roleid)) {
3e219038 487 $heading .= ' <a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?roleid='.$roleid.'&amp;contextid='.$context->id.'">';
b5d0cafc 488 $heading .= '<img src="'.$OUTPUT->pix_url('i/edit') . '" class="icon" alt="" /></a>';
3e219038 489 }
04a7ba52 490 echo $OUTPUT->heading($heading, 3);
3e219038 491 } else {
d9e29086
DM
492 if ($course->id != SITEID && has_capability('moodle/course:enrolreview', $context)) {
493 $editlink = $OUTPUT->action_icon(new moodle_url('/enrol/users.php', array('id' => $course->id)),
494 new pix_icon('i/edit', get_string('edit')));
15234a92 495 } else {
496 $editlink = '';
497 }
5f9e296a 498 if ($course->id == SITEID and $roleid < 0) {
499 $strallparticipants = get_string('allsiteusers', 'role');
500 } else {
501 $strallparticipants = get_string('allparticipants');
502 }
23f5ee25 503 if ($matchcount < $totalcount) {
995f2d51 504 echo $OUTPUT->heading($strallparticipants.get_string('labelsep', 'langconfig').$matchcount.'/'.$totalcount . $editlink, 3);
23f5ee25 505 } else {
995f2d51 506 echo $OUTPUT->heading($strallparticipants.get_string('labelsep', 'langconfig').$matchcount . $editlink, 3);
23f5ee25 507 }
3e219038 508 }
3e219038 509
77c645df 510
511 if ($bulkoperations) {
2ea56951 512 echo '<form action="action_redir.php" method="post" id="participantsform">';
c1138797 513 echo '<div>';
d4a1fcaf 514 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
838c7d29 515 echo '<input type="hidden" name="returnto" value="'.s(me()).'" />';
77c645df 516 }
517
4f0c2d00 518 if ($mode === MODE_USERDETAILS) { // Print simple listing
77c645df 519 if ($totalcount < 1) {
8fa89bfd 520 echo $OUTPUT->heading(get_string('nothingtodisplay'));
77c645df 521 } else {
522 if ($totalcount > $perpage) {
523
524 $firstinitial = $table->get_initial_first();
525 $lastinitial = $table->get_initial_last();
526 $strall = get_string('all');
61bb07c2 527 $alpha = explode(',', get_string('alphabet', 'langconfig'));
77c645df 528
529 // Bar of first initials
530
531 echo '<div class="initialbar firstinitial">'.get_string('firstname').' : ';
532 if(!empty($firstinitial)) {
d7270311 533 echo '<a href="'.$baseurl->out().'&amp;sifirst=">'.$strall.'</a>';
77c645df 534 } else {
535 echo '<strong>'.$strall.'</strong>';
536 }
537 foreach ($alpha as $letter) {
538 if ($letter == $firstinitial) {
539 echo ' <strong>'.$letter.'</strong>';
ee4a52c5 540 } else {
d7270311 541 echo ' <a href="'.$baseurl->out().'&amp;sifirst='.$letter.'">'.$letter.'</a>';
ee4a52c5 542 }
ee4a52c5 543 }
77c645df 544 echo '</div>';
545
546 // Bar of last initials
547
548 echo '<div class="initialbar lastinitial">'.get_string('lastname').' : ';
549 if(!empty($lastinitial)) {
d7270311 550 echo '<a href="'.$baseurl->out().'&amp;silast=">'.$strall.'</a>';
77c645df 551 } else {
552 echo '<strong>'.$strall.'</strong>';
553 }
554 foreach ($alpha as $letter) {
555 if ($letter == $lastinitial) {
556 echo ' <strong>'.$letter.'</strong>';
557 } else {
d7270311 558 echo ' <a href="'.$baseurl->out().'&amp;silast='.$letter.'">'.$letter.'</a>';
ee4a52c5 559 }
560 }
77c645df 561 echo '</div>';
562
929d7a83 563 $pagingbar = new paging_bar($matchcount, intval($table->get_page_start() / $perpage), $perpage, $baseurl);
da9ac19f 564 $pagingbar->pagevar = 'spage';
105666bb 565 echo $OUTPUT->render($pagingbar);
77c645df 566 }
567
568 if ($matchcount > 0) {
1f807bc4 569 $usersprinted = array();
ce8c75ee 570 foreach ($userlist as $user) {
1f807bc4 571 if (in_array($user->id, $usersprinted)) { /// Prevent duplicates by r.hidden - MDL-13935
572 continue;
573 }
574 $usersprinted[] = $user->id; /// Add new user to the array of users printed
575
4f0c2d00 576 context_instance_preload($user);
c351150f 577
578 $context = get_context_instance(CONTEXT_COURSE, $course->id);
4f0c2d00 579 $usercontext = get_context_instance(CONTEXT_USER, $user->id);
c351150f 580
0aa759b0 581 $countries = get_string_manager()->get_list_of_countries();
c351150f 582
583 /// Get the hidden field list
584 if (has_capability('moodle/course:viewhiddenuserfields', $context)) {
585 $hiddenfields = array();
586 } else {
587 $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
588 }
589 $table = new html_table();
16be8974 590 $table->attributes['class'] = 'userinfobox';
c351150f 591
592 $row = new html_table_row();
593 $row->cells[0] = new html_table_cell();
16be8974 594 $row->cells[0]->attributes['class'] = 'left side';
f2f085ee 595
812dbaf7 596 $row->cells[0]->text = $OUTPUT->user_picture($user, array('courseid'=>$course->id));
c351150f 597 $row->cells[1] = new html_table_cell();
16be8974 598 $row->cells[1]->attributes['class'] = 'content';
c351150f 599
600 $row->cells[1]->text = $OUTPUT->container(fullname($user, has_capability('moodle/site:viewfullnames', $context)), 'username');
601 $row->cells[1]->text .= $OUTPUT->container_start('info');
602
603 if (!empty($user->role)) {
995f2d51 604 $row->cells[1]->text .= get_string('role').get_string('labelsep', 'langconfig').$user->role.'<br />';
c351150f 605 }
474f6bfe 606 if ($user->maildisplay == 1 or ($user->maildisplay == 2 and ($course->id != SITEID) and !isguestuser()) or
c351150f 607 has_capability('moodle/course:viewhiddenuserfields', $context)) {
995f2d51 608 $row->cells[1]->text .= get_string('email').get_string('labelsep', 'langconfig').html_writer::link("mailto:$user->email", $user->email) . '<br />';
c351150f 609 }
610 if (($user->city or $user->country) and (!isset($hiddenfields['city']) or !isset($hiddenfields['country']))) {
995f2d51 611 $row->cells[1]->text .= get_string('city').get_string('labelsep', 'langconfig');
c351150f 612 if ($user->city && !isset($hiddenfields['city'])) {
613 $row->cells[1]->text .= $user->city;
614 }
615 if (!empty($countries[$user->country]) && !isset($hiddenfields['country'])) {
616 if ($user->city && !isset($hiddenfields['city'])) {
617 $row->cells[1]->text .= ', ';
618 }
619 $row->cells[1]->text .= $countries[$user->country];
620 }
621 $row->cells[1]->text .= '<br />';
622 }
623
624 if (!isset($hiddenfields['lastaccess'])) {
625 if ($user->lastaccess) {
995f2d51 626 $row->cells[1]->text .= get_string('lastaccess').get_string('labelsep', 'langconfig').userdate($user->lastaccess);
c351150f 627 $row->cells[1]->text .= '&nbsp; ('. format_time(time() - $user->lastaccess, $datestring) .')';
628 } else {
995f2d51 629 $row->cells[1]->text .= get_string('lastaccess').get_string('labelsep', 'langconfig').get_string('never');
c351150f 630 }
631 }
632
633 $row->cells[1]->text .= $OUTPUT->container_end();
3aac07d8 634
c351150f 635 $row->cells[2] = new html_table_cell();
16be8974 636 $row->cells[2]->attributes['class'] = 'links';
c351150f 637 $row->cells[2]->text = '';
3aac07d8 638
c351150f 639 $links = array();
640
641 if ($CFG->bloglevel > 0) {
a6855934 642 $links[] = html_writer::link(new moodle_url('/blog/index.php?userid='.$user->id), get_string('blogs','blog'));
c351150f 643 }
644
645 if (!empty($CFG->enablenotes) and (has_capability('moodle/notes:manage', $context) || has_capability('moodle/notes:view', $context))) {
a6855934 646 $links[] = html_writer::link(new moodle_url('/notes/index.php?course=' . $course->id. '&user='.$user->id), get_string('notes','notes'));
c351150f 647 }
648
649 if (has_capability('moodle/site:viewreports', $context) or has_capability('moodle/user:viewuseractivitiesreport', $usercontext)) {
a6855934 650 $links[] = html_writer::link(new moodle_url('/course/user.php?id='. $course->id .'&user='. $user->id), get_string('activity'));
c351150f 651 }
652
4f0c2d00 653 if ($USER->id != $user->id && !session_is_loggedinas() && has_capability('moodle/user:loginas', $context) && !is_siteadmin($user->id)) {
a6855934 654 $links[] = html_writer::link(new moodle_url('/course/loginas.php?id='. $course->id .'&user='. $user->id .'&sesskey='. sesskey()), get_string('loginas'));
c351150f 655 }
656
a6855934 657 $links[] = html_writer::link(new moodle_url('/user/view.php?id='. $user->id .'&course='. $course->id), get_string('fullprofile') . '...');
3aac07d8 658
f8dab966 659 $row->cells[2]->text .= implode('', $links);
c351150f 660
661 if (!empty($messageselect)) {
662 $row->cells[2]->text .= '<br /><input type="checkbox" name="user'.$user->id.'" /> ';
663 }
664 $table->data = array($row);
16be8974 665 echo html_writer::table($table);
ee4a52c5 666 }
77c645df 667
668 } else {
8fa89bfd 669 echo $OUTPUT->heading(get_string('nothingtodisplay'));
ee4a52c5 670 }
671 }
77c645df 672
673 } else {
674 $countrysort = (strpos($sort, 'country') !== false);
675 $timeformat = get_string('strftimedate');
3997cb40 676
677
03cedd62 678 if ($userlist) {
664fe87f 679
1f807bc4 680 $usersprinted = array();
ce8c75ee 681 foreach ($userlist as $user) {
1f807bc4 682 if (in_array($user->id, $usersprinted)) { /// Prevent duplicates by r.hidden - MDL-13935
683 continue;
684 }
685 $usersprinted[] = $user->id; /// Add new user to the array of users printed
686
4f0c2d00 687 context_instance_preload($user);
0be6f678 688
04186cd9 689 if ($user->lastaccess) {
690 $lastaccess = format_time(time() - $user->lastaccess, $datestring);
77c645df 691 } else {
692 $lastaccess = $strnever;
693 }
694
04186cd9 695 if (empty($user->country)) {
77c645df 696 $country = '';
697
698 } else {
699 if($countrysort) {
04186cd9 700 $country = '('.$user->country.') '.$countries[$user->country];
ee4a52c5 701 }
702 else {
04186cd9 703 $country = $countries[$user->country];
ee4a52c5 704 }
77c645df 705 }
0be6f678 706
4f0c2d00 707 $usercontext = get_context_instance(CONTEXT_USER, $user->id);
0be6f678 708
b08261a1 709 if ($piclink = ($USER->id == $user->id || has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext))) {
22ae509e 710 $profilelink = '<strong><a href="'.$CFG->wwwroot.'/user/view.php?id='.$user->id.'&amp;course='.$course->id.'">'.fullname($user).'</a></strong>';
711 } else {
0be6f678 712 $profilelink = '<strong>'.fullname($user).'</strong>';
22ae509e 713 }
0be6f678 714
4f0c2d00 715 $data = array ($OUTPUT->user_picture($user, array('courseid'=>$course->id)), $profilelink);
22ae509e 716
073af1a6 717 if ($mode === MODE_BRIEF && !isset($hiddenfields['city'])) {
04186cd9 718 $data[] = $user->city;
77c645df 719 }
073af1a6 720 if ($mode === MODE_BRIEF && !isset($hiddenfields['country'])) {
77c645df 721 $data[] = $country;
722 }
723 if (!isset($hiddenfields['lastaccess'])) {
724 $data[] = $lastaccess;
725 }
664fe87f 726
727 if (isset($userlist_extra) && isset($userlist_extra[$user->id])) {
728 $ras = $userlist_extra[$user->id]['ra'];
729 $rastring = '';
730 foreach ($ras AS $key=>$ra) {
4f0c2d00 731 $rolename = $allrolenames[$ra['roleid']] ;
664fe87f 732 if ($ra['ctxlevel'] == CONTEXT_COURSECAT) {
073af1a6 733 $rastring .= $rolename. ' @ ' . '<a href="'.$CFG->wwwroot.'/course/category.php?id='.$ra['ctxinstanceid'].'">'.s($ra['ccname']).'</a>';
664fe87f 734 } elseif ($ra['ctxlevel'] == CONTEXT_SYSTEM) {
073af1a6 735 $rastring .= $rolename. ' - ' . get_string('globalrole','role');
664fe87f 736 } else {
737 $rastring .= $rolename;
738 }
664fe87f 739 }
06e84d52 740 $data[] = $rastring;
a32e05df 741 if ($groupmode != 0) {
664fe87f 742 // htmlescape with s() and implode the array
743 $data[] = implode(', ', array_map('s',$userlist_extra[$user->id]['group']));
98da6021 744 $data[] = implode(', ', array_map('s', $userlist_extra[$user->id]['gping']));
664fe87f 745 }
664fe87f 746 }
747
77c645df 748 if ($bulkoperations) {
2ea56951 749 $data[] = '<input type="checkbox" class="usercheckbox" name="user'.$user->id.'" />';
77c645df 750 }
751 $table->add_data($data);
ee4a52c5 752
ee4a52c5 753 }
ee4a52c5 754 }
b90e2f19 755
77c645df 756 $table->print_html();
757
758 }
759
760 if ($bulkoperations) {
c1138797 761 echo '<br /><div class="buttons">';
2ea56951
PS
762 echo '<input type="button" id="checkall" value="'.get_string('selectall').'" /> ';
763 echo '<input type="button" id="checknone" value="'.get_string('deselectall').'" /> ';
82d561ee 764 $displaylist = array();
576ad290 765 $displaylist['messageselect.php'] = get_string('messageselectadd');
90658eef 766 if (!empty($CFG->enablenotes) && has_capability('moodle/notes:manage', $context) && $context->id != $frontpagectx->id) {
eca3af25 767 $displaylist['addnote.php'] = get_string('addnewnote', 'notes');
768 $displaylist['groupaddnote.php'] = get_string('groupaddnewnote', 'notes');
769 }
576ad290 770
62357718 771 echo $OUTPUT->help_icon('withselectedusers');
26acc814 772 echo html_writer::tag('label', get_string("withselectedusers"), array('for'=>'formactionid'));
2ea56951
PS
773 echo html_writer::select($displaylist, 'formaction', '', array(''=>'choosedots'), array('id'=>'formactionid'));
774
70ce923e 775 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
2ea56951
PS
776 echo '<noscript style="display:inline">';
777 echo '<input type="submit" value="'.get_string('ok').'" />';
778 echo '</noscript>';
779 echo '</div></div>';
c1138797 780 echo '</form>';
d88c5043 781
2ea56951
PS
782 $module = array('name'=>'core_user', 'fullpath'=>'/user/module.js');
783 $PAGE->requires->js_init_call('M.core_user.init_participation', null, false, $module);
77c645df 784 }
b90e2f19 785
3a8f4b90 786 if (has_capability('moodle/site:viewparticipants', $context) && $totalcount > ($perpage*3)) {
8c275093 787 echo '<form action="index.php" class="searchform"><div><input type="hidden" name="id" value="'.$course->id.'" />'.get_string('search').':&nbsp;'."\n";
3593af19 788 echo '<input type="text" name="search" value="'.s($search).'" />&nbsp;<input type="submit" value="'.get_string('search').'" /></div></form>'."\n";
77c645df 789 }
b90e2f19 790
d7270311 791 $perpageurl = clone($baseurl);
792 $perpageurl->remove_params('perpage');
77c645df 793 if ($perpage == SHOW_ALL_PAGE_SIZE) {
d7270311 794 $perpageurl->param('perpage', DEFAULT_PAGE_SIZE);
0f4c64b7 795 echo $OUTPUT->container(html_writer::link($perpageurl, get_string('showperpage', '', DEFAULT_PAGE_SIZE)), array(), 'showall');
77c645df 796
797 } else if ($matchcount > 0 && $perpage < $matchcount) {
d7270311 798 $perpageurl->param('perpage', SHOW_ALL_PAGE_SIZE);
0f4c64b7 799 echo $OUTPUT->container(html_writer::link($perpageurl, get_string('showall', '', $matchcount)), array(), 'showall');
b90e2f19 800 }
77c645df 801
99cca847
MD
802 echo '</div>'; // userlist
803
0ab75c34 804 echo $OUTPUT->footer();
f9903ed0 805
03cedd62 806 if ($userlist) {
ce8c75ee 807 $userlist->close();
03cedd62 808 }
77c645df 809
810
0749caef 811function get_course_lastaccess_sql($accesssince='') {
31b71336 812 if (empty($accesssince)) {
813 return '';
814 }
815 if ($accesssince == -1) { // never
4f0c2d00 816 return 'ul.timeaccess = 0';
31b71336 817 } else {
4f0c2d00 818 return 'ul.timeaccess != 0 AND ul.timeaccess < '.$accesssince;
0749caef 819 }
820}
821
822function get_user_lastaccess_sql($accesssince='') {
823 if (empty($accesssince)) {
824 return '';
825 }
826 if ($accesssince == -1) { // never
4f0c2d00 827 return 'u.lastaccess = 0';
0749caef 828 } else {
4f0c2d00 829 return 'u.lastaccess != 0 AND u.lastaccess < '.$accesssince;
31b71336 830 }
831}
832
4f0c2d00 833function get_participants_extra ($userids, $course, $context) {
ce8c75ee 834 global $CFG, $DB;
664fe87f 835
4f0c2d00 836 if (count($userids) === 0) {
664fe87f 837 return array();
838 }
839
ce8c75ee 840 $params = array();
841
664fe87f 842 $userids = implode(',', $userids);
843
844 // turn the path into a list of context ids
845 $contextids = substr($context->path, 1); // kill leading slash
846 $contextids = str_replace('/', ',', $contextids);;
847
98da6021
PS
848 $gpjoin = "LEFT OUTER JOIN {groupings_groups} gpg
849 ON gpg.groupid=g.id
850 LEFT OUTER JOIN {groupings} gp
851 ON (gp.courseid={$course->id} AND gp.id=gpg.groupingid)";
852 $gpselect = ',gp.id AS gpid, gp.name AS gpname ';
664fe87f 853
854 // Note: this returns strange redundant rows, perhaps
855 // due to the multiple OUTER JOINs. If we can tweak the
856 // JOINs to avoid it ot
06e84d52 857 $sql = "SELECT DISTINCT ra.userid,
858 ctx.id AS ctxid, ctx.path AS ctxpath, ctx.depth AS ctxdepth,
664fe87f 859 ctx.contextlevel AS ctxlevel, ctx.instanceid AS ctxinstanceid,
06e84d52 860 cc.name AS ccname,
664fe87f 861 ra.roleid AS roleid,
664fe87f 862 g.id AS gid, g.name AS gname
863 $gpselect
ce8c75ee 864 FROM {role_assignments} ra
865 JOIN {context} ctx
866 ON (ra.contextid=ctx.id)
867 LEFT JOIN {course_categories} cc
868 ON (ctx.contextlevel=40 AND ctx.instanceid=cc.id)
664fe87f 869
870 /* only if groups active */
ce8c75ee 871 LEFT JOIN {groups_members} gm
872 ON (ra.userid=gm.userid)
873 LEFT JOIN {groups} g
874 ON (gm.groupid=g.id AND g.courseid={$course->id})
664fe87f 875 /* and if groupings is enabled... */
876 $gpjoin
877
06e84d52 878 WHERE ra.userid IN ( $userids )
879 AND ra.contextid in ( $contextids )
664fe87f 880
ce8c75ee 881 ORDER BY ra.userid, ctx.depth DESC";
664fe87f 882
ce8c75ee 883 $rs = $DB->get_recordset_sql($sql, $params);
664fe87f 884 $extra = array();
885
886 // Data structure -
887 // $extra [ $userid ] [ 'group' ] [ $groupid => 'group name']
888 // [ 'gping' ] [ $gpingid => 'gping name']
889 // [ 'ra' ] [ [ "$ctxid:$roleid" => [ctxid => $ctxid
06e84d52 890 // ctxdepth => $ctxdepth,
664fe87f 891 // ctxpath => $ctxpath,
892 // ctxname => 'name' (categories only)
06e84d52 893 // ctxinstid =>
664fe87f 894 // roleid => $roleid
664fe87f 895
ce8c75ee 896 foreach ($rs as $rec) {
664fe87f 897 $userid = $rec->userid;
898
899 // Prime an initial user rec...
900 if (!isset($extra[$userid])) {
901 $extra[$userid] = array( 'group' => array(),
902 'gping' => array(),
903 'ra' => array() );
904 }
905
906 if (!empty($rec->gid)) {
907 $extra[$userid]['group'][$rec->gid]= $rec->gname;
908 }
909 if (!empty($rec->gpid)) {
910 $extra[$userid]['gping'][$rec->gpid]= $rec->gpname;
911 }
912 $rakey = $rec->ctxid . ':' . $rec->roleid;
913 if (!isset($extra[$userid]['ra'][$rakey])) {
914 $extra[$userid]['ra'][$rakey] = array('ctxid' => $rec->ctxid,
915 'ctxlevel' => $rec->ctxlevel,
916 'ctxinstanceid' => $rec->ctxinstanceid,
917 'ccname' => $rec->ccname,
df997f84 918 'roleid' => $rec->roleid);
664fe87f 919
920 }
921 }
ce8c75ee 922 $rs->close();
664fe87f 923 return $extra;
924
925}
926
aa6c1ced 927