MDL-24471, FILEMANAGER change <button> to <input type="button" />, moodle form may...
[moodle.git] / user / index.php
blob545c8572dc033f5aec61ae3d6793a771eb008ed8
1 <?php
3 // Lists all the users within a given course
5 require_once('../config.php');
6 require_once($CFG->libdir.'/tablelib.php');
8 define('USER_SMALL_CLASS', 20); // Below this is considered small
9 define('USER_LARGE_CLASS', 200); // Above this is considered large
10 define('DEFAULT_PAGE_SIZE', 20);
11 define('SHOW_ALL_PAGE_SIZE', 5000);
12 define('MODE_BRIEF', 0);
13 define('MODE_USERDETAILS', 1);
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
17 $mode = optional_param('mode', NULL, PARAM_INT); // use the MODE_ constants
18 $accesssince = optional_param('accesssince',0,PARAM_INT); // filter by last access. -1 = never
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)
22 $contextid = optional_param('contextid', 0, PARAM_INT); // one of this or
23 $courseid = optional_param('id', 0, PARAM_INT); // this are required
25 $PAGE->set_url('/user/index.php', array(
26 'page' => $page,
27 'perpage' => $perpage,
28 'mode' => $mode,
29 'accesssince' => $accesssince,
30 'search' => $search,
31 'roleid' => $roleid,
32 'contextid' => $contextid,
33 'courseid' => $courseid));
35 if ($contextid) {
36 $context = get_context_instance_by_id($contextid, MUST_EXIST);
37 if ($context->contextlevel != CONTEXT_COURSE) {
38 print_error('invalidcontext');
40 $course = $DB->get_record('course', array('id'=>$context->instanceid), '*', MUST_EXIST);
41 } else {
42 $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
43 $context = get_context_instance(CONTEXT_COURSE, $course->id, MUST_EXIST);
45 // not needed anymore
46 unset($contextid);
47 unset($courseid);
49 require_login($course);
51 $systemcontext = get_context_instance(CONTEXT_SYSTEM);
52 $isfrontpage = ($course->id == SITEID);
54 $frontpagectx = get_context_instance(CONTEXT_COURSE, SITEID);
56 if ($isfrontpage) {
57 $PAGE->set_pagelayout('admin');
58 require_capability('moodle/site:viewparticipants', $systemcontext);
59 } else {
60 $PAGE->set_pagelayout('incourse');
61 require_capability('moodle/course:viewparticipants', $context);
64 $rolenamesurl = new moodle_url("$CFG->wwwroot/user/index.php?contextid=$context->id&sifirst=&silast=");
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'));
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];
82 // make sure other roles may not be selected by any means
83 if (empty($rolenames[$roleid])) {
84 print_error('noparticipants');
87 // no roles to display yet?
88 // frontpage course is an exception, on the front page course we should display all users
89 if (empty($rolenames) && !$isfrontpage) {
90 if (has_capability('moodle/role:assign', $context)) {
91 redirect($CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.$context->id);
92 } else {
93 print_error('noparticipants');
97 add_to_log($course->id, 'user', 'view all', 'index.php?id='.$course->id, '');
99 $bulkoperations = has_capability('moodle/course:bulkmessaging', $context);
101 $countries = get_string_manager()->get_list_of_countries();
103 $strnever = get_string('never');
105 $datestring->year = get_string('year');
106 $datestring->years = get_string('years');
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');
116 if ($mode !== NULL) {
117 $mode = (int)$mode;
118 $SESSION->userindexmode = $mode;
119 } else if (isset($SESSION->userindexmode)) {
120 $mode = (int)$SESSION->userindexmode;
121 } else {
122 $mode = MODE_BRIEF;
125 /// Check to see if groups are being used in this course
126 /// and if so, set $currentgroup to reflect the current group
128 $groupmode = groups_get_course_groupmode($course); // Groups are being used
129 $currentgroup = groups_get_course_group($course, true);
131 if (!$currentgroup) { // To make some other functions work better later
132 $currentgroup = NULL;
135 $isseparategroups = ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context));
137 if ($course->id===SITEID) {
138 $PAGE->navbar->ignore_active();
141 $PAGE->navbar->add(get_string('participants'));
142 $PAGE->set_title("$course->shortname: ".get_string('participants'));
143 $PAGE->set_heading($course->fullname);
144 $PAGE->set_pagetype('course-view-' . $course->format);
145 $PAGE->add_body_class('path-user'); // So we can style it independently
146 $PAGE->set_other_editing_capability('moodle/course:manageactivities');
148 echo $OUTPUT->header();
150 echo '<div class="userlist">';
152 if ($isseparategroups and (!$currentgroup) ) {
153 // The user is not in the group so show message and exit
154 echo $OUTPUT->heading(get_string("notingroup"));
155 echo $OUTPUT->footer();
156 exit;
160 // Should use this variable so that we don't break stuff every time a variable is added or changed.
161 $baseurl = new moodle_url('/user/index.php', array(
162 'contextid' => $context->id,
163 'roleid' => $roleid,
164 'id' => $course->id,
165 'perpage' => $perpage,
166 'accesssince' => $accesssince,
167 'search' => s($search)));
169 /// setting up tags
170 if ($course->id == SITEID) {
171 $filtertype = 'site';
172 } else if ($course->id && !$currentgroup) {
173 $filtertype = 'course';
174 $filterselect = $course->id;
175 } else {
176 $filtertype = 'group';
177 $filterselect = $currentgroup;
182 /// Get the hidden field list
183 if (has_capability('moodle/course:viewhiddenuserfields', $context)) {
184 $hiddenfields = array(); // teachers and admins are allowed to see everything
185 } else {
186 $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
189 if (isset($hiddenfields['lastaccess'])) {
190 // do not allow access since filtering
191 $accesssince = 0;
194 /// Print settings and things in a table across the top
195 $controlstable = new html_table();
196 $controlstable->attributes['class'] = 'controls';
197 $controlstable->cellspacing = 0;
198 $controlstable->data[] = new html_table_row();
200 /// Print my course menus
201 if ($mycourses = enrol_get_my_courses()) {
202 $courselist = array();
203 $popupurl = new moodle_url('/user/index.php?roleid='.$roleid.'&sifirst=&silast=');
204 foreach ($mycourses as $mycourse) {
205 $courselist[$mycourse->id] = format_string($mycourse->shortname);
207 if (has_capability('moodle/site:viewparticipants', $systemcontext)) {
208 unset($courselist[SITEID]);
209 $courselist = array(SITEID => format_string($SITE->shortname)) + $courselist;
211 $select = new single_select($popupurl, 'id', $courselist, $course->id, array(''=>'choosedots'), 'courseform');
212 $select->set_label(get_string('mycourses'));
213 $controlstable->data[0]->cells[] = $OUTPUT->render($select);
216 $controlstable->data[0]->cells[] = groups_print_course_menu($course, $baseurl->out(), true);
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
221 if (!$isfrontpage) {
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));
234 $now = usergetmidnight(time());
235 $timeaccess = array();
236 $baseurl->remove_params('accesssince');
238 // makes sense for this to go first.
239 $timeoptions[0] = get_string('selectperiod');
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);
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);
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);
259 // try a year
260 if (strtotime('-1 year',$now) >= $minlastaccess) {
261 $timeoptions[strtotime('-1 year',$now)] = get_string('lastyear');
264 if (!empty($lastaccess0exists)) {
265 $timeoptions[-1] = get_string('never');
268 if (count($timeoptions) > 1) {
269 $select = new single_select($baseurl, 'accesssince', $timeoptions, $accesssince, null, 'timeoptions');
270 $select->set_label(get_string('usersnoaccesssince'));
271 $controlstable->data[0]->cells[] = $OUTPUT->render($select);
275 $formatmenu = array( '0' => get_string('brief'),
276 '1' => get_string('userdetails'));
277 $select = new single_select($baseurl, 'mode', $formatmenu, $mode, null, 'formatmenu');
278 $select->set_label(get_string('userlist'));
279 $userlistcell = new html_table_cell();
280 $userlistcell->attributes['class'] = 'right';
281 $userlistcell->text = $OUTPUT->render($select);
282 $controlstable->data[0]->cells[] = $userlistcell;
284 echo html_writer::table($controlstable);
286 if ($currentgroup and (!$isseparategroups or has_capability('moodle/site:accessallgroups', $context))) { /// Display info about the group
287 if ($group = groups_get_group($currentgroup)) {
288 if (!empty($group->description) or (!empty($group->picture) and empty($group->hidepicture))) {
289 $groupinfotable = new html_table();
290 $groupinfotable->attributes['class'] = 'groupinfobox';
291 $picturecell = new html_table_cell();
292 $picturecell->attributes['class'] = 'left side picture';
293 $picturecell->text = print_group_picture($group, $course->id, true, true, false);
295 $contentcell = new html_table_cell();
296 $contentcell->attributes['class'] = 'content';
298 $contentheading = $group->name;
299 if (has_capability('moodle/course:managegroups', $context)) {
300 $aurl = new moodle_url('/group/group.php', array('id' => $group->id, 'courseid' => $group->courseid));
301 $contentheading .= '&nbsp;' . $OUTPUT->action_icon($aurl, new pix_icon('t/edit', get_string('editgroupprofile')));
304 $group->description = file_rewrite_pluginfile_urls($group->description, 'pluginfile.php', $context->id, 'group', 'description', $group->id);
305 if (!isset($group->descriptionformat)) {
306 $group->descriptionformat = FORMAT_MOODLE;
308 $contentcell->text = $OUTPUT->heading($contentheading, 3) . format_text($group->description, $group->descriptionformat);
309 $groupinfotable->data[] = new html_table_row(array($picturecell, $contentcell));
310 echo html_writer::table($groupinfotable);
315 /// Define a table showing a list of users in the current role selection
317 $tablecolumns = array('userpic', 'fullname');
318 $tableheaders = array(get_string('userpic'), get_string('fullnameuser'));
319 if ($mode === MODE_BRIEF && !isset($hiddenfields['city'])) {
320 $tablecolumns[] = 'city';
321 $tableheaders[] = get_string('city');
323 if ($mode === MODE_BRIEF && !isset($hiddenfields['country'])) {
324 $tablecolumns[] = 'country';
325 $tableheaders[] = get_string('country');
327 if (!isset($hiddenfields['lastaccess'])) {
328 $tablecolumns[] = 'lastaccess';
329 $tableheaders[] = get_string('lastaccess');
332 if ($bulkoperations) {
333 $tablecolumns[] = 'select';
334 $tableheaders[] = get_string('select');
337 $table = new flexible_table('user-index-participants-'.$course->id);
339 $table->define_columns($tablecolumns);
340 $table->define_headers($tableheaders);
341 $table->define_baseurl($baseurl->out());
343 if (!isset($hiddenfields['lastaccess'])) {
344 $table->sortable(true, 'lastaccess', SORT_DESC);
347 $table->no_sorting('roles');
348 $table->no_sorting('groups');
349 $table->no_sorting('groupings');
350 $table->no_sorting('select');
352 $table->set_attribute('cellspacing', '0');
353 $table->set_attribute('id', 'participants');
354 $table->set_attribute('class', 'generaltable generalbox');
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'
364 $table->setup();
366 // we are looking for all users with this role assigned in this context or higher
367 $contextlist = get_related_contexts_string($context);
369 list($esql, $params) = get_enrolled_sql($context, NULL, $currentgroup);
370 $joins = array("FROM {user} u");
371 $wheres = array();
373 if ($isfrontpage) {
374 $select = "SELECT u.id, u.username, u.firstname, u.lastname,
375 u.email, u.city, u.country, u.picture,
376 u.lang, u.timezone, u.emailstop, u.maildisplay, u.imagealt,
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);
383 } else {
384 $select = "SELECT u.id, u.username, u.firstname, u.lastname,
385 u.email, u.city, u.country, u.picture,
386 u.lang, u.timezone, u.emailstop, u.maildisplay, u.imagealt,
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);
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;
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;
408 $from = implode("\n", $joins);
409 if ($wheres) {
410 $where = "WHERE " . implode(" AND ", $wheres);
411 } else {
412 $where = "";
415 $totalcount = $DB->count_records_sql("SELECT COUNT(u.id) $from $where", $params);
417 if (!empty($search)) {
418 $fullname = $DB->sql_fullname('u.firstname','u.lastname');
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) .") ";
422 $params['search1'] = "%$search%";
423 $params['search2'] = "%$search%";
424 $params['search3'] = "%$search%";
427 list($twhere, $tparams) = $table->get_sql_where();
428 if ($twhere) {
429 $wheres[] = $twhere;
430 $params = array_merge($params, $tparams);
433 $from = implode("\n", $joins);
434 if ($wheres) {
435 $where = "WHERE " . implode(" AND ", $wheres);
436 } else {
437 $where = "";
440 if ($table->get_sql_sort()) {
441 $sort = ' ORDER BY '.$table->get_sql_sort();
442 } else {
443 $sort = '';
446 $matchcount = $DB->count_records_sql("SELECT COUNT(u.id) $from $where", $params);
448 $table->initialbars(true);
449 $table->pagesize($perpage, $matchcount);
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());
454 /// If there are multiple Roles in the course, then show a drop down menu for switching
455 if (count($rolenames) > 1) {
456 echo '<div class="rolesform">';
457 echo '<label for="rolesform_jump">'.get_string('currentrole', 'role').'&nbsp;</label>';
458 echo $OUTPUT->single_select($rolenamesurl, 'roleid', $rolenames, $roleid, null, 'rolesform');
459 echo '</div>';
461 } else if (count($rolenames) == 1) {
462 // when all users with the same role - print its name
463 echo '<div class="rolesform">';
464 echo get_string('role').get_string('labelsep', 'langconfig');
465 $rolename = reset($rolenames);
466 echo $rolename;
467 echo '</div>';
470 if ($roleid > 0) {
471 $a->number = $totalcount;
472 $a->role = $rolenames[$roleid];
473 $heading = format_string(get_string('xuserswiththerole', 'role', $a));
475 if ($currentgroup and $group) {
476 $a->group = $group->name;
477 $heading .= ' ' . format_string(get_string('ingroup', 'role', $a));
480 if ($accesssince) {
481 $a->timeperiod = $timeoptions[$accesssince];
482 $heading .= ' ' . format_string(get_string('inactiveformorethan', 'role', $a));
485 $heading .= ": $a->number";
486 if (user_can_assign($context, $roleid)) {
487 $heading .= ' <a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?roleid='.$roleid.'&amp;contextid='.$context->id.'">';
488 $heading .= '<img src="'.$OUTPUT->pix_url('i/edit') . '" class="icon" alt="" /></a>';
490 echo $OUTPUT->heading($heading, 3);
491 } else {
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')));
495 } else {
496 $editlink = '';
498 if ($course->id == SITEID and $roleid < 0) {
499 $strallparticipants = get_string('allsiteusers', 'role');
500 } else {
501 $strallparticipants = get_string('allparticipants');
503 if ($matchcount < $totalcount) {
504 echo $OUTPUT->heading($strallparticipants.get_string('labelsep', 'langconfig').$matchcount.'/'.$totalcount . $editlink, 3);
505 } else {
506 echo $OUTPUT->heading($strallparticipants.get_string('labelsep', 'langconfig').$matchcount . $editlink, 3);
511 if ($bulkoperations) {
512 echo '<form action="action_redir.php" method="post" id="participantsform">';
513 echo '<div>';
514 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
515 echo '<input type="hidden" name="returnto" value="'.s(me()).'" />';
518 if ($mode === MODE_USERDETAILS) { // Print simple listing
519 if ($totalcount < 1) {
520 echo $OUTPUT->heading(get_string('nothingtodisplay'));
521 } else {
522 if ($totalcount > $perpage) {
524 $firstinitial = $table->get_initial_first();
525 $lastinitial = $table->get_initial_last();
526 $strall = get_string('all');
527 $alpha = explode(',', get_string('alphabet', 'langconfig'));
529 // Bar of first initials
531 echo '<div class="initialbar firstinitial">'.get_string('firstname').' : ';
532 if(!empty($firstinitial)) {
533 echo '<a href="'.$baseurl->out().'&amp;sifirst=">'.$strall.'</a>';
534 } else {
535 echo '<strong>'.$strall.'</strong>';
537 foreach ($alpha as $letter) {
538 if ($letter == $firstinitial) {
539 echo ' <strong>'.$letter.'</strong>';
540 } else {
541 echo ' <a href="'.$baseurl->out().'&amp;sifirst='.$letter.'">'.$letter.'</a>';
544 echo '</div>';
546 // Bar of last initials
548 echo '<div class="initialbar lastinitial">'.get_string('lastname').' : ';
549 if(!empty($lastinitial)) {
550 echo '<a href="'.$baseurl->out().'&amp;silast=">'.$strall.'</a>';
551 } else {
552 echo '<strong>'.$strall.'</strong>';
554 foreach ($alpha as $letter) {
555 if ($letter == $lastinitial) {
556 echo ' <strong>'.$letter.'</strong>';
557 } else {
558 echo ' <a href="'.$baseurl->out().'&amp;silast='.$letter.'">'.$letter.'</a>';
561 echo '</div>';
563 $pagingbar = new paging_bar($matchcount, intval($table->get_page_start() / $perpage), $perpage, $baseurl);
564 $pagingbar->pagevar = 'spage';
565 echo $OUTPUT->render($pagingbar);
568 if ($matchcount > 0) {
569 $usersprinted = array();
570 foreach ($userlist as $user) {
571 if (in_array($user->id, $usersprinted)) { /// Prevent duplicates by r.hidden - MDL-13935
572 continue;
574 $usersprinted[] = $user->id; /// Add new user to the array of users printed
576 context_instance_preload($user);
578 $context = get_context_instance(CONTEXT_COURSE, $course->id);
579 $usercontext = get_context_instance(CONTEXT_USER, $user->id);
581 $countries = get_string_manager()->get_list_of_countries();
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));
589 $table = new html_table();
590 $table->attributes['class'] = 'userinfobox';
592 $row = new html_table_row();
593 $row->cells[0] = new html_table_cell();
594 $row->cells[0]->attributes['class'] = 'left side';
596 $row->cells[0]->text = $OUTPUT->user_picture($user, array('courseid'=>$course->id));
597 $row->cells[1] = new html_table_cell();
598 $row->cells[1]->attributes['class'] = 'content';
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');
603 if (!empty($user->role)) {
604 $row->cells[1]->text .= get_string('role').get_string('labelsep', 'langconfig').$user->role.'<br />';
606 if ($user->maildisplay == 1 or ($user->maildisplay == 2 and ($course->id != SITEID) and !isguestuser()) or
607 has_capability('moodle/course:viewhiddenuserfields', $context)) {
608 $row->cells[1]->text .= get_string('email').get_string('labelsep', 'langconfig').html_writer::link("mailto:$user->email", $user->email) . '<br />';
610 if (($user->city or $user->country) and (!isset($hiddenfields['city']) or !isset($hiddenfields['country']))) {
611 $row->cells[1]->text .= get_string('city').get_string('labelsep', 'langconfig');
612 if ($user->city && !isset($hiddenfields['city'])) {
613 $row->cells[1]->text .= $user->city;
615 if (!empty($countries[$user->country]) && !isset($hiddenfields['country'])) {
616 if ($user->city && !isset($hiddenfields['city'])) {
617 $row->cells[1]->text .= ', ';
619 $row->cells[1]->text .= $countries[$user->country];
621 $row->cells[1]->text .= '<br />';
624 if (!isset($hiddenfields['lastaccess'])) {
625 if ($user->lastaccess) {
626 $row->cells[1]->text .= get_string('lastaccess').get_string('labelsep', 'langconfig').userdate($user->lastaccess);
627 $row->cells[1]->text .= '&nbsp; ('. format_time(time() - $user->lastaccess, $datestring) .')';
628 } else {
629 $row->cells[1]->text .= get_string('lastaccess').get_string('labelsep', 'langconfig').get_string('never');
633 $row->cells[1]->text .= $OUTPUT->container_end();
635 $row->cells[2] = new html_table_cell();
636 $row->cells[2]->attributes['class'] = 'links';
637 $row->cells[2]->text = '';
639 $links = array();
641 if ($CFG->bloglevel > 0) {
642 $links[] = html_writer::link(new moodle_url('/blog/index.php?userid='.$user->id), get_string('blogs','blog'));
645 if (!empty($CFG->enablenotes) and (has_capability('moodle/notes:manage', $context) || has_capability('moodle/notes:view', $context))) {
646 $links[] = html_writer::link(new moodle_url('/notes/index.php?course=' . $course->id. '&user='.$user->id), get_string('notes','notes'));
649 if (has_capability('moodle/site:viewreports', $context) or has_capability('moodle/user:viewuseractivitiesreport', $usercontext)) {
650 $links[] = html_writer::link(new moodle_url('/course/user.php?id='. $course->id .'&user='. $user->id), get_string('activity'));
653 if ($USER->id != $user->id && !session_is_loggedinas() && has_capability('moodle/user:loginas', $context) && !is_siteadmin($user->id)) {
654 $links[] = html_writer::link(new moodle_url('/course/loginas.php?id='. $course->id .'&user='. $user->id .'&sesskey='. sesskey()), get_string('loginas'));
657 $links[] = html_writer::link(new moodle_url('/user/view.php?id='. $user->id .'&course='. $course->id), get_string('fullprofile') . '...');
659 $row->cells[2]->text .= implode('', $links);
661 if (!empty($messageselect)) {
662 $row->cells[2]->text .= '<br /><input type="checkbox" name="user'.$user->id.'" /> ';
664 $table->data = array($row);
665 echo html_writer::table($table);
668 } else {
669 echo $OUTPUT->heading(get_string('nothingtodisplay'));
673 } else {
674 $countrysort = (strpos($sort, 'country') !== false);
675 $timeformat = get_string('strftimedate');
678 if ($userlist) {
680 $usersprinted = array();
681 foreach ($userlist as $user) {
682 if (in_array($user->id, $usersprinted)) { /// Prevent duplicates by r.hidden - MDL-13935
683 continue;
685 $usersprinted[] = $user->id; /// Add new user to the array of users printed
687 context_instance_preload($user);
689 if ($user->lastaccess) {
690 $lastaccess = format_time(time() - $user->lastaccess, $datestring);
691 } else {
692 $lastaccess = $strnever;
695 if (empty($user->country)) {
696 $country = '';
698 } else {
699 if($countrysort) {
700 $country = '('.$user->country.') '.$countries[$user->country];
702 else {
703 $country = $countries[$user->country];
707 $usercontext = get_context_instance(CONTEXT_USER, $user->id);
709 if ($piclink = ($USER->id == $user->id || has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext))) {
710 $profilelink = '<strong><a href="'.$CFG->wwwroot.'/user/view.php?id='.$user->id.'&amp;course='.$course->id.'">'.fullname($user).'</a></strong>';
711 } else {
712 $profilelink = '<strong>'.fullname($user).'</strong>';
715 $data = array ($OUTPUT->user_picture($user, array('courseid'=>$course->id)), $profilelink);
717 if ($mode === MODE_BRIEF && !isset($hiddenfields['city'])) {
718 $data[] = $user->city;
720 if ($mode === MODE_BRIEF && !isset($hiddenfields['country'])) {
721 $data[] = $country;
723 if (!isset($hiddenfields['lastaccess'])) {
724 $data[] = $lastaccess;
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) {
731 $rolename = $allrolenames[$ra['roleid']] ;
732 if ($ra['ctxlevel'] == CONTEXT_COURSECAT) {
733 $rastring .= $rolename. ' @ ' . '<a href="'.$CFG->wwwroot.'/course/category.php?id='.$ra['ctxinstanceid'].'">'.s($ra['ccname']).'</a>';
734 } elseif ($ra['ctxlevel'] == CONTEXT_SYSTEM) {
735 $rastring .= $rolename. ' - ' . get_string('globalrole','role');
736 } else {
737 $rastring .= $rolename;
740 $data[] = $rastring;
741 if ($groupmode != 0) {
742 // htmlescape with s() and implode the array
743 $data[] = implode(', ', array_map('s',$userlist_extra[$user->id]['group']));
744 $data[] = implode(', ', array_map('s', $userlist_extra[$user->id]['gping']));
748 if ($bulkoperations) {
749 $data[] = '<input type="checkbox" class="usercheckbox" name="user'.$user->id.'" />';
751 $table->add_data($data);
756 $table->print_html();
760 if ($bulkoperations) {
761 echo '<br /><div class="buttons">';
762 echo '<input type="button" id="checkall" value="'.get_string('selectall').'" /> ';
763 echo '<input type="button" id="checknone" value="'.get_string('deselectall').'" /> ';
764 $displaylist = array();
765 $displaylist['messageselect.php'] = get_string('messageselectadd');
766 if (!empty($CFG->enablenotes) && has_capability('moodle/notes:manage', $context) && $context->id != $frontpagectx->id) {
767 $displaylist['addnote.php'] = get_string('addnewnote', 'notes');
768 $displaylist['groupaddnote.php'] = get_string('groupaddnewnote', 'notes');
771 echo $OUTPUT->help_icon('withselectedusers');
772 echo html_writer::tag('label', get_string("withselectedusers"), array('for'=>'formactionid'));
773 echo html_writer::select($displaylist, 'formaction', '', array(''=>'choosedots'), array('id'=>'formactionid'));
775 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
776 echo '<noscript style="display:inline">';
777 echo '<input type="submit" value="'.get_string('ok').'" />';
778 echo '</noscript>';
779 echo '</div></div>';
780 echo '</form>';
782 $module = array('name'=>'core_user', 'fullpath'=>'/user/module.js');
783 $PAGE->requires->js_init_call('M.core_user.init_participation', null, false, $module);
786 if (has_capability('moodle/site:viewparticipants', $context) && $totalcount > ($perpage*3)) {
787 echo '<form action="index.php" class="searchform"><div><input type="hidden" name="id" value="'.$course->id.'" />'.get_string('search').':&nbsp;'."\n";
788 echo '<input type="text" name="search" value="'.s($search).'" />&nbsp;<input type="submit" value="'.get_string('search').'" /></div></form>'."\n";
791 $perpageurl = clone($baseurl);
792 $perpageurl->remove_params('perpage');
793 if ($perpage == SHOW_ALL_PAGE_SIZE) {
794 $perpageurl->param('perpage', DEFAULT_PAGE_SIZE);
795 echo $OUTPUT->container(html_writer::link($perpageurl, get_string('showperpage', '', DEFAULT_PAGE_SIZE)), array(), 'showall');
797 } else if ($matchcount > 0 && $perpage < $matchcount) {
798 $perpageurl->param('perpage', SHOW_ALL_PAGE_SIZE);
799 echo $OUTPUT->container(html_writer::link($perpageurl, get_string('showall', '', $matchcount)), array(), 'showall');
802 echo '</div>'; // userlist
804 echo $OUTPUT->footer();
806 if ($userlist) {
807 $userlist->close();
811 function get_course_lastaccess_sql($accesssince='') {
812 if (empty($accesssince)) {
813 return '';
815 if ($accesssince == -1) { // never
816 return 'ul.timeaccess = 0';
817 } else {
818 return 'ul.timeaccess != 0 AND ul.timeaccess < '.$accesssince;
822 function get_user_lastaccess_sql($accesssince='') {
823 if (empty($accesssince)) {
824 return '';
826 if ($accesssince == -1) { // never
827 return 'u.lastaccess = 0';
828 } else {
829 return 'u.lastaccess != 0 AND u.lastaccess < '.$accesssince;
833 function get_participants_extra ($userids, $course, $context) {
834 global $CFG, $DB;
836 if (count($userids) === 0) {
837 return array();
840 $params = array();
842 $userids = implode(',', $userids);
844 // turn the path into a list of context ids
845 $contextids = substr($context->path, 1); // kill leading slash
846 $contextids = str_replace('/', ',', $contextids);;
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 ';
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
857 $sql = "SELECT DISTINCT ra.userid,
858 ctx.id AS ctxid, ctx.path AS ctxpath, ctx.depth AS ctxdepth,
859 ctx.contextlevel AS ctxlevel, ctx.instanceid AS ctxinstanceid,
860 cc.name AS ccname,
861 ra.roleid AS roleid,
862 g.id AS gid, g.name AS gname
863 $gpselect
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)
870 /* only if groups active */
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})
875 /* and if groupings is enabled... */
876 $gpjoin
878 WHERE ra.userid IN ( $userids )
879 AND ra.contextid in ( $contextids )
881 ORDER BY ra.userid, ctx.depth DESC";
883 $rs = $DB->get_recordset_sql($sql, $params);
884 $extra = array();
886 // Data structure -
887 // $extra [ $userid ] [ 'group' ] [ $groupid => 'group name']
888 // [ 'gping' ] [ $gpingid => 'gping name']
889 // [ 'ra' ] [ [ "$ctxid:$roleid" => [ctxid => $ctxid
890 // ctxdepth => $ctxdepth,
891 // ctxpath => $ctxpath,
892 // ctxname => 'name' (categories only)
893 // ctxinstid =>
894 // roleid => $roleid
896 foreach ($rs as $rec) {
897 $userid = $rec->userid;
899 // Prime an initial user rec...
900 if (!isset($extra[$userid])) {
901 $extra[$userid] = array( 'group' => array(),
902 'gping' => array(),
903 'ra' => array() );
906 if (!empty($rec->gid)) {
907 $extra[$userid]['group'][$rec->gid]= $rec->gname;
909 if (!empty($rec->gpid)) {
910 $extra[$userid]['gping'][$rec->gpid]= $rec->gpname;
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,
918 'roleid' => $rec->roleid);
922 $rs->close();
923 return $extra;