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(
27 'perpage' => $perpage,
29 'accesssince' => $accesssince,
32 'contextid' => $contextid,
33 'courseid' => $courseid));
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
);
42 $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST
);
43 $context = get_context_instance(CONTEXT_COURSE
, $course->id
, MUST_EXIST
);
49 require_login($course);
51 $systemcontext = get_context_instance(CONTEXT_SYSTEM
);
52 $isfrontpage = ($course->id
== SITEID
);
54 $frontpagectx = get_context_instance(CONTEXT_COURSE
, SITEID
);
57 $PAGE->set_pagelayout('admin');
58 require_capability('moodle/site:viewparticipants', $systemcontext);
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();
70 $rolenames = array(0=>get_string('allsiteusers', 'role'));
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
);
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) {
118 $SESSION->userindexmode
= $mode;
119 } else if (isset($SESSION->userindexmode
)) {
120 $mode = (int)$SESSION->userindexmode
;
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();
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
,
165 'perpage' => $perpage,
166 'accesssince' => $accesssince,
167 'search' => s($search)));
170 if ($course->id
== SITEID
) {
171 $filtertype = 'site';
172 } else if ($course->id
&& !$currentgroup) {
173 $filtertype = 'course';
174 $filterselect = $course->id
;
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
186 $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields
));
189 if (isset($hiddenfields['lastaccess'])) {
190 // do not allow access since filtering
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
222 $minlastaccess = $DB->get_field_sql('SELECT min(timeaccess)
223 FROM {user_lastaccess}
225 AND timeaccess != 0', array($course->id
));
226 $lastaccess0exists = $DB->record_exists('user_lastaccess', array('courseid'=>$course->id
, 'timeaccess'=>0));
228 $minlastaccess = $DB->get_field_sql('SELECT min(lastaccess)
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');
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);
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);
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);
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 .= ' ' . $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'
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");
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,
378 $joins[] = "JOIN ($esql) e ON e.id = u.id"; // everybody on the frontpage usually
380 $wheres[] = get_user_lastaccess_sql($accesssince);
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
;
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;
402 // limit list to users with some role only
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);
410 $where = "WHERE " . implode(" AND ", $wheres);
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();
430 $params = array_merge($params, $tparams);
433 $from = implode("\n", $joins);
435 $where = "WHERE " . implode(" AND ", $wheres);
440 if ($table->get_sql_sort()) {
441 $sort = ' ORDER BY '.$table->get_sql_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').' </label>';
458 echo $OUTPUT->single_select($rolenamesurl, 'roleid', $rolenames, $roleid, null, 'rolesform');
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);
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));
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.'&contextid='.$context->id
.'">';
488 $heading .= '<img src="'.$OUTPUT->pix_url('i/edit') . '" class="icon" alt="" /></a>';
490 echo $OUTPUT->heading($heading, 3);
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')));
498 if ($course->id
== SITEID
and $roleid < 0) {
499 $strallparticipants = get_string('allsiteusers', 'role');
501 $strallparticipants = get_string('allparticipants');
503 if ($matchcount < $totalcount) {
504 echo $OUTPUT->heading($strallparticipants.get_string('labelsep', 'langconfig').$matchcount.'/'.$totalcount . $editlink, 3);
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">';
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'));
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().'&sifirst=">'.$strall.'</a>';
535 echo '<strong>'.$strall.'</strong>';
537 foreach ($alpha as $letter) {
538 if ($letter == $firstinitial) {
539 echo ' <strong>'.$letter.'</strong>';
541 echo ' <a href="'.$baseurl->out().'&sifirst='.$letter.'">'.$letter.'</a>';
546 // Bar of last initials
548 echo '<div class="initialbar lastinitial">'.get_string('lastname').' : ';
549 if(!empty($lastinitial)) {
550 echo '<a href="'.$baseurl->out().'&silast=">'.$strall.'</a>';
552 echo '<strong>'.$strall.'</strong>';
554 foreach ($alpha as $letter) {
555 if ($letter == $lastinitial) {
556 echo ' <strong>'.$letter.'</strong>';
558 echo ' <a href="'.$baseurl->out().'&silast='.$letter.'">'.$letter.'</a>';
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
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();
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
.= ' ('. format_time(time() - $user->lastaccess
, $datestring) .')';
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
= '';
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);
669 echo $OUTPUT->heading(get_string('nothingtodisplay'));
674 $countrysort = (strpos($sort, 'country') !== false);
675 $timeformat = get_string('strftimedate');
680 $usersprinted = array();
681 foreach ($userlist as $user) {
682 if (in_array($user->id
, $usersprinted)) { /// Prevent duplicates by r.hidden - MDL-13935
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);
692 $lastaccess = $strnever;
695 if (empty($user->country
)) {
700 $country = '('.$user->country
.') '.$countries[$user->country
];
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
.'&course='.$course->id
.'">'.fullname($user).'</a></strong>';
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'])) {
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'];
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');
737 $rastring .= $rolename;
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').'" />';
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').': '."\n";
788 echo '<input type="text" name="search" value="'.s($search).'" /> <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();
811 function get_course_lastaccess_sql($accesssince='') {
812 if (empty($accesssince)) {
815 if ($accesssince == -1) { // never
816 return 'ul.timeaccess = 0';
818 return 'ul.timeaccess != 0 AND ul.timeaccess < '.$accesssince;
822 function get_user_lastaccess_sql($accesssince='') {
823 if (empty($accesssince)) {
826 if ($accesssince == -1) { // never
827 return 'u.lastaccess = 0';
829 return 'u.lastaccess != 0 AND u.lastaccess < '.$accesssince;
833 function get_participants_extra ($userids, $course, $context) {
836 if (count($userids) === 0) {
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
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,
862 g.id AS gid, g.name AS gname
864 FROM {role_assignments} ra
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)
874 ON (gm.groupid=g.id AND g.courseid={$course->id})
875 /* and if groupings is enabled... */
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);
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)
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(),
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
);