mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
user selection: MDL-16994 Improve the user selector used on the assign roles and group memebers pages - Convert the group memebership page.
This commit is contained in:
parent
e4749fcc08
commit
9787301687
@ -201,3 +201,17 @@ var removeLoaderImgs = function (elClass, parentId) {
|
||||
parentEl.removeChild(loader);
|
||||
}
|
||||
};
|
||||
|
||||
function init_add_remove_members_page() {
|
||||
var addselect = user_selector.get('addselect');
|
||||
document.getElementById('add').disabled = addselect.is_selection_empty();
|
||||
addselect.subscribe('selectionchanged', function(isempty) {
|
||||
document.getElementById('add').disabled = isempty;
|
||||
});
|
||||
|
||||
var removeselect = user_selector.get('removeselect');
|
||||
document.getElementById('remove').disabled = removeselect.is_selection_empty();
|
||||
removeselect.subscribe('selectionchanged', function(isempty) {
|
||||
document.getElementById('remove').disabled = isempty;
|
||||
});
|
||||
}
|
@ -392,57 +392,6 @@ function groups_delete_groupings($courseid, $showfeedback=false) {
|
||||
/* various functions used by groups UI */
|
||||
/* =================================== */
|
||||
|
||||
/**
|
||||
* Gets the users for a course who are not in a specified group, and returns
|
||||
* them in an array organised by role. For the array format, see
|
||||
* groups_get_members_by_role.
|
||||
* @param int $groupid The id of the group
|
||||
* @param string searchtext similar to searchtext in role assign, search
|
||||
* @return array An array of role id or '*' => information about that role
|
||||
* including a list of users
|
||||
*/
|
||||
function groups_get_users_not_in_group_by_role($courseid, $groupid, $searchtext='', $sort = 'u.lastname ASC') {
|
||||
global $CFG, $DB;
|
||||
|
||||
$context = get_context_instance(CONTEXT_COURSE, $courseid);
|
||||
|
||||
/// Get list of allowed roles
|
||||
if (!$validroleids = groups_get_possible_roles($context)) {
|
||||
return array();
|
||||
}
|
||||
list($roleids, $params) = $DB->get_in_or_equal($validroleids, SQL_PARAMS_NAMED, $start='r0');
|
||||
|
||||
if ($searchtext !== '') { // Search for a subset of remaining users
|
||||
$LIKE = $DB->sql_ilike();
|
||||
$FULLNAME = $DB->sql_fullname();
|
||||
$wheresearch = " AND u.id IN (SELECT id FROM {user} WHERE $FULLNAME $LIKE :search1 OR email $LIKE :search2)";
|
||||
$params['search1'] = "%$searchtext%";
|
||||
$params['search2'] = "%$searchtext%";
|
||||
} else {
|
||||
$wheresearch = '';
|
||||
}
|
||||
|
||||
/// Construct the main SQL
|
||||
$sql = " SELECT r.id AS roleid,r.shortname AS roleshortname,r.name AS rolename,
|
||||
u.id AS userid, u.firstname, u.lastname
|
||||
FROM {user} u
|
||||
JOIN {role_assignments} ra ON ra.userid = u.id
|
||||
JOIN {role} r ON r.id = ra.roleid
|
||||
WHERE ra.contextid ".get_related_contexts_string($context)."
|
||||
AND u.deleted = 0
|
||||
AND ra.roleid $roleids
|
||||
AND u.id NOT IN (SELECT userid
|
||||
FROM {groups_members}
|
||||
WHERE groupid = :groupid)
|
||||
$wheresearch
|
||||
ORDER BY $sort";
|
||||
$params['groupid'] = $groupid;
|
||||
|
||||
$rs = $DB->get_recordset_sql($sql, $params);
|
||||
return groups_calculate_role_people($rs, $context);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Obtains a list of the possible roles that group members might come from,
|
||||
* on a course. Generally this includes all the roles who would have
|
||||
@ -620,15 +569,22 @@ function groups_unassign_grouping($groupingid, $groupid) {
|
||||
* @param int $courseid Course ID (should match the group's course)
|
||||
* @param string $fields List of fields from user table prefixed with u, default 'u.*'
|
||||
* @param string $sort SQL ORDER BY clause, default 'u.lastname ASC'
|
||||
* @param string $extrawheretest extra SQL conditions ANDed with the existing where clause.
|
||||
* @param array $whereparams any parameters required by $extrawheretest.
|
||||
* @return array Complex array as described above
|
||||
*/
|
||||
function groups_get_members_by_role($groupid, $courseid, $fields='u.*', $sort='u.lastname ASC') {
|
||||
function groups_get_members_by_role($groupid, $courseid, $fields='u.*',
|
||||
$sort='u.lastname ASC', $extrawheretest='', $whereparams=array()) {
|
||||
global $CFG, $DB;
|
||||
|
||||
// Retrieve information about all users and their roles on the course or
|
||||
// parent ('related') contexts
|
||||
$context = get_context_instance(CONTEXT_COURSE, $courseid);
|
||||
|
||||
if ($extrawheretest) {
|
||||
$extrawheretest = ' AND ' . $extrawheretest;
|
||||
}
|
||||
|
||||
$sql = "SELECT r.id AS roleid, r.shortname AS roleshortname, r.name AS rolename,
|
||||
u.id AS userid, $fields
|
||||
FROM {groups_members} gm
|
||||
@ -636,10 +592,11 @@ function groups_get_members_by_role($groupid, $courseid, $fields='u.*', $sort='u
|
||||
JOIN {role_assignments} ra ON ra.userid = u.id
|
||||
JOIN {role} r ON r.id = ra.roleid
|
||||
WHERE gm.groupid=?
|
||||
AND ra.contextid ".get_related_contexts_string($context)."
|
||||
AND ra.contextid ".get_related_contexts_string($context).
|
||||
$extrawheretest."
|
||||
ORDER BY r.sortorder, $sort";
|
||||
$params = array($groupid);
|
||||
$rs = $DB->get_recordset_sql($sql, $params);
|
||||
array_unshift($whereparams, $groupid);
|
||||
$rs = $DB->get_recordset_sql($sql, $whereparams);
|
||||
|
||||
return groups_calculate_role_people($rs, $context);
|
||||
}
|
||||
|
@ -2,24 +2,18 @@
|
||||
/**
|
||||
* Add/remove members from group.
|
||||
*
|
||||
* @copyright © 2006 The Open University
|
||||
* @copyright © 2006 The Open University and others
|
||||
* @author N.D.Freear AT open.ac.uk
|
||||
* @author J.White AT open.ac.uk
|
||||
* @author J.White AT open.ac.uk and others
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
|
||||
* @package groups
|
||||
*/
|
||||
require_once('../config.php');
|
||||
require_once('lib.php');
|
||||
|
||||
define("MAX_USERS_PER_PAGE", 5000);
|
||||
require_once(dirname(__FILE__) . '/../config.php');
|
||||
require_once(dirname(__FILE__) . '/lib.php');
|
||||
require_once($CFG->dirroot . '/user/selector/lib.php');
|
||||
require_js('group/clientlib.js');
|
||||
|
||||
$groupid = required_param('group', PARAM_INT);
|
||||
$searchtext = optional_param('searchtext', '', PARAM_RAW); // search string
|
||||
$showall = optional_param('showall', 0, PARAM_BOOL);
|
||||
|
||||
if ($showall) {
|
||||
$searchtext = '';
|
||||
}
|
||||
|
||||
if (!$group = $DB->get_record('groups', array('id'=>$groupid))) {
|
||||
print_error('invalidgroupid');
|
||||
@ -34,106 +28,45 @@ require_login($course);
|
||||
$context = get_context_instance(CONTEXT_COURSE, $courseid);
|
||||
require_capability('moodle/course:managegroups', $context);
|
||||
|
||||
$strsearch = get_string('search');
|
||||
$strshowall = get_string('showall');
|
||||
$returnurl = $CFG->wwwroot.'/group/index.php?id='.$courseid.'&group='.$group->id;
|
||||
|
||||
if (optional_param('cancel', false, PARAM_BOOL)) {
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
if ($frm = data_submitted() and confirm_sesskey()) {
|
||||
|
||||
if (isset($frm->cancel)) {
|
||||
redirect($returnurl);
|
||||
|
||||
} else if (isset($frm->add) and !empty($frm->addselect)) {
|
||||
|
||||
foreach ($frm->addselect as $userid) {
|
||||
if (! $userid = clean_param($userid, PARAM_INT)) {
|
||||
continue;
|
||||
}
|
||||
if (!groups_add_member($groupid, $userid)) {
|
||||
$groupmembersselector = new group_members_selector('removeselect',
|
||||
array('groupid' => $groupid, 'courseid' => $course->id));
|
||||
$groupmembersselector->set_extra_fields(array());
|
||||
$potentialmembersselector = new group_non_members_selector('addselect',
|
||||
array('groupid' => $groupid, 'courseid' => $course->id));
|
||||
$potentialmembersselector->set_extra_fields(array());
|
||||
|
||||
if (optional_param('add', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
$userstoadd = $potentialmembersselector->get_selected_users();
|
||||
if (!empty($userstoadd)) {
|
||||
foreach ($userstoadd as $user) {
|
||||
if (!groups_add_member($groupid, $user->id)) {
|
||||
print_error('erroraddremoveuser', 'group', $returnurl);
|
||||
}
|
||||
$groupmembersselector->invalidate_selected_users();
|
||||
$potentialmembersselector->invalidate_selected_users();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (isset($frm->remove) and !empty($frm->removeselect)) {
|
||||
|
||||
foreach ($frm->removeselect as $userid) {
|
||||
if (! $userid = clean_param($userid, PARAM_INT)) {
|
||||
continue;
|
||||
}
|
||||
if (!groups_remove_member($groupid, $userid)) {
|
||||
if (optional_param('remove', false, PARAM_BOOL) && confirm_sesskey()) {
|
||||
$userstoremove = $groupmembersselector->get_selected_users();
|
||||
if (!empty($userstoremove)) {
|
||||
foreach ($userstoremove as $user) {
|
||||
if (!groups_remove_member($groupid, $user->id)) {
|
||||
print_error('erroraddremoveuser', 'group', $returnurl);
|
||||
}
|
||||
$groupmembersselector->invalidate_selected_users();
|
||||
$potentialmembersselector->invalidate_selected_users();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$groupmembersoptions = '';
|
||||
$groupmemberscount = 0;
|
||||
|
||||
// Get members, organised by role, and display
|
||||
if ($groupmemberroles = groups_get_members_by_role($groupid,$courseid,'u.id,u.firstname,u.lastname')) {
|
||||
foreach($groupmemberroles as $roleid=>$roledata) {
|
||||
$groupmembersoptions .= '<optgroup label="'.s($roledata->name).'">';
|
||||
foreach($roledata->users as $member) {
|
||||
$groupmembersoptions .= '<option value="'.$member->id.'">'.fullname($member, true).'</option>';
|
||||
$groupmemberscount ++;
|
||||
}
|
||||
$groupmembersoptions .= '</optgroup>';
|
||||
}
|
||||
} else {
|
||||
$groupmembersoptions .= '<option> </option>';
|
||||
}
|
||||
|
||||
$potentialmembers = array();
|
||||
$potentialmembersoptions = '';
|
||||
$potentialmemberscount = 0;
|
||||
|
||||
// Get potential members, organised by role, and count them
|
||||
$potentialmembersbyrole = groups_get_users_not_in_group_by_role($courseid, $groupid, $searchtext);
|
||||
$potentialmemberscount=0;
|
||||
$potentialmembersids=array();
|
||||
if (!empty($potentialmembersbyrole)) {
|
||||
foreach($potentialmembersbyrole as $roledata) {
|
||||
$potentialmemberscount += count($roledata->users);
|
||||
$potentialmembersids = array_merge($potentialmembersids, array_keys($roledata->users));
|
||||
}
|
||||
}
|
||||
|
||||
$usergroups = array();
|
||||
|
||||
if ($potentialmemberscount <= MAX_USERS_PER_PAGE) {
|
||||
if ($potentialmemberscount > 0) {
|
||||
// Get other groups user already belongs to
|
||||
list($potentialmembersids, $params) = $DB->get_in_or_equal($potentialmembersids, SQL_PARAMS_NAMED, 'pm0');
|
||||
$sql = "SELECT u.id AS userid, g.*
|
||||
FROM {user} u
|
||||
JOIN {groups_members} gm ON u.id = gm.userid
|
||||
JOIN {groups} g ON gm.groupid = g.id
|
||||
WHERE u.id $potentialmembersids AND g.courseid = :courseid ";
|
||||
$params['courseid'] = $course->id;
|
||||
if ($rs = $DB->get_recordset_sql($sql, $params)) {
|
||||
foreach ($rs as $usergroup) {
|
||||
$usergroups[$usergroup->userid][$usergroup->id] = $usergroup;
|
||||
}
|
||||
$rs->close();
|
||||
}
|
||||
|
||||
foreach ($potentialmembersbyrole as $roleid=>$roledata) {
|
||||
$potentialmembersoptions .= '<optgroup label="'.s($roledata->name).'">';
|
||||
foreach($roledata->users as $member) {
|
||||
$name = s(fullname($member, true));
|
||||
$potentialmembersoptions .= '<option value="'.$member->id.
|
||||
'" title="'.$name.'">'.$name.
|
||||
' ('.@count($usergroups[$member->id]).')</option>';
|
||||
}
|
||||
$potentialmembersoptions .= '</optgroup>';
|
||||
}
|
||||
} else {
|
||||
$potentialmembersoptions .= '<option> </option>';
|
||||
}
|
||||
}
|
||||
|
||||
// Print the page and form
|
||||
$strgroups = get_string('groups');
|
||||
$strparticipants = get_string('participants');
|
||||
@ -149,62 +82,8 @@ $navlinks[] = array('name' => $stradduserstogroup, 'link' => null, 'type' => 'mi
|
||||
$navigation = build_navigation($navlinks);
|
||||
|
||||
print_header("$course->shortname: $strgroups", $course->fullname, $navigation, '', '', true, '', user_login_string($course, $USER));
|
||||
|
||||
// Print Javascript for showing the selected users group membership
|
||||
check_theme_arrows();
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var userSummaries = Array(
|
||||
<?php
|
||||
$membercnt = count($potentialmembers);
|
||||
$i=1;
|
||||
foreach ($potentialmembers as $userid => $potentalmember) {
|
||||
|
||||
if (isset($usergroups[$userid])) {
|
||||
$usergrouplist = '<ul>';
|
||||
|
||||
foreach ($usergroups[$userid] as $groupitem) {
|
||||
$usergrouplist .= '<li>'.addslashes_js(format_string($groupitem->name)).'</li>';
|
||||
}
|
||||
$usergrouplist .= '</ul>';
|
||||
}
|
||||
else {
|
||||
$usergrouplist = '';
|
||||
}
|
||||
echo "'$usergrouplist'";
|
||||
if ($i < $membercnt) {
|
||||
echo ', ';
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
?>
|
||||
);
|
||||
|
||||
function updateUserSummary() {
|
||||
|
||||
var selectEl = document.getElementById('addselect');
|
||||
var summaryDiv = document.getElementById('group-usersummary');
|
||||
var length = selectEl.length;
|
||||
var selectCnt = 0;
|
||||
var selectIdx = -1;
|
||||
|
||||
for(i=0;i<length;i++) {
|
||||
if (selectEl.options[i].selected) {
|
||||
selectCnt++;
|
||||
selectIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectCnt == 1 && userSummaries[selectIdx]) {
|
||||
summaryDiv.innerHTML = userSummaries[selectIdx];
|
||||
} else {
|
||||
summaryDiv.innerHTML = '';
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<div id="addmembersform">
|
||||
<h3 class="main"><?php print_string('adduserstogroup', 'group'); echo ": $groupname"; ?></h3>
|
||||
@ -214,71 +93,28 @@ function updateUserSummary() {
|
||||
<input type="hidden" name="sesskey" value="<?php p(sesskey()); ?>" />
|
||||
<input type="hidden" name="group" value="<?php echo $groupid; ?>" />
|
||||
|
||||
<table cellpadding="6" class="generaltable generalbox groupmanagementtable boxaligncenter" summary="">
|
||||
<table class="generaltable generalbox groupmanagementtable boxaligncenter" summary="">
|
||||
<tr>
|
||||
<td valign="top">
|
||||
<td id='memberscell'>
|
||||
<p>
|
||||
<label for="removeselect"><?php print_string('existingmembers', 'group', $groupmemberscount); ?></label>
|
||||
<label for="removeselect"><?php print_string('groupmembers', 'group'); ?></label>
|
||||
</p>
|
||||
<select name="removeselect[]" size="20" id="removeselect" multiple="multiple"
|
||||
onfocus="document.getElementById('assignform').add.disabled=true;
|
||||
document.getElementById('assignform').remove.disabled=false;
|
||||
document.getElementById('assignform').addselect.selectedIndex=-1;"
|
||||
onclick="this.focus();updateUserSummary();">
|
||||
<?php echo $groupmembersoptions ?>
|
||||
</select></td>
|
||||
<td valign="top">
|
||||
<?php // Hidden assignment? ?>
|
||||
|
||||
<?php check_theme_arrows(); ?>
|
||||
<?php $groupmembersselector->display(); ?>
|
||||
</td>
|
||||
<td id='buttonscell'>
|
||||
<p class="arrow_button">
|
||||
<input name="add" id="add" type="submit" value="<?php echo $THEME->larrow.' '.get_string('add'); ?>" title="<?php print_string('add'); ?>" /><br />
|
||||
<input name="remove" id="remove" type="submit" value="<?php echo get_string('remove').' '.$THEME->rarrow; ?>" title="<?php print_string('remove'); ?>" />
|
||||
</p>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<td id='nonmemberscell'>
|
||||
<p>
|
||||
<label for="addselect"><?php print_string('potentialmembers', 'group', $potentialmemberscount); ?></label>
|
||||
<label for="addselect"><?php print_string('potentialmembs', 'group'); ?></label>
|
||||
</p>
|
||||
<select name="addselect[]" size="20" id="addselect" multiple="multiple"
|
||||
onfocus="updateUserSummary();document.getElementById('assignform').add.disabled=false;
|
||||
document.getElementById('assignform').remove.disabled=true;
|
||||
document.getElementById('assignform').removeselect.selectedIndex=-1;"
|
||||
onclick="this.focus();updateUserSummary();">
|
||||
<?php
|
||||
if ($potentialmemberscount > MAX_USERS_PER_PAGE) {
|
||||
echo '<optgroup label="'.get_string('toomanytoshow').'"><option></option></optgroup>'."\n"
|
||||
.'<optgroup label="'.get_string('trysearching').'"><option></option></optgroup>'."\n";
|
||||
} else {
|
||||
echo $potentialmembersoptions;
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<br />
|
||||
<label for="searchtext" class="accesshide"><?php p($strsearch) ?></label>
|
||||
<input type="text" name="searchtext" id="searchtext" size="21" value="<?php p($searchtext) ?>"
|
||||
onfocus ="getElementById('assignform').add.disabled=true;
|
||||
getElementById('assignform').remove.disabled=true;
|
||||
getElementById('assignform').removeselect.selectedIndex=-1;
|
||||
getElementById('assignform').addselect.selectedIndex=-1;"
|
||||
onkeydown = "var keyCode = event.which ? event.which : event.keyCode;
|
||||
if (keyCode == 13) {
|
||||
getElementById('assignform').previoussearch.value=1;
|
||||
getElementById('assignform').submit();
|
||||
} " />
|
||||
<input name="search" id="search" type="submit" value="<?php p($strsearch) ?>" />
|
||||
<?php
|
||||
if (!empty($searchtext)) {
|
||||
echo '<br /><input name="showall" id="showall" type="submit" value="'.s($strshowall).'" />'."\n";
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td valign="top">
|
||||
<p><?php echo($strusergroupmembership) ?></p>
|
||||
<div id="group-usersummary"></div>
|
||||
</td>
|
||||
<?php $potentialmembersselector->display(); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>
|
||||
<tr><td colspan="3" id='backcell'>
|
||||
<input type="submit" name="cancel" value="<?php print_string('backtogroups', 'group'); ?>" />
|
||||
</td></tr>
|
||||
</table>
|
||||
@ -287,5 +123,6 @@ function updateUserSummary() {
|
||||
</div>
|
||||
|
||||
<?php
|
||||
print_js_call('init_add_remove_members_page');
|
||||
print_footer($course);
|
||||
?>
|
||||
|
@ -269,7 +269,7 @@ $string['invalidnumkey'] = '\$conditions array may not contain numeric keys, ple
|
||||
$string['invalidoutcome'] = 'Incorrect outcome id';
|
||||
$string['invalidpagesize'] = 'Invalid page size';
|
||||
$string['invalidpaymentmethod'] = 'Invalid payment method: $a';
|
||||
$stirng['invalidqueryparam'] = 'ERROR: Incorrect number of query parameters!!';
|
||||
$string['invalidqueryparam'] = 'ERROR: Incorrect number of query parameters. Expected $a->expected, got $a->actual.';
|
||||
$string['invalidrequest'] = 'Invalid request';
|
||||
$string['invalidrole'] = 'Invalid role';
|
||||
$string['invalidroleid'] = 'Invalid role ID';
|
||||
|
@ -72,6 +72,7 @@ $string['newgrouping'] = 'New grouping';
|
||||
$string['backtogroups'] = 'Back to groups';
|
||||
$string['backtogroupings'] = 'Back to groupings';
|
||||
$string['existingmembers'] = 'Existing members: $a';
|
||||
$string['potentialmembs'] = 'Potential members';
|
||||
$string['potentialmembers'] = 'Potential members: $a';
|
||||
$string['groupinfo'] = 'Info about selected group';
|
||||
$string['groupinfomembers'] = 'Info about selected members';
|
||||
|
@ -433,16 +433,45 @@ form.popupform label {
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.groupmanagementtable {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.groupmanagementtable td {
|
||||
vertical-align: top;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.groupmanagementtable p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.groupmanagementtable select {
|
||||
width: 18em;
|
||||
.groupmanagementtable #memberscell,
|
||||
.groupmanagementtable #nonmemberscell {
|
||||
width: 42%;
|
||||
}
|
||||
.groupmanagementtable #memberscell label,
|
||||
.groupmanagementtable #nonmemberscell label {
|
||||
font-weight: bold;
|
||||
}
|
||||
.groupmanagementtable #buttonscell {
|
||||
width: 16%;
|
||||
}
|
||||
.groupmanagementtable #buttonscell input {
|
||||
width: 80%;
|
||||
padding: 1em 0;
|
||||
margin: 2em 0;
|
||||
}
|
||||
.groupmanagementtable #backcell {
|
||||
padding-top: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
#removeselect_wrapper,
|
||||
#addselect_wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
.groupmanagementtable #removeselect_wrapper label,
|
||||
.groupmanagementtable #addselect_wrapper label {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#group-groupings .buttons {
|
||||
@ -517,6 +546,13 @@ div.hide {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.userselector select {
|
||||
width: 100%;
|
||||
}
|
||||
.userselector div label {
|
||||
margin-right: 0.3em;
|
||||
}
|
||||
|
||||
/***
|
||||
*** Forms
|
||||
***/
|
||||
|
@ -37,6 +37,10 @@ define('USER_SELECTOR_DEFAULT_ROWS', 20);
|
||||
|
||||
/**
|
||||
* Base class for user selectors.
|
||||
*
|
||||
* In your theme, you must give each user-selector a defined width. If the
|
||||
* user selector has name="myid", then the div myid_wrapper must have a width
|
||||
* specified.
|
||||
*/
|
||||
abstract class user_selector_base {
|
||||
/** The control name (and id) in the HTML. */
|
||||
@ -115,14 +119,22 @@ abstract class user_selector_base {
|
||||
return $this->selected;
|
||||
}
|
||||
|
||||
/**
|
||||
* If you update the database in such a way that it is likely to change the
|
||||
* list of users that this component is allowed to select from, then you
|
||||
* must call this method. For example, on the role assign page, after you have
|
||||
* assigned some roles to some users, you should call this.
|
||||
*/
|
||||
public function invalidate_selected_users() {
|
||||
$this->selected = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output this user_selector as HTML.
|
||||
* @param boolean $return if true, return the HTML as a string instead of outputting it.
|
||||
* @return mixed if $return is true, returns the HTML as a string, otherwise returns nothing.
|
||||
*/
|
||||
public function display($return = false) {
|
||||
global $USER, $CFG;
|
||||
|
||||
// Get the list of requested users.
|
||||
$search = optional_param($this->name . '_searchtext', '', PARAM_RAW);
|
||||
$groupedusers = $this->find_users($search);
|
||||
@ -199,6 +211,16 @@ abstract class user_selector_base {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user fields that are displayed in the selector in addition to the
|
||||
* user's name.
|
||||
*
|
||||
* @param array $fields a list of field names that exist in the user table.
|
||||
*/
|
||||
public function set_extra_fields($fields) {
|
||||
$this->extrafields = $fields;
|
||||
}
|
||||
|
||||
// API for sublasses =======================================================
|
||||
|
||||
/**
|
||||
@ -351,7 +373,7 @@ abstract class user_selector_base {
|
||||
// If $groupedusers is empty, make a 'no matching users' group. If there
|
||||
// is only one selected user, set a flag to select them.
|
||||
$select = false;
|
||||
if (empty($groupedusers) && empty($this->selected)) {
|
||||
if (empty($groupedusers)) {
|
||||
$groupedusers = array(get_string('nomatchingusers') => array());
|
||||
} else if (count($groupedusers) == 1 && count(reset($groupedusers)) == 1) {
|
||||
$select = true;
|
||||
@ -387,7 +409,7 @@ abstract class user_selector_base {
|
||||
*/
|
||||
protected function output_optgroup($groupname, $users, $select) {
|
||||
if (!empty($users)) {
|
||||
$output = '<optgroup label="' . s($groupname) . ' (' . count($users) . ')">' . "\n";
|
||||
$output = ' <optgroup label="' . s($groupname) . ' (' . count($users) . ')">' . "\n";
|
||||
foreach ($users as $user) {
|
||||
if ($select || isset($this->selected[$user->id])) {
|
||||
$selectattr = ' selected="selected"';
|
||||
@ -395,14 +417,14 @@ abstract class user_selector_base {
|
||||
$selectattr = '';
|
||||
}
|
||||
unset($this->selected[$user->id]);
|
||||
$output .= '<option' . $selectattr . ' value="' . $user->id . '">' .
|
||||
$output .= ' <option' . $selectattr . ' value="' . $user->id . '">' .
|
||||
$this->output_user($user) . "</option>\n";
|
||||
}
|
||||
} else {
|
||||
$output = '<optgroup label="' . s($groupname) . '">' . "\n";
|
||||
$output .= '<option disabled="disabled"> </option>' . "\n";
|
||||
$output = ' <optgroup label="' . s($groupname) . '">' . "\n";
|
||||
$output .= ' <option disabled="disabled"> </option>' . "\n";
|
||||
}
|
||||
$output .= "</optgroup>\n";
|
||||
$output .= " </optgroup>\n";
|
||||
return $output;
|
||||
}
|
||||
|
||||
@ -449,7 +471,8 @@ abstract class user_selector_base {
|
||||
|
||||
// Initialise the selector.
|
||||
$output .= print_js_call('new user_selector', array($this->name, $hash,
|
||||
sesskey(), $this->extrafields, get_string('previouslyselectedusers')), true);
|
||||
sesskey(), $this->extrafields, get_string('previouslyselectedusers'),
|
||||
get_string('nomatchingusers')), true);
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@ -474,9 +497,119 @@ class role_assign_current_user_selector extends user_selector_base {
|
||||
}
|
||||
}
|
||||
|
||||
class group_members_user_selector extends user_selector_base {
|
||||
abstract class groups_user_selector_base extends user_selector_base {
|
||||
protected $groupid;
|
||||
protected $courseid;
|
||||
|
||||
/**
|
||||
* @param string $name control name
|
||||
* @param array $options should have two elements with keys groupid and courseid.
|
||||
*/
|
||||
public function __construct($name, $options) {
|
||||
global $CFG;
|
||||
parent::__construct($name, $options);
|
||||
$this->groupid = $options['groupid'];
|
||||
$this->courseid = $options['courseid'];
|
||||
require_once($CFG->dirroot . '/group/lib.php');
|
||||
}
|
||||
|
||||
protected function get_options() {
|
||||
$options = parent::get_options();
|
||||
$options['groupid'] = $this->groupid;
|
||||
$options['courseid'] = $this->courseid;
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter description here...
|
||||
*
|
||||
* @param array $roles array in the format returned by groups_calculate_role_people.
|
||||
* @return array array in the format find_users is supposed to return.
|
||||
*/
|
||||
protected function convert_array_format($roles) {
|
||||
if (empty($roles)) {
|
||||
$roles = array();
|
||||
}
|
||||
$groupedusers = array();
|
||||
foreach ($roles as $role) {
|
||||
$groupedusers[$role->name] = $role->users;
|
||||
foreach ($groupedusers[$role->name] as &$user) {
|
||||
unset($user->roles);
|
||||
$user->fullname = fullname($user);
|
||||
}
|
||||
}
|
||||
return $groupedusers;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User selector subclass for the list of users who are in a certain group.
|
||||
* Used on the add group memebers page.
|
||||
*/
|
||||
class group_members_selector extends groups_user_selector_base {
|
||||
public function find_users($search) {
|
||||
return array(); // TODO
|
||||
list($wherecondition, $params) = $this->search_sql($search, 'u');
|
||||
$roles = groups_get_members_by_role($this->groupid, $this->courseid,
|
||||
$this->required_fields_sql('u'), 'u.lastname, u.firstname',
|
||||
$wherecondition, $params);
|
||||
return $this->convert_array_format($roles);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User selector subclass for the list of users who are not in a certain group.
|
||||
* Used on the add group memebers page.
|
||||
*/
|
||||
class group_non_members_selector extends groups_user_selector_base {
|
||||
const MAX_USERS_PER_PAGE = 100;
|
||||
|
||||
protected function output_user($user) {
|
||||
return parent::output_user($user) . ' (' . $user->numgroups . ')';
|
||||
}
|
||||
|
||||
public function find_users($search) {
|
||||
global $DB;
|
||||
|
||||
// Get list of allowed roles.
|
||||
$context = get_context_instance(CONTEXT_COURSE, $this->courseid);
|
||||
if (!$validroleids = groups_get_possible_roles($context)) {
|
||||
return array();
|
||||
}
|
||||
list($roleids, $roleparams) = $DB->get_in_or_equal($validroleids);
|
||||
|
||||
// Get the search condition.
|
||||
list($searchcondition, $searchparams) = $this->search_sql($search, 'u');
|
||||
|
||||
// Build the SQL
|
||||
$fields = "SELECT r.id AS roleid, r.shortname AS roleshortname, r.name AS rolename, u.id AS userid, " .
|
||||
$this->required_fields_sql('u') .
|
||||
', (SELECT count(igm.groupid) FROM {groups_members} igm JOIN {groups} ig ON
|
||||
igm.groupid = ig.id WHERE igm.userid = u.id AND ig.courseid = ?) AS numgroups ';
|
||||
$sql = " FROM {user} u
|
||||
JOIN {role_assignments} ra ON ra.userid = u.id
|
||||
JOIN {role} r ON r.id = ra.roleid
|
||||
WHERE ra.contextid " . get_related_contexts_string($context) . "
|
||||
AND u.deleted = 0
|
||||
AND ra.roleid $roleids
|
||||
AND u.id NOT IN (SELECT userid
|
||||
FROM {groups_members}
|
||||
WHERE groupid = ?)
|
||||
AND $searchcondition";
|
||||
$orderby = " ORDER BY u.lastname, u.firstname";
|
||||
|
||||
$params = array_merge($roleparams, array($this->groupid), $searchparams);
|
||||
$potentialmemberscount = $DB->count_records_sql('SELECT count(DISTINCT u.id) ' . $sql, $params);
|
||||
|
||||
if ($potentialmemberscount > group_non_members_selector::MAX_USERS_PER_PAGE) {
|
||||
return array(get_string('toomanytoshow') => array(),
|
||||
get_string('trysearching') => array());
|
||||
}
|
||||
|
||||
array_unshift($params, $this->courseid);
|
||||
$rs = $DB->get_recordset_sql($fields . $sql . $orderby, $params);
|
||||
$roles = groups_calculate_role_people($rs, $context);
|
||||
|
||||
return $this->convert_array_format($roles);
|
||||
}
|
||||
}
|
||||
?>
|
@ -12,14 +12,16 @@
|
||||
* @param Array extrafields extra fields we are displaying for each user in addition to fullname.
|
||||
* @param String label used for the optgroup of users who are selected but who do not match the current search.
|
||||
*/
|
||||
function user_selector(name, hash, sesskey, extrafields, strprevselected) {
|
||||
function user_selector(name, hash, sesskey, extrafields, strprevselected, strnomatchingusers) {
|
||||
this.name = name;
|
||||
this.extrafields = extrafields;
|
||||
this.strprevselected = strprevselected;
|
||||
this.strnomatchingusers = strnomatchingusers;
|
||||
this.searchurl = moodle_cfg.wwwroot + '/user/selector/search.php?selectorid=' +
|
||||
hash + '&sesskey=' + sesskey + '&search='
|
||||
|
||||
// Set up the data source.
|
||||
this.datasource = new YAHOO.util.XHRDataSource(moodle_cfg.wwwroot +
|
||||
'/user/selector/search.php?selectorid=' + hash + '&sesskey=' + sesskey + '&search=');
|
||||
this.datasource = new YAHOO.util.XHRDataSource(this.searchurl);
|
||||
this.datasource.connXhrMode = 'cancelStaleRequests';
|
||||
this.datasource.responseType = YAHOO.util.XHRDataSource.TYPE_JSON;
|
||||
this.datasource.responseSchema = {resultsList: 'results'};
|
||||
@ -92,6 +94,14 @@ user_selector.prototype.extrafields = [];
|
||||
*/
|
||||
user_selector.prototype.strprevselected = '';
|
||||
|
||||
/**
|
||||
* Name of the no matching users group.
|
||||
*
|
||||
* @property strnomatchingusers
|
||||
* @type String
|
||||
*/
|
||||
user_selector.prototype.strnomatchingusers = '';
|
||||
|
||||
// Fields that configure the control's behaviour ===============================
|
||||
|
||||
/**
|
||||
@ -107,6 +117,13 @@ user_selector.prototype.querydelay = 0.2;
|
||||
|
||||
// Internal fields =============================================================
|
||||
|
||||
/**
|
||||
* The URL for the datasource.
|
||||
* @property searchurl
|
||||
* @type String
|
||||
*/
|
||||
user_selector.prototype.searchurl = null;
|
||||
|
||||
/**
|
||||
* The datasource used to fetch lists of users from Moodle.
|
||||
* @property datasource
|
||||
@ -199,6 +216,7 @@ user_selector.prototype.get_search_text = function() {
|
||||
*/
|
||||
user_selector.prototype.send_query = function() {
|
||||
var value = this.get_search_text();
|
||||
this.searchfield.className = '';
|
||||
if (this.lastsearch == value) {
|
||||
return;
|
||||
}
|
||||
@ -226,6 +244,15 @@ user_selector.prototype.handle_response = function(request, data) {
|
||||
*/
|
||||
user_selector.prototype.handle_failure = function() {
|
||||
this.listbox.style.background = '';
|
||||
this.searchfield.className = 'error';
|
||||
|
||||
// If we are in developer debug mode, output a link to help debug the failure.
|
||||
if (moodle_cfg.developerdebug) {
|
||||
var link = document.createElement('a');
|
||||
link.href = this.searchurl + this.get_search_text();
|
||||
link.appendChild(document.createTextNode('Ajax call failed. Click here to try the search call directly.'))
|
||||
this.searchfield.parentNode.appendChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,10 +263,10 @@ user_selector.prototype.is_selection_empty = function() {
|
||||
for (i = 0; i < options.length; i++) {
|
||||
var option = options[i];
|
||||
if (option.selected) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -283,8 +310,14 @@ user_selector.prototype.output_options = function(data) {
|
||||
|
||||
// Output each optgroup.
|
||||
this.onlyoption = null;
|
||||
var nogroups = true;
|
||||
for (groupname in results) {
|
||||
this.output_group(groupname, results[groupname], false);
|
||||
nogroups = false;
|
||||
}
|
||||
|
||||
if (nogroups) {
|
||||
this.output_group(this.strnomatchingusers, {}, false)
|
||||
}
|
||||
|
||||
// If there was only one option matching the search results, select it.
|
||||
@ -343,7 +376,7 @@ user_selector.prototype.output_group = function(groupname, users, select) {
|
||||
var option = document.createElement('option');
|
||||
option.disabled = 'disabled';
|
||||
option.appendChild(document.createTextNode('\u00A0'));
|
||||
optgroup.appendchild(option);
|
||||
optgroup.appendChild(option);
|
||||
}
|
||||
this.listbox.appendChild(optgroup);
|
||||
}
|
||||
|
@ -34,7 +34,6 @@ class test_user_selector extends user_selector_base {
|
||||
$options['file'] = 'user/selector/test.php';
|
||||
return $options;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($justdefineclass) {
|
||||
@ -46,7 +45,7 @@ require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
|
||||
print_header();
|
||||
|
||||
$userselector = new test_user_selector('myuserselector');
|
||||
$userselector->set_multiselect(false);
|
||||
//$userselector->set_multiselect(false);
|
||||
|
||||
$users = $userselector->get_selected_users();
|
||||
if (!empty($users)) {
|
||||
@ -58,14 +57,14 @@ if (!empty($users)) {
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
echo '<form action="test.php"><div><label for="myuserselector">Select users</label>';
|
||||
echo '<form action="test.php"><div style="width: 30em;"><label for="myuserselector">Select users</label>';
|
||||
$userselector->display();
|
||||
echo '<p><input type="submit" id="submitbutton" value="Submit" /></p>';
|
||||
echo '</div></form>';
|
||||
|
||||
echo '<script type="text/javascript">
|
||||
function selection_change(isempty) {
|
||||
document.getElementById("submitbutton").disabled = !isempty;
|
||||
document.getElementById("submitbutton").disabled = isempty;
|
||||
}
|
||||
user_selector.get("myuserselector").subscribe("selectionchanged", selection_change);
|
||||
</script>';
|
||||
|
Loading…
x
Reference in New Issue
Block a user