From 1ea118e4bd88d846c21c5a5ac21984337218fb3e Mon Sep 17 00:00:00 2001 From: tjhunt Date: Mon, 8 Sep 2008 07:01:41 +0000 Subject: [PATCH] MDL-16343 Report showing, for a given capability, how it is set in the definition of each role, and everywhere that it is overridden. --- admin/report/capability/index.php | 221 +++++++++++++++++++++++++++++ admin/report/capability/script.js | 69 +++++++++ lang/en_utf8/report_capability.php | 14 ++ lib/weblib.php | 27 +++- theme/standard/styles_layout.css | 23 +++ 5 files changed, 352 insertions(+), 2 deletions(-) create mode 100644 admin/report/capability/index.php create mode 100644 admin/report/capability/script.js create mode 100644 lang/en_utf8/report_capability.php diff --git a/admin/report/capability/index.php b/admin/report/capability/index.php new file mode 100644 index 00000000000..7877c5bcf19 --- /dev/null +++ b/admin/report/capability/index.php @@ -0,0 +1,221 @@ +libdir.'/adminlib.php'); + +// Check permissions. +require_login(); +$systemcontext = get_context_instance(CONTEXT_SYSTEM); +require_capability('moodle/role:manage', $systemcontext); + +// Get URL parameters. +$capability = optional_param('capability', '', PARAM_CAPABILITY); +$roleids = optional_param('roles', array('0'), PARAM_INTEGER); + +// Clean the passed in list of role ids. If 'All' selected as an option, or +// if none were selected, do all roles. +$allroles = get_all_roles(); +$cleanedroleids = array(); +foreach ($roleids as $roleid) { + if ($roleid == 0) { + $cleanedroleids = array_keys($allroles); + break; + } + if (array_key_exists($roleid, $allroles)) { + $cleanedroleids[] = $roleid; + } +} +if (empty($cleanedroleids)) { + $cleanedroleids = array_keys($allroles); +} + +// Include the required JavaScript. +require_js(array('yui_yahoo','yui_event')); +require_js($CFG->wwwroot . '/admin/report/capability/script.js'); + +// Log. +add_to_log(SITEID, "admin", "report capability", "report/capability/index.php?capability=$capability", $capability); + +// Print the header. +admin_externalpage_setup('reportcapability'); +$strtitle = get_string('capabilityreport', 'report_capability'); +admin_externalpage_print_header(); + +// Prepare the list of capabilites to choose from +$allcapabilities = fetch_context_capabilities($systemcontext); +$capabilitychoices = array(); +foreach ($allcapabilities as $cap) { + $capabilitychoices[$cap->name] = $cap->name . ': ' . get_capability_string($cap->name); +} + +// Prepare the list of roles to choose from +$rolechoices = array('0' => get_string('all')); +foreach ($allroles as $role) { + $rolechoices[$role->id] = $role->name; +} +if (count($cleanedroleids) == count($allroles)) { + // Select 'All', rather than each role individually. + $selectedroleids = array('0'); +} else { + $selectedroleids = $cleanedroleids; +} + +// Print the settings form. +print_box_start('generalbox boxwidthwide boxaligncenter centerpara'); +echo '
'; +print_heading(get_string('reportsettings', 'report_capability')); +echo '

', get_string('intro', 'report_capability') , '

'; +echo '

'; +choose_from_menu($capabilitychoices, 'capability', $capability, 'choose', '', '', false, false, 0, '', true); +echo '

'; +choose_from_menu($rolechoices, 'roles[]', $selectedroleids, '', '', '', false, false, 0, '', true, true); +echo '

'; +echo ''; +echo ''; +echo '
'; +print_box_end(); + +// If we have a capability, generate the report. +if ($capability) { + + // Work out the bits needed for the SQL WHERE clauses. + $params = array($capability); + $sqlroletest = ''; + if (count($cleanedroleids) != count($allroles)) { + list($sqlroletest, $roleparams) = $DB->get_in_or_equal($cleanedroleids); + $params = array_merge($params, $roleparams); + $sqlroletest = 'AND roleid ' . $sqlroletest; + } + + // Get all the role_capabilities rows for this capability - that is, all + // role definitions, and all role overrides. + $rolecaps = $DB->get_records_sql(" + SELECT id, roleid, contextid, permission + FROM {role_capabilities} + WHERE capability = ? $sqlroletest", $params); + + // In order to display a nice tree of contexts, we need to get all the + // ancestors of all the contexts in the query we just did. + $relevantpaths = $DB->get_records_sql_menu(" + SELECT DISTINCT con.path, 1 + FROM {context} con JOIN {role_capabilities} rc ON rc.contextid = con.id + WHERE capability = ? $sqlroletest", $params); + $requiredcontexts = array(); + foreach ($relevantpaths as $path => $notused) { + $requiredcontexts = array_merge($requiredcontexts, explode('/', trim($path, '/'))); + } + $requiredcontexts = array_unique($requiredcontexts); + + // Now load those contexts. + list($sqlcontexttest, $contextparams) = $DB->get_in_or_equal($requiredcontexts); + $contexts = $DB->get_records_select('context', 'id ' . $sqlcontexttest, $contextparams); + + // Prepare some empty arrays to hold the data we are about to compute. + foreach ($contexts as $conid => $con) { + $contexts[$conid]->children = array(); + $contexts[$conid]->rolecapabilites = array(); + } + + // Put the contexts into a tree structure. + foreach ($contexts as $conid => $con) { + $contexts[$conid]->children = array(); + $parentcontextid = get_parent_contextid($con); + if ($parentcontextid) { + $contexts[$parentcontextid]->children[] = $conid; + } + } + + // Put the role capabilites into the context tree. + foreach ($rolecaps as $rolecap) { + $contexts[$rolecap->contextid]->rolecapabilites[$rolecap->roleid] = $rolecap->permission; + } + + // Fill in any missing rolecaps for the system context. + foreach ($cleanedroleids as $roleid) { + if (!isset($contexts[$systemcontext->id]->rolecapabilites[$roleid])) { + $contexts[$systemcontext->id]->rolecapabilites[$roleid] = CAP_INHERIT; + } + } + + // Print the report heading. + print_heading(get_string('reportforcapability', 'report_capability', get_capability_string($capability))); + if (count($cleanedroleids) != count($allroles)) { + $rolenames = array(); + foreach ($cleanedroleids as $roleid) { + $rolenames[] = $allroles[$roleid]->name; + } + echo '

', get_string('forroles', 'report_capability', implode(', ', $rolenames)), '

'; + } + + // Now, recursively print the contexts, and the role information. + print_report_tree($systemcontext->id, $contexts, $allroles); +} + +// Footer. +admin_externalpage_print_footer(); + +function print_report_tree($contextid, $contexts, $allroles) { + global $CFG; + + // Array for holding lang strings. + static $strpermissions = null; + if (is_null($strpermissions)) { + $strpermissions = array( + CAP_INHERIT => get_string('notset','role'), + CAP_ALLOW => get_string('allow','role'), + CAP_PREVENT => get_string('prevent','role'), + CAP_PROHIBIT => get_string('prohibit','role') + ); + } + + // Start the list item, and print the context name as a link to the place to + // make changes. + if ($contextid == get_system_context()->id) { + $url = $CFG->wwwroot . '/admin/roles/manage.php'; + $title = get_string('changeroles', 'report_capability'); + } else { + $url = $CFG->wwwroot . '/admin/roles/override.php?contextid=' . $contextid; + $title = get_string('changeoverrides', 'report_capability'); + } + echo '

', print_context_name($contexts[$contextid]), '

'; + + // If there are any role overrides here, print them. + if (!empty($contexts[$contextid]->rolecapabilites)) { + $rowcounter = 0; + echo ''; + foreach ($allroles as $role) { + if (isset($contexts[$contextid]->rolecapabilites[$role->id])) { + $permission = $contexts[$contextid]->rolecapabilites[$role->id]; + echo ''; + $rowcounter++; + } + } + echo '
', $role->name, + '' . $strpermissions[$permission] . '
'; + } + + // After we have done the site context, change the string for CAP_INHERIT + // from 'notset' to 'inherit'. + $strpermissions[CAP_INHERIT] = get_string('inherit','role'); + + // If there are any child contexts, print them recursively. + if (!empty($contexts[$contextid]->children)) { + echo ''; + } +} + +?> diff --git a/admin/report/capability/script.js b/admin/report/capability/script.js new file mode 100644 index 00000000000..429bc92a871 --- /dev/null +++ b/admin/report/capability/script.js @@ -0,0 +1,69 @@ +capability_report = { + select: null, + input: null, + button: null, + + cap_filter_init: function(strsearch) { + // Find the form controls. + capability_report.select = document.getElementById('menucapability'); + capability_report.button = document.getElementById('settingssubmit'); + + // Create a div to hold the search UI. + var div = document.createElement('div'); + div.id = 'capabilitysearchui'; + + // Find the capability search input. + var input = document.createElement('input'); + input.type = 'text'; + input.id = 'capabilitysearch'; + capability_report.input = input; + + // Create a label for the search input. + var label = document.createElement('label'); + label.htmlFor = input.id; + label.appendChild(document.createTextNode(strsearch + ' ')); + + // Tie it all together + div.appendChild(label); + div.appendChild(input); + capability_report.select.parentNode.insertBefore(div, capability_report.select); + YAHOO.util.Event.addListener(input, 'keyup', capability_report.cap_filter_change); + YAHOO.util.Event.addListener(capability_report.select, 'change', capability_report.validate); + capability_report.select.options[0].style.display = 'none'; + capability_report.validate(); + }, + + cap_filter_change: function() { + var filtertext = capability_report.input.value; + var options = capability_report.select.options; + var onlycapability = -1; + for (var i = 1; i < options.length; i++) { + if (options[i].text.indexOf(filtertext) >= 0) { + options[i].disabled = false; + options[i].style.display = 'block'; + if (onlycapability == -1) { + onlycapability = i; + } else { + onlycapability = -2; + } + } else { + options[i].disabled = true; + options[i].selected = false; + options[i].style.display = 'none'; + } + } + if (onlycapability >= 0) { + options[onlycapability].selected = true; + } + if (onlycapability == -1) { + capability_report.input.className = "error"; + } else { + capability_report.input.className = ""; + } + capability_report.validate(); + }, + + validate: function() { + capability_report.button.disabled = (capability_report.select.value == ''); + } +} \ No newline at end of file diff --git a/lang/en_utf8/report_capability.php b/lang/en_utf8/report_capability.php new file mode 100644 index 00000000000..25b3fb2d406 --- /dev/null +++ b/lang/en_utf8/report_capability.php @@ -0,0 +1,14 @@ + diff --git a/lib/weblib.php b/lib/weblib.php index 0f6ca41bdd0..c95d71a2735 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -780,9 +780,14 @@ function close_window($delay=0) { * @param int $tabindex if give, sets the tabindex attribute on the <select> element. Default none. * @param string $id value to use for the id attribute of the <select> element. If none is given, * then a suitable one is constructed. + * @param mixed $listbox if false, display as a dropdown menu. If true, display as a list box. + * By default, the list box will have a number of rows equal to min(10, count($options)), but if + * $listbox is an integer, that number is used for size instead. + * @param */ function choose_from_menu ($options, $name, $selected='', $nothing='choose', $script='', - $nothingvalue='0', $return=false, $disabled=false, $tabindex=0, $id='') { + $nothingvalue='0', $return=false, $disabled=false, $tabindex=0, + $id='', $listbox=false, $multiple=false) { if ($nothing == 'choose') { $nothing = get_string('choose') .'...'; @@ -804,6 +809,22 @@ function choose_from_menu ($options, $name, $selected='', $nothing='choose', $sc $id = str_replace(']', '', $id); } + if ($listbox) { + if (is_integer($listbox)) { + $size = $listbox; + } else { + $numchoices = count($options); + if ($nothing) { + $numchoices += 1; + } + $size = min(10, $numchoices); + } + $attributes .= ' size="' . $size . '"'; + if ($multiple) { + $attributes .= ' multiple="multiple"'; + } + } + $output = '