MDL-59365 enrol: Make select users first
[moodle.git] / user / index.php
CommitLineData
aa6c1ced 1<?php
a2ed6e69
SH
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Lists all the users within a given course.
19 *
20 * @copyright 1999 Martin Dougiamas http://dougiamas.com
21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 * @package core_user
23 */
24
25require_once('../config.php');
0ff203b6 26require_once($CFG->dirroot.'/user/lib.php');
a2ed6e69
SH
27require_once($CFG->libdir.'/tablelib.php');
28require_once($CFG->libdir.'/filelib.php');
29
a2ed6e69
SH
30define('DEFAULT_PAGE_SIZE', 20);
31define('SHOW_ALL_PAGE_SIZE', 5000);
a2ed6e69
SH
32
33$page = optional_param('page', 0, PARAM_INT); // Which page to show.
34$perpage = optional_param('perpage', DEFAULT_PAGE_SIZE, PARAM_INT); // How many per page.
a2ed6e69
SH
35$accesssince = optional_param('accesssince', 0, PARAM_INT); // Filter by last access. -1 = never.
36$search = optional_param('search', '', PARAM_RAW); // Make sure it is processed with p() or s() when sending to output!
37$roleid = optional_param('roleid', 0, PARAM_INT); // Optional roleid, 0 means all enrolled users (or all on the frontpage).
38$contextid = optional_param('contextid', 0, PARAM_INT); // One of this or.
39$courseid = optional_param('id', 0, PARAM_INT); // This are required.
5b7c500a 40$selectall = optional_param('selectall', false, PARAM_BOOL); // When rendering checkboxes against users mark them all checked.
a2ed6e69
SH
41
42$PAGE->set_url('/user/index.php', array(
43 'page' => $page,
44 'perpage' => $perpage,
a2ed6e69
SH
45 'accesssince' => $accesssince,
46 'search' => $search,
47 'roleid' => $roleid,
48 'contextid' => $contextid,
49 'id' => $courseid));
50
51if ($contextid) {
52 $context = context::instance_by_id($contextid, MUST_EXIST);
53 if ($context->contextlevel != CONTEXT_COURSE) {
54 print_error('invalidcontext');
55 }
56 $course = $DB->get_record('course', array('id' => $context->instanceid), '*', MUST_EXIST);
57} else {
58 $course = $DB->get_record('course', array('id' => $courseid), '*', MUST_EXIST);
59 $context = context_course::instance($course->id, MUST_EXIST);
60}
61// Not needed anymore.
62unset($contextid);
63unset($courseid);
f9903ed0 64
a2ed6e69 65require_login($course);
f9903ed0 66
a2ed6e69
SH
67$systemcontext = context_system::instance();
68$isfrontpage = ($course->id == SITEID);
f9903ed0 69
a2ed6e69 70$frontpagectx = context_course::instance(SITEID);
4f0c2d00 71
a2ed6e69
SH
72if ($isfrontpage) {
73 $PAGE->set_pagelayout('admin');
74 require_capability('moodle/site:viewparticipants', $systemcontext);
75} else {
76 $PAGE->set_pagelayout('incourse');
77 require_capability('moodle/course:viewparticipants', $context);
78}
224aa44a 79
a2ed6e69 80$rolenamesurl = new moodle_url("$CFG->wwwroot/user/index.php?contextid=$context->id&sifirst=&silast=");
6d3c57f4 81
a2ed6e69
SH
82$rolenames = role_fix_names(get_profile_roles($context), $context, ROLENAME_ALIAS, true);
83if ($isfrontpage) {
84 $rolenames[0] = get_string('allsiteusers', 'role');
85} else {
86 $rolenames[0] = get_string('allparticipants');
87}
d7270311 88
a2ed6e69
SH
89// Make sure other roles may not be selected by any means.
90if (empty($rolenames[$roleid])) {
91 print_error('noparticipants');
92}
5f9e296a 93
a2ed6e69
SH
94// No roles to display yet?
95// frontpage course is an exception, on the front page course we should display all users.
96if (empty($rolenames) && !$isfrontpage) {
97 if (has_capability('moodle/role:assign', $context)) {
98 redirect($CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.$context->id);
99 } else {
4f0c2d00 100 print_error('noparticipants');
5f9e296a 101 }
a2ed6e69 102}
5f9e296a 103
0ff203b6
JL
104// Trigger events.
105user_list_view($course, $context);
a2ed6e69
SH
106
107$bulkoperations = has_capability('moodle/course:bulkmessaging', $context);
108
109$countries = get_string_manager()->get_list_of_countries();
110
a2ed6e69
SH
111// Check to see if groups are being used in this course
112// and if so, set $currentgroup to reflect the current group.
ff3caf30 113
a2ed6e69
SH
114$groupmode = groups_get_course_groupmode($course); // Groups are being used.
115$currentgroup = groups_get_course_group($course, true);
ff3caf30 116
a2ed6e69
SH
117if (!$currentgroup) { // To make some other functions work better later.
118 $currentgroup = null;
119}
ff3caf30 120
a2ed6e69 121$isseparategroups = ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context));
ff3caf30 122
a2ed6e69
SH
123$PAGE->set_title("$course->shortname: ".get_string('participants'));
124$PAGE->set_heading($course->fullname);
125$PAGE->set_pagetype('course-view-' . $course->format);
126$PAGE->add_body_class('path-user'); // So we can style it independently.
127$PAGE->set_other_editing_capability('moodle/course:manageactivities');
2cb2ce61 128
a2ed6e69 129echo $OUTPUT->header();
4e1f6047 130echo $OUTPUT->heading(get_string('participants'));
caa8363f 131
a2ed6e69 132echo '<div class="userlist">';
0be6f678 133
a2ed6e69
SH
134if ($isseparategroups and (!$currentgroup) ) {
135 // The user is not in the group so show message and exit.
136 echo $OUTPUT->heading(get_string("notingroup"));
137 echo $OUTPUT->footer();
138 exit;
139}
99cca847 140
a2ed6e69
SH
141// Should use this variable so that we don't break stuff every time a variable is added or changed.
142$baseurl = new moodle_url('/user/index.php', array(
143 'contextid' => $context->id,
144 'roleid' => $roleid,
145 'id' => $course->id,
146 'perpage' => $perpage,
147 'accesssince' => $accesssince,
148 'search' => s($search)));
149
150// Setting up tags.
151if ($course->id == SITEID) {
152 $filtertype = 'site';
153} else if ($course->id && !$currentgroup) {
154 $filtertype = 'course';
155 $filterselect = $course->id;
156} else {
157 $filtertype = 'group';
158 $filterselect = $currentgroup;
159}
03d9401e 160
a2ed6e69
SH
161// Print settings and things in a table across the top.
162$controlstable = new html_table();
163$controlstable->attributes['class'] = 'controls';
164$controlstable->cellspacing = 0;
165$controlstable->data[] = new html_table_row();
166
24c3db91
DP
167if ($groupmenu = groups_print_course_menu($course, $baseurl->out(), true)) {
168 $controlstable->data[0]->cells[] = $groupmenu;
169}
a2ed6e69 170
bc47b706
MN
171// Get the list of fields we have to hide.
172$hiddenfields = array();
173if (!has_capability('moodle/course:viewhiddenuserfields', $context)) {
174 $hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
175}
176
177// If lastaccess is in the hidden fields access do not allow filtering.
178if (isset($hiddenfields['lastaccess'])) {
179 $accesssince = 0;
180} else { // The user is allowed to filter by last access.
a2ed6e69
SH
181 // Get minimum lastaccess for this course and display a dropbox to filter by lastaccess going back this far.
182 // We need to make it diferently for normal courses and site course.
183 if (!$isfrontpage) {
184 $minlastaccess = $DB->get_field_sql('SELECT min(timeaccess)
185 FROM {user_lastaccess}
186 WHERE courseid = ?
187 AND timeaccess != 0', array($course->id));
188 $lastaccess0exists = $DB->record_exists('user_lastaccess', array('courseid' => $course->id, 'timeaccess' => 0));
189 } else {
190 $minlastaccess = $DB->get_field_sql('SELECT min(lastaccess)
191 FROM {user}
192 WHERE lastaccess != 0');
193 $lastaccess0exists = $DB->record_exists('user', array('lastaccess' => 0));
7da0af9f 194 }
87a13824 195
a2ed6e69
SH
196 $now = usergetmidnight(time());
197 $timeaccess = array();
198 $baseurl->remove_params('accesssince');
87a13824 199
a2ed6e69
SH
200 // Makes sense for this to go first.
201 $timeoptions[0] = get_string('selectperiod');
87a13824 202
a2ed6e69
SH
203 // Days.
204 for ($i = 1; $i < 7; $i++) {
205 if (strtotime('-'.$i.' days', $now) >= $minlastaccess) {
206 $timeoptions[strtotime('-'.$i.' days', $now)] = get_string('numdays', 'moodle', $i);
ca792680 207 }
a2ed6e69
SH
208 }
209 // Weeks.
210 for ($i = 1; $i < 10; $i++) {
211 if (strtotime('-'.$i.' weeks', $now) >= $minlastaccess) {
212 $timeoptions[strtotime('-'.$i.' weeks', $now)] = get_string('numweeks', 'moodle', $i);
5ff311f0 213 }
a2ed6e69
SH
214 }
215 // Months.
216 for ($i = 2; $i < 12; $i++) {
217 if (strtotime('-'.$i.' months', $now) >= $minlastaccess) {
218 $timeoptions[strtotime('-'.$i.' months', $now)] = get_string('nummonths', 'moodle', $i);
31b71336 219 }
a2ed6e69
SH
220 }
221 // Try a year.
222 if (strtotime('-1 year', $now) >= $minlastaccess) {
223 $timeoptions[strtotime('-1 year', $now)] = get_string('lastyear');
224 }
87a13824 225
a2ed6e69
SH
226 if (!empty($lastaccess0exists)) {
227 $timeoptions[-1] = get_string('never');
228 }
87a13824 229
a2ed6e69
SH
230 if (count($timeoptions) > 1) {
231 $select = new single_select($baseurl, 'accesssince', $timeoptions, $accesssince, null, 'timeoptions');
232 $select->set_label(get_string('usersnoaccesssince'));
233 $controlstable->data[0]->cells[] = $OUTPUT->render($select);
77c645df 234 }
a2ed6e69 235}
87a13824 236
a2ed6e69
SH
237echo html_writer::table($controlstable);
238
bc47b706
MN
239$participanttable = new \core_user\participants_table($course->id, $currentgroup, $accesssince, $roleid, $search,
240 $bulkoperations, $selectall);
241$participanttable->define_baseurl($baseurl);
77c645df 242
bc47b706
MN
243// Do this so we can get the total number of rows.
244ob_start();
245$participanttable->out($perpage, true);
246$participanttablehtml = ob_get_contents();
247ob_end_clean();
3e219038 248
a2ed6e69
SH
249// If there are multiple Roles in the course, then show a drop down menu for switching.
250if (count($rolenames) > 1) {
251 echo '<div class="rolesform">';
32bd11cb
BB
252 echo $OUTPUT->single_select($rolenamesurl, 'roleid', $rolenames, $roleid, null,
253 'rolesform', array('label' => get_string('currentrole', 'role')));
a2ed6e69 254 echo '</div>';
5f9e296a 255
a2ed6e69
SH
256} else if (count($rolenames) == 1) {
257 // When all users with the same role - print its name.
258 echo '<div class="rolesform">';
259 echo get_string('role').get_string('labelsep', 'langconfig');
260 $rolename = reset($rolenames);
261 echo $rolename;
262 echo '</div>';
263}
3e219038 264
a2ed6e69
SH
265if ($roleid > 0) {
266 $a = new stdClass();
bc47b706 267 $a->number = $participanttable->totalrows;
a2ed6e69
SH
268 $a->role = $rolenames[$roleid];
269 $heading = format_string(get_string('xuserswiththerole', 'role', $a));
f642a21a 270
e727e91c
MN
271 if ($currentgroup) {
272 if ($group = groups_get_group($currentgroup)) {
273 $a->group = $group->name;
274 $heading .= ' ' . format_string(get_string('ingroup', 'role', $a));
275 }
a2ed6e69 276 }
f642a21a 277
9488b6f3 278 if ($accesssince && !empty($timeoptions[$accesssince])) {
a2ed6e69
SH
279 $a->timeperiod = $timeoptions[$accesssince];
280 $heading .= ' ' . format_string(get_string('inactiveformorethan', 'role', $a));
281 }
f642a21a 282
a2ed6e69 283 $heading .= ": $a->number";
b85b25eb 284
a2ed6e69
SH
285 echo $OUTPUT->heading($heading, 3);
286} else {
a2ed6e69
SH
287 if ($course->id == SITEID and $roleid < 0) {
288 $strallparticipants = get_string('allsiteusers', 'role');
289 } else {
290 $strallparticipants = get_string('allparticipants');
291 }
7057c3ef 292
bc47b706 293 echo $OUTPUT->heading($strallparticipants.get_string('labelsep', 'langconfig') . $participanttable->totalrows, 3);
a2ed6e69 294}
3e219038 295
a2ed6e69
SH
296if ($bulkoperations) {
297 echo '<form action="action_redir.php" method="post" id="participantsform">';
298 echo '<div>';
299 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
300 echo '<input type="hidden" name="returnto" value="'.s($PAGE->url->out(false)).'" />';
301}
77c645df 302
bc47b706 303echo $participanttablehtml;
4c7593ff 304
8dd42b38
AH
305$perpageurl = clone($baseurl);
306$perpageurl->remove_params('perpage');
bc47b706 307if ($perpage == SHOW_ALL_PAGE_SIZE && $participanttable->totalrows > DEFAULT_PAGE_SIZE) {
8dd42b38
AH
308 $perpageurl->param('perpage', DEFAULT_PAGE_SIZE);
309 echo $OUTPUT->container(html_writer::link($perpageurl, get_string('showperpage', '', DEFAULT_PAGE_SIZE)), array(), 'showall');
310
bc47b706 311} else if ($participanttable->get_page_size() < $participanttable->totalrows) {
8dd42b38 312 $perpageurl->param('perpage', SHOW_ALL_PAGE_SIZE);
bc47b706
MN
313 echo $OUTPUT->container(html_writer::link($perpageurl, get_string('showall', '', $participanttable->totalrows)),
314 array(), 'showall');
8dd42b38
AH
315}
316
a2ed6e69
SH
317if ($bulkoperations) {
318 echo '<br /><div class="buttons">';
5b7c500a 319
bc47b706 320 if ($participanttable->get_page_size() < $participanttable->totalrows) {
5b7c500a
AH
321 $perpageurl = clone($baseurl);
322 $perpageurl->remove_params('perpage');
323 $perpageurl->param('perpage', SHOW_ALL_PAGE_SIZE);
324 $perpageurl->param('selectall', true);
325 $showalllink = $perpageurl;
326 } else {
327 $showalllink = false;
328 }
329
b27c8d81 330 echo html_writer::start_tag('div', array('class' => 'btn-group'));
bc47b706 331 if ($participanttable->get_page_size() < $participanttable->totalrows) {
5b7c500a 332 // Select all users, refresh page showing all users and mark them all selected.
bc47b706 333 $label = get_string('selectalluserswithcount', 'moodle', $participanttable->totalrows);
b27c8d81
SB
334 echo html_writer::tag('input', "", array('type' => 'button', 'id' => 'checkall', 'class' => 'btn btn-secondary',
335 'value' => $label, 'data-showallink' => $showalllink));
5b7c500a 336 // Select all users, mark all users on page as selected.
b27c8d81
SB
337 echo html_writer::tag('input', "", array('type' => 'button', 'id' => 'checkallonpage', 'class' => 'btn btn-secondary',
338 'value' => get_string('selectallusersonpage')));
5b7c500a 339 } else {
b27c8d81
SB
340 echo html_writer::tag('input', "", array('type' => 'button', 'id' => 'checkallonpage', 'class' => 'btn btn-secondary',
341 'value' => get_string('selectall')));
5b7c500a
AH
342 }
343
b27c8d81
SB
344 echo html_writer::tag('input', "", array('type' => 'button', 'id' => 'checknone', 'class' => 'btn btn-secondary',
345 'value' => get_string('deselectall')));
346 echo html_writer::end_tag('div');
a2ed6e69
SH
347 $displaylist = array();
348 $displaylist['messageselect.php'] = get_string('messageselectadd');
349 if (!empty($CFG->enablenotes) && has_capability('moodle/notes:manage', $context) && $context->id != $frontpagectx->id) {
350 $displaylist['addnote.php'] = get_string('addnewnote', 'notes');
351 $displaylist['groupaddnote.php'] = get_string('groupaddnewnote', 'notes');
352 }
353
354 echo $OUTPUT->help_icon('withselectedusers');
355 echo html_writer::tag('label', get_string("withselectedusers"), array('for' => 'formactionid'));
356 echo html_writer::select($displaylist, 'formaction', '', array('' => 'choosedots'), array('id' => 'formactionid'));
357
358 echo '<input type="hidden" name="id" value="'.$course->id.'" />';
359 echo '<noscript style="display:inline">';
360 echo '<div><input type="submit" value="'.get_string('ok').'" /></div>';
361 echo '</noscript>';
362 echo '</div></div>';
363 echo '</form>';
364
365 $module = array('name' => 'core_user', 'fullpath' => '/user/module.js');
366 $PAGE->requires->js_init_call('M.core_user.init_participation', null, false, $module);
367}
b90e2f19 368
a2ed6e69 369// Show a search box if all participants don't fit on a single screen.
bc47b706 370if ($participanttable->get_page_size() < $participanttable->totalrows) {
a2ed6e69
SH
371 echo '<form action="index.php" class="searchform"><div><input type="hidden" name="id" value="'.$course->id.'" />';
372 echo '<label for="search">' . get_string('search', 'search') . ' </label>';
373 echo '<input type="text" id="search" name="search" value="'.s($search).'" />&nbsp;<input type="submit" value="'.get_string('search').'" /></div></form>'."\n";
374}
77c645df 375
a2ed6e69 376echo '</div>'; // Userlist.
f9903ed0 377
a2ed6e69 378echo $OUTPUT->footer();