MDL-59395 core_user: move participants table to own class

Removed the edit link variable which was used in the heading
'Users with the role ..' but was never displayed due to filters.

Other minor tidy ups as well.

Part of MDL-59290.
This commit is contained in:
Mark Nelson 2017-06-28 11:44:20 +08:00
parent a50089bac5
commit bc47b70667
3 changed files with 479 additions and 320 deletions

View file

@ -0,0 +1,276 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contains the class used for the displaying the participants table.
*
* @package core_user
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_user;
defined('MOODLE_INTERNAL') || die;
global $CFG;
require_once($CFG->libdir . '/tablelib.php');
require_once($CFG->dirroot . '/user/lib.php');
/**
* Class for the displaying the participants table.
*
* @package core_user
* @copyright 2017 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class participants_table extends \table_sql {
/**
* @var int $courseid The course id
*/
protected $courseid;
/**
* @var int|false False if groups not used, int if groups used, 0 for all groups.
*/
protected $currentgroup;
/**
* @var int $accesssince The time the user last accessed the site
*/
protected $accesssince;
/**
* @var int $roleid The role we are including, 0 means all enrolled users
*/
protected $roleid;
/**
* @var string $search The string being searched.
*/
protected $search;
/**
* @var bool $selectall Has the user selected all users on the page?
*/
protected $selectall;
/**
* @var string[] The list of countries.
*/
protected $countries;
/**
* @var string[] Extra fields to display.
*/
protected $extrafields;
/**
* Sets up the table.
*
* @param int $courseid
* @param int|false $currentgroup False if groups not used, int if groups used, 0 for all groups.
* @param int $accesssince The time the user last accessed the site
* @param int $roleid The role we are including, 0 means all enrolled users
* @param string $search The string being searched
* @param bool $bulkoperations Is the user allowed to perform bulk operations?
* @param bool $selectall Has the user selected all users on the page?
*/
public function __construct($courseid, $currentgroup, $accesssince, $roleid, $search,
$bulkoperations, $selectall) {
global $CFG;
parent::__construct('user-index-participants-' . $courseid);
// Get the context.
$context = \context_course::instance($courseid, MUST_EXIST);
// Define the headers and columns.
$headers = [];
$columns = [];
if ($bulkoperations) {
$headers[] = get_string('select');
$columns[] = 'select';
}
$headers[] = get_string('fullname');
$columns[] = 'fullname';
$extrafields = get_extra_user_fields($context);
foreach ($extrafields as $field) {
$headers[] = get_user_field_name($field);
$columns[] = $field;
}
// Get the list of fields we have to hide.
$hiddenfields = array();
if (!has_capability('moodle/course:viewhiddenuserfields', $context)) {
$hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
}
// Do not show the columns if it exists in the hiddenfields array.
if (!isset($hiddenfields['city'])) {
$headers[] = get_string('city');
$columns[] = 'city';
}
if (!isset($hiddenfields['country'])) {
$headers[] = get_string('country');
$columns[] = 'country';
}
if (!isset($hiddenfields['lastaccess'])) {
if ($courseid == SITEID) {
$headers[] = get_string('lastsiteaccess');
} else {
$headers[] = get_string('lastcourseaccess');
}
$columns[] = 'lastaccess';
}
$this->define_columns($columns);
$this->define_headers($headers);
$this->no_sorting('select');
$this->set_attribute('id', 'participants');
// Set the variables we need to use later.
$this->courseid = $courseid;
$this->currentgroup = $currentgroup;
$this->accesssince = $accesssince;
$this->roleid = $roleid;
$this->search = $search;
$this->selectall = $selectall;
$this->countries = get_string_manager()->get_list_of_countries();
$this->extrafields = $extrafields;
}
/**
* Generate the select column.
*
* @param \stdClass $data
* @return string
*/
public function col_select($data) {
if ($this->selectall) {
$checked = 'checked="true"';
} else {
$checked = '';
}
return '<input type="checkbox" class="usercheckbox" name="user' . $data->id . '" ' . $checked . '/>';
}
/**
* Generate the fullname column.
*
* @param \stdClass $data
* @return string
*/
public function col_fullname($data) {
global $OUTPUT;
return $OUTPUT->user_picture($data, array('size' => 35, 'courseid' => $this->courseid)) . ' ' . fullname($data);
}
/**
* Generate the city column.
*
* @param \stdClass $data
* @return string
*/
public function col_city($data) {
return $data->city;
}
/**
* Generate the country column.
*
* @param \stdClass $data
* @return string
*/
public function col_country($data) {
if (!empty($this->countries[$data->country])) {
return $this->countries[$data->country];
}
return '';
}
/**
* Generate the last access column.
*
* @param \stdClass $data
* @return string
*/
public function col_lastaccess($data) {
if ($data->lastaccess) {
return format_time(time() - $data->lastaccess);
}
return get_string('never');
}
/**
* This function is used for the extra user fields.
*
* These are being dynamically added to the table so there are no functions 'col_<userfieldname>' as
* the list has the potential to increase in the future and we don't want to have to remember to add
* a new method to this class. We also don't want to pollute this class with unnecessary methods.
*
* @param string $colname The column name
* @param \stdClass $data
* @return string
*/
public function other_cols($colname, $data) {
// Do not process if it is not a part of the extra fields.
if (!in_array($colname, $this->extrafields)) {
return '';
}
return s($data->{$colname});
}
/**
* Query the database for results to display in the table.
*
* @param int $pagesize size of page for paginated displayed table.
* @param bool $useinitialsbar do you want to use the initials bar.
*/
public function query_db($pagesize, $useinitialsbar = true) {
list($twhere, $tparams) = $this->get_sql_where();
$total = user_get_total_participants($this->courseid, $this->currentgroup, $this->accesssince,
$this->roleid, $this->search, $twhere, $tparams);
$this->pagesize($pagesize, $total);
$sort = $this->get_sql_sort();
if ($sort) {
$sort = 'ORDER BY ' . $sort;
}
$this->rawdata = user_get_participants($this->courseid, $this->currentgroup, $this->accesssince,
$this->roleid, $this->search, $twhere, $tparams, $sort, $this->get_page_start(),
$this->get_page_size());
// Set initial bars.
if ($useinitialsbar) {
$this->initialbars(true);
}
}
}

View file

@ -27,8 +27,6 @@ require_once($CFG->dirroot.'/user/lib.php');
require_once($CFG->libdir.'/tablelib.php');
require_once($CFG->libdir.'/filelib.php');
define('USER_SMALL_CLASS', 20); // Below this is considered small.
define('USER_LARGE_CLASS', 200); // Above this is considered large.
define('DEFAULT_PAGE_SIZE', 20);
define('SHOW_ALL_PAGE_SIZE', 5000);
@ -110,20 +108,6 @@ $bulkoperations = has_capability('moodle/course:bulkmessaging', $context);
$countries = get_string_manager()->get_list_of_countries();
$strnever = get_string('never');
$datestring = new stdClass();
$datestring->year = get_string('year');
$datestring->years = get_string('years');
$datestring->day = get_string('day');
$datestring->days = get_string('days');
$datestring->hour = get_string('hour');
$datestring->hours = get_string('hours');
$datestring->min = get_string('min');
$datestring->mins = get_string('mins');
$datestring->sec = get_string('sec');
$datestring->secs = get_string('secs');
// Check to see if groups are being used in this course
// and if so, set $currentgroup to reflect the current group.
@ -154,7 +138,6 @@ if ($isseparategroups and (!$currentgroup) ) {
exit;
}
// Should use this variable so that we don't break stuff every time a variable is added or changed.
$baseurl = new moodle_url('/user/index.php', array(
'contextid' => $context->id,
@ -175,20 +158,6 @@ if ($course->id == SITEID) {
$filterselect = $currentgroup;
}
// Get the hidden field list.
if (has_capability('moodle/course:viewhiddenuserfields', $context)) {
$hiddenfields = array(); // Teachers and admins are allowed to see everything.
} else {
$hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
}
if (isset($hiddenfields['lastaccess'])) {
// Do not allow access since filtering.
$accesssince = 0;
}
// Print settings and things in a table across the top.
$controlstable = new html_table();
$controlstable->attributes['class'] = 'controls';
@ -199,7 +168,16 @@ if ($groupmenu = groups_print_course_menu($course, $baseurl->out(), true)) {
$controlstable->data[0]->cells[] = $groupmenu;
}
if (!isset($hiddenfields['lastaccess'])) {
// Get the list of fields we have to hide.
$hiddenfields = array();
if (!has_capability('moodle/course:viewhiddenuserfields', $context)) {
$hiddenfields = array_flip(explode(',', $CFG->hiddenuserfields));
}
// If lastaccess is in the hidden fields access do not allow filtering.
if (isset($hiddenfields['lastaccess'])) {
$accesssince = 0;
} else { // The user is allowed to filter by last access.
// Get minimum lastaccess for this course and display a dropbox to filter by lastaccess going back this far.
// We need to make it diferently for normal courses and site course.
if (!$isfrontpage) {
@ -258,160 +236,15 @@ if (!isset($hiddenfields['lastaccess'])) {
echo html_writer::table($controlstable);
// Define a table showing a list of users in the current role selection.
$tablecolumns = array();
$tableheaders = array();
if ($bulkoperations) {
$tablecolumns[] = 'select';
$tableheaders[] = get_string('select');
}
$tablecolumns[] = 'userpic';
$tablecolumns[] = 'fullname';
$participanttable = new \core_user\participants_table($course->id, $currentgroup, $accesssince, $roleid, $search,
$bulkoperations, $selectall);
$participanttable->define_baseurl($baseurl);
$extrafields = get_extra_user_fields($context);
$tableheaders[] = get_string('userpic');
$tableheaders[] = get_string('fullnameuser');
foreach ($extrafields as $field) {
$tablecolumns[] = $field;
$tableheaders[] = get_user_field_name($field);
}
if (!isset($hiddenfields['city'])) {
$tablecolumns[] = 'city';
$tableheaders[] = get_string('city');
}
if (!isset($hiddenfields['country'])) {
$tablecolumns[] = 'country';
$tableheaders[] = get_string('country');
}
if (!isset($hiddenfields['lastaccess'])) {
$tablecolumns[] = 'lastaccess';
if ($course->id == SITEID) {
// Exception case for viewing participants on site home.
$tableheaders[] = get_string('lastsiteaccess');
} else {
$tableheaders[] = get_string('lastcourseaccess');
}
}
$table = new flexible_table('user-index-participants-'.$course->id);
$table->define_columns($tablecolumns);
$table->define_headers($tableheaders);
$table->define_baseurl($baseurl->out());
if (!isset($hiddenfields['lastaccess'])) {
$table->sortable(true, 'lastaccess', SORT_DESC);
} else {
$table->sortable(true, 'firstname', SORT_ASC);
}
$table->no_sorting('roles');
$table->no_sorting('groups');
$table->no_sorting('groupings');
$table->no_sorting('select');
$table->set_attribute('cellspacing', '0');
$table->set_attribute('id', 'participants');
$table->set_attribute('class', 'generaltable generalbox');
$table->set_control_variables(array(
TABLE_VAR_SORT => 'ssort',
TABLE_VAR_HIDE => 'shide',
TABLE_VAR_SHOW => 'sshow',
TABLE_VAR_IFIRST => 'sifirst',
TABLE_VAR_ILAST => 'silast',
TABLE_VAR_PAGE => 'spage'
));
$table->setup();
list($esql, $params) = get_enrolled_sql($context, null, $currentgroup, true);
$joins = array("FROM {user} u");
$wheres = array();
$userfields = array('username', 'email', 'city', 'country', 'lang', 'timezone', 'maildisplay');
$mainuserfields = user_picture::fields('u', $userfields);
$extrasql = get_extra_user_fields_sql($context, 'u', '', $userfields);
if ($isfrontpage) {
$select = "SELECT $mainuserfields, u.lastaccess$extrasql";
$joins[] = "JOIN ($esql) e ON e.id = u.id"; // Everybody on the frontpage usually.
if ($accesssince) {
$wheres[] = get_user_lastaccess_sql($accesssince);
}
} else {
$select = "SELECT $mainuserfields, COALESCE(ul.timeaccess, 0) AS lastaccess$extrasql";
$joins[] = "JOIN ($esql) e ON e.id = u.id"; // Course enrolled users only.
$joins[] = "LEFT JOIN {user_lastaccess} ul ON (ul.userid = u.id AND ul.courseid = :courseid)"; // Not everybody accessed course yet.
$params['courseid'] = $course->id;
if ($accesssince) {
$wheres[] = get_course_lastaccess_sql($accesssince);
}
}
// Performance hacks - we preload user contexts together with accounts.
$ccselect = ', ' . context_helper::get_preload_record_columns_sql('ctx');
$ccjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel)";
$params['contextlevel'] = CONTEXT_USER;
$select .= $ccselect;
$joins[] = $ccjoin;
// Limit list to users with some role only.
if ($roleid) {
// We want to query both the current context and parent contexts.
list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx');
$wheres[] = "u.id IN (SELECT userid FROM {role_assignments} WHERE roleid = :roleid AND contextid $relatedctxsql)";
$params = array_merge($params, array('roleid' => $roleid), $relatedctxparams);
}
$from = implode("\n", $joins);
if ($wheres) {
$where = "WHERE " . implode(" AND ", $wheres);
} else {
$where = "";
}
$totalcount = $DB->count_records_sql("SELECT COUNT(u.id) $from $where", $params);
if (!empty($search)) {
$fullname = $DB->sql_fullname('u.firstname', 'u.lastname');
$wheres[] = "(". $DB->sql_like($fullname, ':search1', false, false) .
" OR ". $DB->sql_like('email', ':search2', false, false) .
" OR ". $DB->sql_like('idnumber', ':search3', false, false) .") ";
$params['search1'] = "%$search%";
$params['search2'] = "%$search%";
$params['search3'] = "%$search%";
}
list($twhere, $tparams) = $table->get_sql_where();
if ($twhere) {
$wheres[] = $twhere;
$params = array_merge($params, $tparams);
}
$from = implode("\n", $joins);
if ($wheres) {
$where = "WHERE " . implode(" AND ", $wheres);
} else {
$where = "";
}
if ($table->get_sql_sort()) {
$sort = ' ORDER BY '.$table->get_sql_sort();
} else {
$sort = '';
}
$matchcount = $DB->count_records_sql("SELECT COUNT(u.id) $from $where", $params);
$table->initialbars(true);
$table->pagesize($perpage, $matchcount);
// List of users at the current visible page - paging makes it relatively short.
$userlist = $DB->get_recordset_sql("$select $from $where $sort", $params, $table->get_page_start(), $table->get_page_size());
// Do this so we can get the total number of rows.
ob_start();
$participanttable->out($perpage, true);
$participanttablehtml = ob_get_contents();
ob_end_clean();
// If there are multiple Roles in the course, then show a drop down menu for switching.
if (count($rolenames) > 1) {
@ -429,14 +262,9 @@ if (count($rolenames) > 1) {
echo '</div>';
}
$editlink = '';
if ($course->id != SITEID && has_capability('moodle/course:enrolreview', $context)) {
$editlink = new moodle_url('/enrol/users.php', array('id' => $course->id));
}
if ($roleid > 0) {
$a = new stdClass();
$a->number = $totalcount;
$a->number = $participanttable->totalrows;
$a->role = $rolenames[$roleid];
$heading = format_string(get_string('xuserswiththerole', 'role', $a));
@ -454,10 +282,6 @@ if ($roleid > 0) {
$heading .= ": $a->number";
if (!empty($editlink)) {
$editlink->param('role', $roleid);
$heading .= $OUTPUT->action_icon($editlink, new pix_icon('t/edit', get_string('edit')));
}
echo $OUTPUT->heading($heading, 3);
} else {
if ($course->id == SITEID and $roleid < 0) {
@ -466,18 +290,9 @@ if ($roleid > 0) {
$strallparticipants = get_string('allparticipants');
}
if (!empty($editlink)) {
$editlink = $OUTPUT->action_icon($editlink, new pix_icon('t/edit', get_string('edit')));
}
if ($matchcount < $totalcount) {
echo $OUTPUT->heading($strallparticipants.get_string('labelsep', 'langconfig').$matchcount.'/'.$totalcount . $editlink, 3);
} else {
echo $OUTPUT->heading($strallparticipants.get_string('labelsep', 'langconfig').$matchcount . $editlink, 3);
}
echo $OUTPUT->heading($strallparticipants.get_string('labelsep', 'langconfig') . $participanttable->totalrows, 3);
}
if ($bulkoperations) {
echo '<form action="action_redir.php" method="post" id="participantsform">';
echo '<div>';
@ -485,92 +300,24 @@ if ($bulkoperations) {
echo '<input type="hidden" name="returnto" value="'.s($PAGE->url->out(false)).'" />';
}
$countrysort = (strpos($sort, 'country') !== false);
$timeformat = get_string('strftimedate');
if ($userlist) {
$usersprinted = array();
foreach ($userlist as $user) {
if (in_array($user->id, $usersprinted)) { // Prevent duplicates by r.hidden - MDL-13935.
continue;
}
$usersprinted[] = $user->id; // Add new user to the array of users printed.
context_helper::preload_from_record($user);
if ($user->lastaccess) {
$lastaccess = format_time(time() - $user->lastaccess, $datestring);
} else {
$lastaccess = $strnever;
}
if (empty($user->country)) {
$country = '';
} else {
if ($countrysort) {
$country = '('.$user->country.') '.$countries[$user->country];
} else {
$country = $countries[$user->country];
}
}
$usercontext = context_user::instance($user->id);
if ($piclink = ($USER->id == $user->id || has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext))) {
$profilelink = '<strong><a href="'.$CFG->wwwroot.'/user/view.php?id='.$user->id.'&amp;course='.$course->id.'">'.fullname($user).'</a></strong>';
} else {
$profilelink = '<strong>'.fullname($user).'</strong>';
}
$data = array();
if ($bulkoperations) {
if ($selectall) {
$checked = 'checked="true"';
} else {
$checked = '';
}
$data[] = '<input type="checkbox" class="usercheckbox" name="user'.$user->id.'" ' . $checked .'/>';
}
$data[] = $OUTPUT->user_picture($user, array('size' => 35, 'courseid' => $course->id));
$data[] = $profilelink;
foreach ($extrafields as $field) {
$data[] = $user->{$field};
}
if (!isset($hiddenfields['city'])) {
$data[] = $user->city;
}
if (!isset($hiddenfields['country'])) {
$data[] = $country;
}
if (!isset($hiddenfields['lastaccess'])) {
$data[] = $lastaccess;
}
$table->add_data($data);
}
}
$table->print_html();
echo $participanttablehtml;
$perpageurl = clone($baseurl);
$perpageurl->remove_params('perpage');
if ($perpage == SHOW_ALL_PAGE_SIZE) {
if ($perpage == SHOW_ALL_PAGE_SIZE && $participanttable->totalrows > DEFAULT_PAGE_SIZE) {
$perpageurl->param('perpage', DEFAULT_PAGE_SIZE);
echo $OUTPUT->container(html_writer::link($perpageurl, get_string('showperpage', '', DEFAULT_PAGE_SIZE)), array(), 'showall');
} else if ($matchcount > 0 && $perpage < $matchcount) {
} else if ($participanttable->get_page_size() < $participanttable->totalrows) {
$perpageurl->param('perpage', SHOW_ALL_PAGE_SIZE);
echo $OUTPUT->container(html_writer::link($perpageurl, get_string('showall', '', $matchcount)), array(), 'showall');
echo $OUTPUT->container(html_writer::link($perpageurl, get_string('showall', '', $participanttable->totalrows)),
array(), 'showall');
}
if ($bulkoperations) {
echo '<br /><div class="buttons">';
if ($matchcount > 0 && $perpage < $matchcount) {
if ($participanttable->get_page_size() < $participanttable->totalrows) {
$perpageurl = clone($baseurl);
$perpageurl->remove_params('perpage');
$perpageurl->param('perpage', SHOW_ALL_PAGE_SIZE);
@ -581,9 +328,9 @@ if ($bulkoperations) {
}
echo html_writer::start_tag('div', array('class' => 'btn-group'));
if ($perpage < $matchcount) {
if ($participanttable->get_page_size() < $participanttable->totalrows) {
// Select all users, refresh page showing all users and mark them all selected.
$label = get_string('selectalluserswithcount', 'moodle', $matchcount);
$label = get_string('selectalluserswithcount', 'moodle', $participanttable->totalrows);
echo html_writer::tag('input', "", array('type' => 'button', 'id' => 'checkall', 'class' => 'btn btn-secondary',
'value' => $label, 'data-showallink' => $showalllink));
// Select all users, mark all users on page as selected.
@ -620,7 +367,7 @@ if ($bulkoperations) {
}
// Show a search box if all participants don't fit on a single screen.
if ($totalcount > $perpage) {
if ($participanttable->get_page_size() < $participanttable->totalrows) {
echo '<form action="index.php" class="searchform"><div><input type="hidden" name="id" value="'.$course->id.'" />';
echo '<label for="search">' . get_string('search', 'search') . ' </label>';
echo '<input type="text" id="search" name="search" value="'.s($search).'" />&nbsp;<input type="submit" value="'.get_string('search').'" /></div></form>'."\n";
@ -629,41 +376,3 @@ if ($totalcount > $perpage) {
echo '</div>'; // Userlist.
echo $OUTPUT->footer();
if ($userlist) {
$userlist->close();
}
/**
* Returns SQL that can be used to limit a query to a period where the user last accessed a course..
*
* @param string $accesssince
* @return string
*/
function get_course_lastaccess_sql($accesssince='') {
if (empty($accesssince)) {
return '';
}
if ($accesssince == -1) { // Never.
return 'ul.timeaccess = 0';
} else {
return 'ul.timeaccess != 0 AND ul.timeaccess < '.$accesssince;
}
}
/**
* Returns SQL that can be used to limit a query to a period where the user last accessed the system.
*
* @param string $accesssince
* @return string
*/
function get_user_lastaccess_sql($accesssince='') {
if (empty($accesssince)) {
return '';
}
if ($accesssince == -1) { // Never.
return 'u.lastaccess = 0';
} else {
return 'u.lastaccess != 0 AND u.lastaccess < '.$accesssince;
}
}

View file

@ -1212,3 +1212,177 @@ function user_get_tagged_users($tag, $exclusivemode = false, $fromctx = 0, $ctx
return new core_tag\output\tagindex($tag, 'core', 'user', $content,
$exclusivemode, $fromctx, $ctx, $rec, $page, $totalpages);
}
/**
* Returns the SQL used by the participants table.
*
* @param int $courseid The course id
* @param int $groupid The groupid, 0 means all groups
* @param int $accesssince The time since last access, 0 means any time
* @param int $roleid The role id, 0 means all roles
* @param string $search The search that was performed, empty means perform no search
* @param string $additionalwhere Any additional SQL to add to where
* @param array $additionalparams The additional params
* @return array
*/
function user_get_participants_sql($courseid, $groupid = 0, $accesssince = 0, $roleid = 0, $search = '', $additionalwhere = '',
$additionalparams = array()) {
global $DB;
// Get the context.
$context = \context_course::instance($courseid, MUST_EXIST);
$isfrontpage = ($courseid == SITEID);
list($esql, $params) = get_enrolled_sql($context, null, $groupid, true);
$joins = array('FROM {user} u');
$wheres = array();
$userfields = array('username', 'email', 'city', 'country', 'lang', 'timezone', 'maildisplay');
$mainuserfields = user_picture::fields('u', $userfields);
$extrasql = get_extra_user_fields_sql($context, 'u', '', $userfields);
if ($isfrontpage) {
$select = "SELECT $mainuserfields, u.lastaccess$extrasql";
$joins[] = "JOIN ($esql) e ON e.id = u.id"; // Everybody on the frontpage usually.
if ($accesssince) {
$wheres[] = user_get_user_lastaccess_sql($accesssince);
}
} else {
$select = "SELECT $mainuserfields, COALESCE(ul.timeaccess, 0) AS lastaccess$extrasql";
$joins[] = "JOIN ($esql) e ON e.id = u.id"; // Course enrolled users only.
// Not everybody has accessed the course yet.
$joins[] = 'LEFT JOIN {user_lastaccess} ul ON (ul.userid = u.id AND ul.courseid = :courseid)';
$params['courseid'] = $courseid;
if ($accesssince) {
$wheres[] = user_get_course_lastaccess_sql($accesssince);
}
}
// Performance hacks - we preload user contexts together with accounts.
$ccselect = ', ' . context_helper::get_preload_record_columns_sql('ctx');
$ccjoin = 'LEFT JOIN {context} ctx ON (ctx.instanceid = u.id AND ctx.contextlevel = :contextlevel)';
$params['contextlevel'] = CONTEXT_USER;
$select .= $ccselect;
$joins[] = $ccjoin;
// Limit list to users with some role only.
if ($roleid) {
// We want to query both the current context and parent contexts.
list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($context->get_parent_context_ids(true),
SQL_PARAMS_NAMED, 'relatedctx');
$wheres[] = "u.id IN (SELECT userid FROM {role_assignments} WHERE roleid = :roleid AND contextid $relatedctxsql)";
$params = array_merge($params, array('roleid' => $roleid), $relatedctxparams);
}
if (!empty($search)) {
$fullname = $DB->sql_fullname('u.firstname', 'u.lastname');
$wheres[] = '(' . $DB->sql_like($fullname, ':search1', false, false) .
' OR ' . $DB->sql_like('email', ':search2', false, false) .
' OR ' . $DB->sql_like('idnumber', ':search3', false, false) . ') ';
$params['search1'] = "%$search%";
$params['search2'] = "%$search%";
$params['search3'] = "%$search%";
}
if (!empty($additionalwhere)) {
$wheres[] = $additionalwhere;
$params = array_merge($params, $additionalparams);
}
$from = implode("\n", $joins);
if ($wheres) {
$where = 'WHERE ' . implode(' AND ', $wheres);
} else {
$where = '';
}
return array($select, $from, $where, $params);
}
/**
* Returns the total number of participants for a given course.
*
* @param int $courseid The course id
* @param int $groupid The groupid, 0 means all groups
* @param int $accesssince The time since last access, 0 means any time
* @param int $roleid The role id, 0 means all roles
* @param string $search The search that was performed, empty means perform no search
* @param string $additionalwhere Any additional SQL to add to where
* @param array $additionalparams The additional params
* @return int
*/
function user_get_total_participants($courseid, $groupid = 0, $accesssince = 0, $roleid = 0, $search = '', $additionalwhere = '',
$additionalparams = array()) {
global $DB;
list($select, $from, $where, $params) = user_get_participants_sql($courseid, $groupid, $accesssince, $roleid,
$search, $additionalwhere, $additionalparams);
return $DB->count_records_sql("SELECT COUNT(u.id) $from $where", $params);
}
/**
* Returns the participants for a given course.
*
* @param int $courseid The course id
* @param int $groupid The group id
* @param int $accesssince The time since last access
* @param int $roleid The role id
* @param string $search The search that was performed
* @param string $additionalwhere Any additional SQL to add to where
* @param array $additionalparams The additional params
* @param string $sort The SQL sort
* @param int $limitfrom return a subset of records, starting at this point (optional).
* @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
* @return moodle_recordset
*/
function user_get_participants($courseid, $groupid = 0, $accesssince, $roleid, $search, $additionalwhere = '',
$additionalparams = array(), $sort = '', $limitfrom = 0, $limitnum = 0) {
global $DB;
list($select, $from, $where, $params) = user_get_participants_sql($courseid, $groupid, $accesssince, $roleid,
$search, $additionalwhere, $additionalparams);
return $DB->get_recordset_sql("$select $from $where $sort", $params, $limitfrom, $limitnum);
}
/**
* Returns SQL that can be used to limit a query to a period where the user last accessed a course.
*
* @param int $accesssince The time since last access
* @param string $tableprefix
* @return string
*/
function user_get_course_lastaccess_sql($accesssince = null, $tableprefix = 'ul') {
if (empty($accesssince)) {
return '';
}
if ($accesssince == -1) { // Never.
return $tableprefix . '.timeaccess = 0';
} else {
return $tableprefix . '.timeaccess != 0 AND ul.timeaccess < ' . $accesssince;
}
}
/**
* Returns SQL that can be used to limit a query to a period where the user last accessed the system.
*
* @param int $accesssince The time since last access
* @param string $tableprefix
* @return string
*/
function user_get_user_lastaccess_sql($accesssince = null, $tableprefix = 'u') {
if (empty($accesssince)) {
return '';
}
if ($accesssince == -1) { // Never.
return $tableprefix . '.lastaccess = 0';
} else {
return $tableprefix . '.lastaccess != 0 AND u.lastaccess < ' . $accesssince;
}
}