roles admin: Improve the usability of the assign roles interface - this is the first half of the work. Part of MDL-16993.

To do this, I found a way to clean up the method signatures of a couple of accesslib methods, so I did, hence the fact that this seems to touch some unrelated files.

Also, there is a nice new method in accesslib get_context_url, which gives you the natural URL for a context, so the course view page, or the user profile, etc.
This commit is contained in:
tjhunt 2008-10-30 06:26:18 +00:00
parent 2a5e1ba72f
commit 96f1a7a265
8 changed files with 173 additions and 78 deletions

View File

@ -3,7 +3,6 @@
<label for="extendperiod"><?php print_string('enrolperiod') ?></label> <?php choose_from_menu($periodmenu, "extendperiod", $defaultperiod, $unlimitedperiod); ?>
<label for="extendbase"><?php print_string('startingfrom') ?></label> <?php choose_from_menu($basemenu, "extendbase", 3, ""); ?>
<input type="hidden" name="previoussearch" value="<?php p($previoussearch) ?>" />
<input type="hidden" name="userid" value="<?php p($userid) ?>" />
<input type="hidden" name="courseid" value="<?php p($courseid) ?>" />
<input type="hidden" name="sesskey" value="<?php p(sesskey()) ?>" />

View File

@ -14,7 +14,6 @@
$remove = optional_param('remove', 0, PARAM_BOOL);
$showall = optional_param('showall', 0, PARAM_BOOL);
$searchtext = optional_param('searchtext', '', PARAM_RAW); // search string
$previoussearch = optional_param('previoussearch', 0, PARAM_BOOL);
$hidden = optional_param('hidden', 0, PARAM_BOOL); // whether this assignment is hidden
$extendperiod = optional_param('extendperiod', 0, PARAM_INT);
$extendbase = optional_param('extendbase', 0, PARAM_INT);
@ -23,9 +22,7 @@
$errors = array();
$previoussearch = ($searchtext != '') or ($previoussearch) ? 1:0;
$baseurl = 'assign.php?contextid='.$contextid;
$baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/role/assign.php?contextid=' . $contextid;
if (!empty($userid)) {
$baseurl .= '&amp;userid='.$userid;
}
@ -35,8 +32,9 @@
if (! $context = get_context_instance_by_id($contextid)) {
print_error('wrongcontextid', 'error');
}
$isfrontpage = $context->contextlevel == CONTEXT_COURSE && $context->instanceid == SITEID;
$contextname = print_context_name($context);
$inmeta = 0;
if ($context->contextlevel == CONTEXT_COURSE) {
@ -63,15 +61,14 @@
/// needed for tabs.php
$overridableroles = get_overridable_roles($context, 'name', ROLENAME_BOTH);
$assignableroles = get_assignable_roles($context, 'name', ROLENAME_BOTH);
$overridableroles = get_overridable_roles($context, ROLENAME_BOTH);
list($assignableroles, $assigncounts, $nameswithcounts) = get_assignable_roles($context, ROLENAME_BOTH, true);
/// Get some language strings
$strpotentialusers = get_string('potentialusers', 'role');
$strexistingusers = get_string('existingusers', 'role');
$straction = get_string('assignroles', 'role');
$strroletoassign = get_string('roletoassign', 'role');
$strsearch = get_string('search');
$strshowall = get_string('showall');
$strparticipants = get_string('participants');
@ -104,7 +101,7 @@
}
}
/// Make sure this user can assign that role
/// Make sure this user can assign this role
if ($roleid) {
if (!isset($assignableroles[$roleid])) {
@ -158,7 +155,6 @@
}
/// Process incoming role assignment
if ($frm = data_submitted()) {
@ -249,24 +245,20 @@
add_to_log($course->id, 'role', 'unassign', 'admin/roles/assign.php?contextid='.$context->id.'&roleid='.$roleid, $rolename, '', $USER->id);
} else if ($showall) {
$searchtext = '';
$previoussearch = 0;
}
}
if ($context->contextlevel==CONTEXT_COURSE and $context->instanceid == SITEID) {
if ($isfrontpage) {
print_heading_with_help(get_string('frontpageroles', 'admin'), 'assignroles');
} else {
print_heading_with_help(get_string('assignrolesin', 'role', print_context_name($context)), 'assignroles');
print_heading_with_help(get_string('assignrolesin', 'role', $contextname), 'assignroles');
}
if ($context->contextlevel==CONTEXT_SYSTEM) {
print_box(get_string('globalroleswarning', 'role'));
}
if ($roleid) { /// prints a form to swap roles
if ($roleid) {
/// Get all existing participants in this context.
// Why is this not done with get_users???
@ -383,12 +375,6 @@
$usercount = $DB->count_records_sql("$countfields $sql", $params);
}
echo '<div class="selector">';
$assignableroles = array('0'=>get_string('listallroles', 'role').'...') + $assignableroles;
popup_form("$CFG->wwwroot/$CFG->admin/roles/assign.php?userid=$userid&amp;courseid=$courseid&amp;contextid=$contextid&amp;roleid=",
$assignableroles, 'switchrole', $roleid, '', '', '', false, 'self', $strroletoassign);
echo '</div>';
print_simple_box_start('center');
include('assign.html');
print_simple_box_end();
@ -404,8 +390,18 @@
print_simple_box_end();
}
/// Print a form to swap roles, and a link back to the all roles list.
echo '<div class="backlink">';
popup_form($baseurl . '&amp;roleid=', $nameswithcounts, 'switchrole',
$roleid, '', '', '', false, 'self', get_string('assignanotherrole', 'role'));
echo '<p><a href="' . $baseurl . '">' . get_string('backtoallroles', 'role') . '</a></p>';
echo '</div>';
} else { // Print overview table
// Print instruction
print_heading(get_string('chooseroletoassign', 'role'), 'center', 3);
// sync metacourse enrolments if needed
if ($inmeta) {
sync_metacourse($course);
@ -413,15 +409,12 @@
// Get the names of role holders for roles with between 1 and MAX_USERS_TO_LIST_PER_ROLE users,
// and so determine whether to show the extra column.
$rolehodlercount = array();
$rolehodlernames = array();
$strmorethanten = get_string('morethan', 'role', MAX_USERS_TO_LIST_PER_ROLE);
$strmorethanmax = get_string('morethan', 'role', MAX_USERS_TO_LIST_PER_ROLE);
$showroleholders = false;
foreach ($assignableroles as $roleid => $rolename) {
$countusers = count_role_users($roleid, $context);
$rolehodlercount[$roleid] = $countusers;
$roleusers = '';
if (0 < $countusers && $countusers <= MAX_USERS_TO_LIST_PER_ROLE) {
if (0 < $assigncounts[$roleid] && $assigncounts[$roleid] <= MAX_USERS_TO_LIST_PER_ROLE) {
$roleusers = get_role_users($roleid, $context, false, 'u.id, u.lastname, u.firstname');
if (!empty($roleusers)) {
$strroleusers = array();
@ -431,8 +424,8 @@
$rolehodlernames[$roleid] = implode('<br />', $strroleusers);
$showroleholders = true;
}
} else if ($countusers > MAX_USERS_TO_LIST_PER_ROLE) {
$rolehodlernames[$roleid] = '<a href="'.$baseurl.'&amp;roleid='.$roleid.'">'.$strmorethanten.'</a>';
} else if ($assigncounts[$roleid] > MAX_USERS_TO_LIST_PER_ROLE) {
$rolehodlernames[$roleid] = '<a href="'.$baseurl.'&amp;roleid='.$roleid.'">'.$strmorethanmax.'</a>';
} else {
$rolehodlernames[$roleid] = '';
}
@ -443,18 +436,18 @@
$table->cellpadding = 5;
$table->cellspacing = 0;
$table->width = '60%';
$table->head = array(get_string('roles', 'role'), get_string('description'), get_string('users'));
$table->head = array(get_string('role'), get_string('description'), get_string('userswiththisrole', 'role'));
$table->wrap = array('nowrap', '', 'nowrap');
$table->align = array('right', 'left', 'center');
$table->align = array('left', 'left', 'center');
if ($showroleholders) {
$table->head[] = '';
$table->headspan = array(1, 1, 2);
$table->wrap[] = 'nowrap';
$table->align[] = 'left';
}
foreach ($assignableroles as $roleid => $rolename) {
$description = format_string($DB->get_field('role', 'description', array('id'=>$roleid)));
$row = array('<a href="'.$baseurl.'&amp;roleid='.$roleid.'">'.$rolename.'</a>',$description, $rolehodlercount[$roleid]);
$row = array('<a href="'.$baseurl.'&amp;roleid='.$roleid.'">'.$rolename.'</a>',$description, $assigncounts[$roleid]);
if ($showroleholders) {
$row[] = $rolehodlernames[$roleid];
}
@ -462,8 +455,12 @@
}
print_table($table);
if (!$isfrontpage && ($url = get_context_url($context))) {
echo '<div class="backlink"><a href="' . $url . '">' .
get_string('backto', '', $contextname) . '</a></div>';
}
}
print_footer($course);
?>

View File

@ -50,8 +50,8 @@
}
/// needed for tabs.php
$overridableroles = get_overridable_roles($context, 'name', ROLENAME_BOTH);
$assignableroles = get_assignable_roles($context, 'name', ROLENAME_BOTH);
$overridableroles = get_overridable_roles($context, ROLENAME_BOTH);
$assignableroles = get_assignable_roles($context, ROLENAME_BOTH);
/// Get some language strings

View File

@ -601,8 +601,7 @@ $xml_file = $CFG->dataroot."/temp/backup/".$backup_unique_code."/moodle.xml";
$info = restore_read_xml_info($xml_file);
// fix for MDL-9068, front page course is just a normal course
$siterolesarray = get_assignable_roles (get_context_instance(CONTEXT_COURSE, $course->id), "shortname", ROLENAME_ORIGINAL);
$siterolesnamearray = get_assignable_roles (get_context_instance(CONTEXT_COURSE, $course->id), "name", ROLENAME_ORIGINAL);
$siterolesarray = get_assignable_roles(get_context_instance(CONTEXT_COURSE, $course->id), ROLENAME_ORIGINALANDSHORT);
$allroles = $DB->get_records('role');
echo ('<table width="100%" class="restore-form-instances">');
@ -654,13 +653,9 @@ if ($info->backup_moodle_version < 2006092801) {
$roles = restore_read_xml_roles($xml_file);
if (!empty($roles->roles)) { // possible to have course with no roles
foreach ($siterolesarray as $siteroleid=>$siteroleshortname) {
$siteroleschoicearray[$siteroleid] = $siterolesnamearray[$siteroleid]." (". $siterolesarray[$siteroleid].")";
}
foreach ($roles->roles as $roleid=>$role) {
$mappableroles = $siteroleschoicearray;
$mappableroles = $siterolesarray;
echo ('<tr><td align="right">');
echo '<label for="menuroles_'.$roleid.'">'.format_string($role->name)." (".($role->shortname).")".'</label>';
@ -678,8 +673,8 @@ if ($info->backup_moodle_version < 2006092801) {
// no exact role found, let's try to match shortname
// this is useful in situations where basic roles differ slightly in definition
$matchrole = 0;
foreach ($siterolesarray as $siteroleid=>$siteroleshortname) {
if ($siteroleshortname == $role->shortname) {
foreach ($siterolesarray as $siteroleid => $notused) {
if ($siteroleshortname == $allroles[$siteroleid]->shortname) {
$matchrole = $siteroleid;
break;
}

View File

@ -67,7 +67,7 @@ class block_admin extends block_list {
if (has_capability('moodle/role:assign', $context)) {
$this->content->items[]='<a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.$context->id.'">'.get_string('assignroles', 'role').'</a>';
$this->content->icons[]='<img src="'.$CFG->pixpath.'/i/roles.gif" class="icon" alt="" />';
} else if (get_overridable_roles($context, 'name', ROLENAME_ORIGINAL)) {
} else if (get_overridable_roles($context, ROLENAME_ORIGINAL)) {
$this->content->items[]='<a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/roles/override.php?contextid='.$context->id.'">'.get_string('overridepermissions', 'role').'</a>';
$this->content->icons[]='<img src="'.$CFG->pixpath.'/i/roles.gif" class="icon" alt="" />';
}

View File

@ -7,10 +7,12 @@ $string['allow'] = 'Allow';
$string['allowassign'] = 'Allow role assignments';
$string['allowoverride'] = 'Allow role overrides';
$string['allsiteusers'] = 'All site users';
$string['assignanotherrole'] = 'Assign another role';
$string['assignroles'] = 'Assign roles';
$string['assignrolesin'] = 'Assign roles in $a';
$string['assignglobalroles'] = 'Assign system roles';
$string['assignmentcontext'] = 'Assignment context';
$string['backtoallroles'] = 'Back to the list of all roles';
$string['blog:create'] = 'Create new blog entries';
$string['blog:manageentries'] = 'Edit and manage entries';
$string['blog:manageofficialtags'] = 'Manage official tags';
@ -26,6 +28,7 @@ $string['category:create'] = 'Create categories';
$string['category:delete'] = 'Delete categories';
$string['category:update'] = 'Update categories';
$string['category:visibility'] = 'See hidden categories';
$string['chooseroletoassign'] = 'Please choose a role to assign';
$string['context'] = 'Context';
$string['course:activityvisibility'] = 'Hide/show activities';
$string['course:bulkmessaging'] = 'Send a message to many people';
@ -182,6 +185,7 @@ $string['user:viewdetails'] = 'View user profiles';
$string['user:viewhiddendetails'] = 'View hidden details of users';
$string['user:viewuseractivitiesreport'] = 'See user activity reports';
$string['userhashiddenassignments'] = 'This user has one or more hidden role assignments in this course';
$string['userswiththisrole'] = 'Users with role';
$string['userswithrole'] = 'All users with a role';
$string['viewrole'] = 'View role details';
$string['xuserswiththerole'] = 'Users with the role \"$a->role\"';

View File

@ -155,6 +155,7 @@ define('RISK_DATALOSS', 0x0020);
define('ROLENAME_ORIGINAL', 0);// the name as defined in the role definition
define('ROLENAME_ALIAS', 1); // the name as defined by a role alias
define('ROLENAME_BOTH', 2); // Both, like this: Role alias (Original)
define('ROLENAME_ORIGINALANDSHORT', 0); // the name as defined in the role definition and the shortname in brackets
$context_cache = array(); // Cache of all used context objects for performance (by level and instance)
$context_cache_id = array(); // Index to above cache by id
@ -3243,7 +3244,14 @@ function capabilities_cleanup($component, $newcapdef=NULL) {
/**
* prints human readable context identifier.
* Prints human readable context identifier.
*
* @param object $context the context.
* @param boolean $withprefix whether to prefix the name of the context with the
* type of context, e.g. User, Course, Forum, etc.
* @param boolean $short whether to user the short name of the thing. Only applies
* to course contexts
* @return string the human readable context name.
*/
function print_context_name($context, $withprefix = true, $short = false) {
global $DB;
@ -3299,14 +3307,13 @@ function print_context_name($context, $withprefix = true, $short = false) {
break;
case CONTEXT_MODULE: // 1 to 1 to course
if ($cm = $DB->get_record('course_modules', array('id'=>$context->instanceid))) {
if ($module = $DB->get_record('modules', array('id'=>$cm->module))) {
if ($mod = $DB->get_record($module->name, array('id'=>$cm->instance))) {
if ($withprefix){
$name = get_string('activitymodule').': ';
}
$name .= $mod->name;
if ($cm = $DB->get_record_sql('SELECT cm.*, md.name AS modname FROM {course_modules} cm ' .
'JOIN {modules} md ON md.id = cm.module WHERE cm.id = ?', array($context->instanceid))) {
if ($mod = $DB->get_record($cm->modname, array('id' => $cm->instance))) {
if ($withprefix){
$name = get_string('modulename', $cm->modname).': ';
}
$name .= $mod->name;
}
}
break;
@ -3331,11 +3338,60 @@ function print_context_name($context, $withprefix = true, $short = false) {
default:
error ('This is an unknown context (' . $context->contextlevel . ') in print_context_name!');
return false;
}
return $name;
}
/**
* Get a URL for a context, if there is a natural one. For example, for
* CONTEXT_COURSE, this is the course page. For CONTEXT_USER it is the
* user profile page.
*
* First three parameters as for
* @param object $context the context.
* @return string a suitable URL, or blank.
*/
function get_context_url($context) {
global $CFG, $COURSE, $DB;
$url = '';
switch ($context->contextlevel) {
case CONTEXT_USER:
$url = $CFG->wwwroot . '/user/view.php?id=' . $context->instanceid;
if ($COURSE->id != SITEID) {
$url .= '&amp;courseid=' . $COURSE->id;
}
break;
case CONTEXT_COURSECAT: // Coursecat -> coursecat or site
$url = $CFG->wwwroot . '/course/category.php?id=' . $context->instanceid;
break;
case CONTEXT_COURSE: // 1 to 1 to course cat
if ($context->instanceid == SITEID) {
$url = $CFG->wwwroot . '/';
} else {
$url = $CFG->wwwroot . '/course/view.php?id=' . $context->instanceid;
}
break;
case CONTEXT_MODULE: // 1 to 1 to course
if ($modname = $DB->get_field_sql('SELECT md.name AS modname FROM {course_modules} cm ' .
'JOIN {modules} md ON md.id = cm.module WHERE cm.id = ?', array($context->instanceid))) {
$url = $CFG->wwwroot . '/mod/' . $modname . '/view.php?id=' . $context->instanceid;
}
break;
case CONTEXT_SYSTEM:
case CONTEXT_GROUP:
case CONTEXT_BLOCK:
default:
$url = '';
}
return $url;
}
/**
* Extracts the relevant capabilities given a contextid.
@ -4001,12 +4057,16 @@ function allow_assign($sroleid, $troleid) {
/**
* Gets a list of roles that this user can assign in this context
* @param object $context
* @param string $field
* @param int $rolenamedisplay
* @return array
* @param object $context the context.
* @param string $field the field to return for each role.
* @param int $rolenamedisplay the type of role name to display. One of the
* ROLENAME_X constants. Default ROLENAME_ALIAS.
* @param $withusercounts if true, count the number of users with each role.
* @return array if $withusercounts is false, then an array $roleid => $rolename.
* if $withusercounts is true, returns a list of three arrays,
* $rolenames, $rolecounts, and $nameswithcounts.
*/
function get_assignable_roles($context, $field='name', $rolenamedisplay=ROLENAME_ALIAS) {
function get_assignable_roles($context, $rolenamedisplay = ROLENAME_ALIAS, $withusercounts = false) {
global $USER, $DB;
if (!has_capability('moodle/role:assign', $context)) {
@ -4017,37 +4077,69 @@ function get_assignable_roles($context, $field='name', $rolenamedisplay=ROLENAME
$parents[] = $context->id;
$contexts = implode(',' , $parents);
if (!$roles = $DB->get_records_sql("SELECT ro.*
FROM {role} ro,
(
$params = array();
$extrafields = '';
if ($rolenamedisplay == ROLENAME_ORIGINALANDSHORT) {
$extrafields .= ', ro.shortname';
}
if ($withusercounts) {
$countjoinandgroupby =
"JOIN
GROUP BY ro.id, ro.name$extrafields";
$extrafields = ', (SELECT count(u.id)
FROM {role_assignments} cra JOIN {user} u ON cra.userid = u.id
WHERE cra.roleid = ro.id AND cra.contextid = :conid AND u.deleted = 0
) AS usercount';
$params['conid'] = $context->id;
}
$params['userid'] = $USER->id;
if (!$roles = $DB->get_records_sql("SELECT ro.id, ro.name$extrafields
FROM {role} ro
JOIN (
SELECT DISTINCT r.id
FROM {role} r,
{role_assignments} ra,
{role_allow_assign} raa
WHERE ra.userid = :userid AND ra.contextid IN ($contexts)
AND raa.roleid = ra.roleid AND r.id = raa.allowassign
) inline_view
WHERE ro.id = inline_view.id
ORDER BY ro.sortorder ASC", array('userid'=>$USER->id))) {
) inline_view ON ro.id = inline_view.id
ORDER BY ro.sortorder ASC", $params)) {
return array();
}
$rolenames = array();
foreach ($roles as $role) {
$roles[$role->id] = $role->$field;
$rolenames[$role->id] = $role->name;
if ($rolenamedisplay == ROLENAME_ORIGINALANDSHORT) {
$rolenames[$role->id] .= ' (' . $role->shortname . ')';
}
}
if ($rolenamedisplay != ROLENAME_ORIGINALANDSHORT) {
$rolenames = role_fix_names($rolenames, $context, $rolenamedisplay);
}
return role_fix_names($roles, $context, $rolenamedisplay);
if (!$withusercounts) {
return $rolenames;
}
$rolecounts = array();
$nameswithcounts = array();
foreach ($roles as $role) {
$nameswithcounts[$role->id] = $rolenames[$role->id] . ' (' . $roles[$role->id]->usercount . ')';
$rolecounts[$role->id] = $roles[$role->id]->usercount;
}
return array($rolenames, $rolecounts, $nameswithcounts);
}
/**
* Gets a list of roles that this user can assign in this context, for the switchrole menu
*
* @param object $context
* @param string $field
* @param int $rolenamedisplay
* @return array
*/
function get_assignable_roles_for_switchrole($context, $field='name', $rolenamedisplay=ROLENAME_ALIAS) {
function get_assignable_roles_for_switchrole($context) {
global $USER, $DB;
if (!has_capability('moodle/role:assign', $context)) {
@ -4075,11 +4167,11 @@ function get_assignable_roles_for_switchrole($context, $field='name', $rolenamed
return array();
}
$rolenames = array();
foreach ($roles as $role) {
$roles[$role->id] = $role->$field;
$rolenames[$role->id] = $role->name;
}
return role_fix_names($roles, $context, $rolenamedisplay);
return role_fix_names($rolenames, $context, ROLENAME_ALIAS);
}
/**
@ -4089,7 +4181,7 @@ function get_assignable_roles_for_switchrole($context, $field='name', $rolenamed
* @param int $rolenamedisplay
* @return array
*/
function get_overridable_roles($context, $field='name', $rolenamedisplay=ROLENAME_ALIAS) {
function get_overridable_roles($context, $rolenamedisplay=ROLENAME_ALIAS) {
global $USER, $DB;
if (!has_capability('moodle/role:override', $context) and !has_capability('moodle/role:safeoverride', $context)) {
@ -4116,7 +4208,7 @@ function get_overridable_roles($context, $field='name', $rolenamedisplay=ROLENAM
}
foreach ($roles as $role) {
$roles[$role->id] = $role->$field;
$roles[$role->id] = $role->name;
}
return role_fix_names($roles, $context, $rolenamedisplay);

View File

@ -1040,6 +1040,14 @@ body#admin-modules table.generaltable td.c0
margin-right:auto;
}
#admin-roles-manage .backlink,
#admin-roles-assign .backlink,
#admin-roles-override .backlink {
text-align: right;
width: 90%;
margin: 2em auto 1em;
}
#admin-roles-manage table.rolecap,
#admin-roles-override table.rolecap {
margin-left:auto;