# This patch file was generated by NetBeans IDE
# This patch can be applied using context Tools: Apply Diff Patch action on respective folder.
# It uses platform neutral UTF-8 encoding.
# Above lines and this line are ignored by the patching process.
Index: moodle/admin/roles/permissions.php
--- moodle/admin/roles/permissions.php No Base Revision
+++ moodle/admin/roles/permissions.php Locally New
@@ -0,0 +1,310 @@
+<?php  //$Id:$
+
+require('../../config.php');
+require_once("$CFG->libdir/adminlib.php");
+require_once("permissions_forms.php");
+
+$contextid  = required_param('contextid',PARAM_INT);
+$roleid     = optional_param('roleid', 0, PARAM_INT);
+$capability = optional_param('capability', false, PARAM_CAPABILITY);
+$confirm    = optional_param('confirm', 0, PARAM_BOOL);
+
+$prevent    = optional_param('prevent', 0, PARAM_BOOL);
+$allow      = optional_param('allow', 0, PARAM_BOOL);
+$unprohibit = optional_param('unprohibit', 0, PARAM_BOOL);
+$prohibit   = optional_param('prohibit', 0, PARAM_BOOL);
+
+if (!$context = get_context_instance_by_id($contextid)) {
+    print_error('unknowncontext');
+}
+
+require_capability('moodle/role:review', $context);
+
+if (empty($CFG->simplifiedroles)) {
+    die;
+}
+
+/// security first
+$infrontapge = false;
+$cm = null;
+if ($context->contextlevel == CONTEXT_USER) {
+    $userid   = $context->instanceid;
+    $courseid = optional_param('courseid', SITEID, PARAM_INT); // needed for user tabs
+} else {
+    $userid = 0;
+    if ($context->contextlevel == CONTEXT_SYSTEM) {
+        $courseid = SITEID;
+    } else if ($context->contextlevel == CONTEXT_COURSECAT) {
+        $courseid = SITEID;
+    } else if ($context->contextlevel == CONTEXT_COURSE) {
+        $courseid = $context->instanceid;
+        if ($courseid == SITEID) {
+            $infrontapge = true;
+        }
+    } else if ($context->contextlevel == CONTEXT_MODULE) {
+        if (!$cm = get_record('course_modules', 'id', $context->instanceid)) {
+            print_error('invalidcoursemodule');
+        }
+        $courseid = $cm->course;
+    } else if ($context->contextlevel == CONTEXT_BLOCK) {
+        //TODO: grrr
+        die();
+    } else {
+        //error
+        die();
+    }
+}
+
+if (!$course = get_record('course', 'id', $courseid)) {
+    print_error('invalidcourse', 'error');
+}
+
+require_login($course, false, $cm);
+
+/// These are needed early because of tabs.php
+$assignableroles = get_assignable_roles($context, 'name', ROLENAME_BOTH);
+$overridableroles = get_overridable_roles($context, 'name', ROLENAME_BOTH);
+
+if ($capability) {
+    $capability = get_record('capabilities', 'name', $capability);
+}
+
+$allowoverrides     = has_capability('moodle/role:override', $context);
+$allowsafeoverrides = has_capability('moodle/role:safeoverride', $context);
+
+$contextname = print_context_name($context);
+$title = get_string('permissionsin', 'role', $contextname); // TODO: localise (grrr)
+
+/// Print the header and tabs
+if ($context->contextlevel == CONTEXT_USER) {
+    $userid = $context->instanceid;
+    $user = get_record('user', 'id', $userid);
+    $fullname = fullname($user, has_capability('moodle/site:viewfullnames', $context));
+
+    /// course header
+    $navlinks = array();
+    if ($courseid != SITEID) {
+        if (has_capability('moodle/course:viewparticipants', get_context_instance(CONTEXT_COURSE, $courseid))) {
+            $navlinks[] = array('name' => get_string('participants'), 'link' => "$CFG->wwwroot/user/index.php?id=$courseid", 'type' => 'misc');
+        }
+        $navlinks[] = array('name' => $fullname, 'link' => "$CFG->wwwroot/user/view.php?id=$userid&amp;course=$courseid", 'type' => 'misc');
+        $navlinks[] = array('name' => $straction, 'link' => null, 'type' => 'misc');
+        $navigation = build_navigation($navlinks);
+
+        print_header($title, $fullname, $navigation, '', '', true, '&nbsp;', navmenu($course));
+
+    /// site header
+    } else {
+        $navlinks[] = array('name' => $fullname, 'link' => "$CFG->wwwroot/user/view.php?id=$userid&amp;course=$courseid", 'type' => 'misc');
+        $navlinks[] = array('name' => $straction, 'link' => null, 'type' => 'misc');
+        $navigation = build_navigation($navlinks);
+        print_header($title, $course->fullname, $navigation, '', '', true, '&nbsp;', navmenu($course));
+    }
+
+    $showroles = 1;
+    $currenttab = 'review';
+    include($CFG->dirroot.'/user/tabs.php');
+
+} else if ($context->contextlevel == CONTEXT_SYSTEM) {
+    admin_externalpage_setup('reviewpremissions', '', array('contextid' => $contextid, 'roleid' => $roleid));
+    admin_externalpage_print_header();
+
+} else if ($infrontapge) {
+    $courseid = SITEID;
+    $course = $SITE;
+    admin_externalpage_setup('reviewpremissions', '', array('contextid' => $contextid, 'roleid' => $roleid));
+    admin_externalpage_print_header();
+    $currenttab = 'review';
+    include('tabs.php');
+
+} else {
+    $currenttab = 'review';
+    include('tabs.php');
+}
+
+print_heading($title);
+
+// handle confirmations and actions
+if ($prevent and isset($overridableroles[$roleid]) and $capability) {
+    if ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability))) {
+        if ($confirm and data_submitted() and confirm_sesskey()) {
+            simple_capability_prevent($roleid, $context, $capability->name);
+        } else {
+            $optionsyes = array('contextid'=>$context->id, 'roleid'=>$roleid, 'capability'=>$capability->name, 'prevent'=>1, 'sesskey'=>sesskey(), 'confirm'=>1);
+            $optionsno  = array('contextid'=>$contextid);
+            $a = (object)array('cap'=>get_capability_docs_link($capability)." ($capability->name)", 'role'=>$overridableroles[$roleid], 'context'=>$contextname);
+            $message = get_string('confirmroleprevent', 'role', $a);
+            notice_yesno($message, 'permissions.php', 'permissions.php', $optionsyes, $optionsno, 'post', 'get');
+            print_footer();
+            die;
+        }
+    }
+}
+
+if ($unprohibit and isset($overridableroles[$roleid]) and $capability) {
+    if ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability))) {
+        if ($confirm and data_submitted() and confirm_sesskey()) {
+            simple_capability_unprohibit($roleid, $context, $capability->name);
+        } else {
+            $optionsyes = array('contextid'=>$context->id, 'roleid'=>$roleid, 'capability'=>$capability->name, 'unprohibit'=>1, 'sesskey'=>sesskey(), 'confirm'=>1);
+            $optionsno  = array('contextid'=>$contextid);
+            $a = (object)array('cap'=>get_capability_docs_link($capability)." ($capability->name)", 'role'=>$overridableroles[$roleid], 'context'=>$contextname);
+            $message = get_string('confirmroleunprohibit', 'role', $a); //TODO: localise grrr
+            notice_yesno($message, 'permissions.php', 'permissions.php', $optionsyes, $optionsno, 'post', 'get');
+            print_footer();
+            die;
+        }
+    }
+}
+
+if ($allow and $capability) {
+    if ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability))) {
+        $mform = new role_allow_form(null, array($context, $capability, $overridableroles));
+        if ($mform->is_cancelled()) {
+            // nothing
+
+        } else if ($data = $mform->get_data()) {
+            $roleid = $data->roleid;
+            if (isset($overridableroles[$roleid])) {
+                simple_capability_allow($roleid, $context, $capability->name);
+            }
+
+        } else {
+            $a = (object)array('cap'=>get_capability_docs_link($capability)." ($capability->name)", 'context'=>$contextname);
+            $message = get_string('roleallowinfo', 'role', $a);  // TODO: localise grrr
+            print_box($message);
+            $mform->display();
+            print_footer();
+            die;
+        }
+    }
+}
+
+if ($prohibit and $capability) {
+    if ($allowoverrides or ($allowsafeoverrides and is_safe_capability($capability))) {
+        $mform = new role_prohibit_form(null, array($context, $capability, $overridableroles));
+        if ($mform->is_cancelled()) {
+            // nothing
+
+        } else if ($data = $mform->get_data()) {
+            $roleid = $data->roleid;
+            if (isset($overridableroles[$roleid])) {
+                simple_capability_prohibit($roleid, $context, $capability->name);
+            }
+
+        } else {
+            $a = (object)array('cap'=>get_capability_docs_link($capability)." ($capability->name)", 'context'=>$contextname);
+            $message = get_string('roleprohibitinfo', 'role', $a);  // TODO: localise grrr
+            print_box($message);
+            $mform->display();
+            print_footer();
+            die;
+        }
+    }
+}
+
+// Print overview table
+$table = new object();
+$table->tablealign = 'center';
+$table->width      = '80%';
+$table->head       = array(get_string('capability', 'role'), get_string('risks', 'role'), get_string('neededroles', 'role'), get_string('prohibitedroles', 'role')); //TODO: localise (grrr)
+$table->wrap       = array('nowrap', 'nowrap','', '');
+$table->align      = array('left', 'center', 'left', 'left');
+$table->class      = 'generaltable rolecap';
+
+$capabilities = fetch_context_capabilities($context);
+
+$roles = get_records('role', '', '', 'sortorder DESC');
+foreach ($roles as $roleid=>$role) {
+    $roles[$roleid] = $role->name;
+}
+$roles = role_fix_names($roles, $context);
+
+foreach ($capabilities as $capid => $cap) {
+    list($needed, $forbidden, $adminroles) = get_roles_with_cap_in_context($context, $cap->name, true);
+    $neededroles    = array();
+    $forbiddenroles = array();
+    $allowable      = $overridableroles;
+    $forbitable    = $overridableroles;
+    foreach ($neededroles as $id=>$unused) {
+        unset($allowable[$id]);
+    }
+    foreach ($forbidden as $id=>$unused) {
+        unset($allowable[$id]);
+        unset($forbitable[$id]);
+    }
+
+    foreach ($roles as $id=>$name) {
+        if (isset($needed[$id])) {
+            $neededroles[$id] = $roles[$id];
+            if (!isset($adminroles[$id]) and isset($overridableroles[$id]) and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($cap)))) {
+                $preventurl = "permissions.php?contextid=$contextid&amp;roleid=$id&amp;capability=$cap->name&amp;prevent=1";
+                $img = '<img src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'.get_string('prevent', 'role').'" />';
+                $neededroles[$id] .= ' <a href="'.$preventurl.'">'.$img.'</a>';
+            }
+        }
+    }
+    $neededroles = implode(', ', $neededroles);
+    foreach ($roles as $id=>$name) {
+        if (isset($forbidden[$id])  and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($cap)))) {
+            $forbiddenroles[$id] = $roles[$id];
+            if (isset($overridableroles[$id]) and prohibit_is_removable($id, $context, $cap->name)) {
+                $unprohibiturl = "permissions.php?contextid=$contextid&amp;roleid=$id&amp;capability=$cap->name&amp;unprohibit=1";
+                $img = '<img src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="'.get_string('unprohibit', 'role').'" />'; // TODO: localise grrr
+                $forbiddenroles[$id] .= ' <a href="'.$unprohibiturl.'">'.$img.'</a>';
+            }
+        }
+    }
+    $forbiddenroles = implode(', ', $forbiddenroles);
+
+    if ($allowable and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($cap)))) {
+        $allowurl = "permissions.php?contextid=$contextid&amp;capability=$cap->name&amp;allow=1";
+        $img = '<img src="'.$CFG->pixpath.'/t/add.gif" class="iconsmall" alt="'.get_string('allow', 'role').'" />'; // TODO: localise grrr
+        $neededroles .= '<div class="allowmore"><a href="'.$allowurl.'">'.$img.'</a></div>';
+    }
+
+    if ($forbitable and ($allowoverrides or ($allowsafeoverrides and is_safe_capability($cap)))) {
+        $prohibiturl = "permissions.php?contextid=$contextid&amp;capability=$cap->name&amp;prohibit=1";
+        $img = '<img src="'.$CFG->pixpath.'/t/add.gif" class="iconsmall" alt="'.get_string('prohibit', 'role').'" />'; // TODO: localise grrr
+        $forbiddenroles .= '<div class="prohibitmore"><a href="'.$prohibiturl.'">'.$img.'</a></div>';
+    }
+
+    $capname = '<span class="cap-desc">'.get_capability_docs_link($cap).'<span class="cap-name">'.$cap->name.'</span></span>';
+
+    $risks = get_risks($cap);
+
+    $row = array($capname, $risks, $neededroles, $forbiddenroles);
+    $table->data[] = $row;
+}
+
+print_table($table);
+
+print_footer($course);
+
+/// some functions
+
+function get_risks($capability) {
+    global $CFG;
+
+    static $icons = array();
+
+    $allrisks = get_all_risks();
+    $risksurl = get_docs_url(s(get_string('risks', 'role')));
+
+    $return = '';
+
+    foreach ($allrisks as $type=>$risk) {
+        if ($risk & (int)$capability->riskbitmask) {
+            if (!isset($icons[$type])) {
+
+                $iconurl = $CFG->pixpath . '/i/' . str_replace('risk', 'risk_', $type) . '.gif';
+                $icons[$type] = link_to_popup_window($risksurl, 'docspopup',
+                                '<img src="' . $iconurl . '" alt="' . get_string($type . 'short', 'admin') . '" />',
+                                0, 0, get_string($type, 'admin'), null, true);
+            }
+            $return .= $icons[$type];
+        }
+    }
+
+    return $return;
+}
\ No newline at end of file
Index: moodle/admin/roles/permissions_forms.php
--- moodle/admin/roles/permissions_forms.php No Base Revision
+++ moodle/admin/roles/permissions_forms.php Locally New
@@ -0,0 +1,87 @@
+<?php  //$Id:$
+
+require_once("$CFG->libdir/formslib.php");
+
+class role_allow_form extends moodleform {
+
+    // Define the form
+    function definition() {
+        global $CFG;
+
+//TODO: localise!! grrr
+
+        $mform = $this->_form;
+        list($context, $capability, $overridableroles) = $this->_customdata;
+
+        list($needed, $forbidden, $admins) = get_roles_with_cap_in_context($context, $capability->name, true);
+        foreach($needed as $id=>$unused) {
+            unset($overridableroles[$id]);
+        }
+        foreach($forbidden as $id=>$unused) {
+            unset($overridableroles[$id]);
+        }
+        foreach($admins as $id=>$unused) {
+            unset($overridableroles[$id]);
+        }
+
+        $mform->addElement('header', 'allowheader', get_string('roleallowheader', 'role'));
+
+        $mform->addElement('select', 'roleid', get_string('roleselect', 'role'), $overridableroles);
+
+        $mform->addElement('hidden','capability');
+        $mform->setType('capability', PARAM_CAPABILITY);
+        $mform->setDefault('capability', $capability->name);
+
+        $mform->addElement('hidden','contextid');
+        $mform->setType('contextid', PARAM_INT);
+        $mform->setDefault('contextid', $context->id);
+
+        $mform->addElement('hidden','allow');
+        $mform->setType('allow', PARAM_INT);
+        $mform->setDefault('allow', 1);
+
+        $this->add_action_buttons(true, get_string('allow', 'role'));
+    }
+}
+
+class role_prohibit_form extends moodleform {
+
+    // Define the form
+    function definition() {
+        global $CFG;
+
+//TODO: localise!! grrr
+
+        $mform = $this->_form;
+        list($context, $capability, $overridableroles) = $this->_customdata;
+
+        list($needed, $forbidden, $admins) = get_roles_with_cap_in_context($context, $capability->name, true);
+        foreach($needed as $id=>$unused) {
+            unset($overridableroles[$id]);
+        }
+        foreach($forbidden as $id=>$unused) {
+            unset($overridableroles[$id]);
+        }
+        foreach($admins as $id=>$unused) {
+            unset($overridableroles[$id]);
+        }
+
+        $mform->addElement('header', 'ptohibitheader', get_string('roleprohibitheader', 'role'));
+
+        $mform->addElement('select', 'roleid', get_string('roleselect', 'role'), $overridableroles);
+
+        $mform->addElement('hidden','capability');
+        $mform->setType('capability', PARAM_CAPABILITY);
+        $mform->setDefault('capability', $capability->name);
+
+        $mform->addElement('hidden','contextid');
+        $mform->setType('contextid', PARAM_INT);
+        $mform->setDefault('contextid', $context->id);
+
+        $mform->addElement('hidden','prohibit');
+        $mform->setType('prohibit', PARAM_INT);
+        $mform->setDefault('prohibit', 1);
+
+        $this->add_action_buttons(true, get_string('prohibit', 'role'));
+    }
+}
\ No newline at end of file
Index: moodle/admin/roles/tabs.php
--- moodle/admin/roles/tabs.php Base (1.27.2.6)
+++ moodle/admin/roles/tabs.php Locally Modified (Based On 1.27.2.6)
@@ -177,6 +177,14 @@
 
     }
 
+    if (!empty($CFG->simplifiedroles)) {
+        if (has_capability('moodle/role:review', $context)) {
+            $toprow[] = new tabobject('review',
+                    $CFG->wwwroot.'/'.$CFG->admin.'/roles/permissions.php?contextid='.$context->id,
+                    get_string('permissions', 'role'));
+        }
+    }
+
     if (!empty($assignableroles)) {
         $toprow[] = new tabobject('assign',
                         $CFG->wwwroot.'/'.$CFG->admin.'/roles/assign.php?contextid='.$context->id,
Index: moodle/lang/en_utf8/role.php
--- moodle/lang/en_utf8/role.php Base (1.47.2.18)
+++ moodle/lang/en_utf8/role.php Locally Modified (Based On 1.47.2.18)
@@ -102,15 +102,18 @@
 $string['overridepermissionsin'] = 'Override permissions in $a';
 $string['morethan'] = 'More than $a';
 $string['my:manageblocks'] = 'Manage myMoodle page blocks';
+$string['neededroles'] = 'Allowed roles';
 $string['nocapabilitiesincontext'] = 'No capabilities available in this context';
 $string['notset'] = 'Not set';
 $string['overrideroles'] = 'Override roles';
 $string['overriderolesin'] = 'Override roles in $a';
 $string['overrides'] = 'Overrides';
 $string['permissions'] = 'Permissions';
+$string['permissionsin'] = 'Permissions in $a';
 $string['potentialusers'] = '$a potential users';
 $string['prevent'] = 'Prevent';
 $string['prohibit'] = 'Prohibit';
+$string['prohibitedroles'] = 'Prohibited roles';
 $string['question:add'] = 'Add new questions';
 $string['question:config'] = 'Configure question types';
 $string['question:editall'] = 'Edit all questions';
Index: moodle/lib/accesslib.php
--- moodle/lib/accesslib.php Base (1.421.2.101)
+++ moodle/lib/accesslib.php Locally Modified (Based On 1.421.2.101)
@@ -579,13 +579,117 @@
     return false;
 }
 
+function has_capability_in_accessdata_simple($capability, $context, $accessdata, $doanything) {
+    global $CFG;
+
+    $syscontext = get_context_instance(CONTEXT_SYSTEM);
+
+/// build $paths as a list of current + all parent "paths" with order bottom-to-top
+    $contextids = explode('/', $context->path);
+    $paths = array($context->path);
+    $top = '/'.$syscontext->id; // system context path after the loop
+    while (count($contextids) > 2) {
+        array_pop($contextids);
+        $paths[] = implode('/', $contextids);
+    }
+
+    // At the base, ignore rdefs where moodle/legacy:guest or moodle/course:view is allowed
+    if (isset($accessdata['dr']) and $capability === 'moodle/legacy:guest') {
+        $defaultrole = $accessdata['dr'];
+        if (isset($accessdata['rdef']["{$top}:$defaultrole"][$capability])) {
+            if ($accessdata['rdef']["{$top}:$defaultrole"][$capability] > 0) {
+                unset($accessdata['rdef']["{$top}:$defaultrole"][$capability]);
+            }
+        }
+    }
+
+    $roles = array();
+    $switchedrole = false;
+
+/// Find out if role switched
+    if (isset($accessdata['rsw'])) {
+        if (empty($accessdata['rsw'])) {
+            unset($accessdata['rsw']); // keep things fast and unambiguous
+
+        } else {
+            if ($capability === 'moodle/site:doanything') {
+                // no admin rights when switching roles, sorry
+                return false;
+            }
+            // From the bottom up...
+            foreach ($paths as $path) {
+                if (isset($accessdata['rsw'][$path])) {
+                    // Found a switchrole assignment
+                    // check for that role _plus_ the default user role
+                    $roles = array($accessdata['rsw'][$path]=>null, $CFG->defaultuserroleid=>null);
+                    $switchedrole = true;
+                    break;
+                }
+            }
+        }
+    }
+
+
+    if (!$switchedrole) {
+        // get all users roles in this context and above
+        foreach ($paths as $path) {
+            if (isset($accessdata['ra'][$path])) {
+                foreach ($accessdata['ra'][$path] as $roleid) {
+                    $roles[$roleid] = null;
+                }
+            }
+        }
+    }
+
+/// special case for doanything
+    if ($capability === 'moodle/site:doanything') {
+        // tested in system context only, because overriding not allowed
+        foreach ($roles as $roleid=>$ignored) {
+            if (isset($accessdata['rdef']["{$top}:$roleid"][$capability])) {
+                if ($accessdata['rdef']["{$top}:$roleid"][$capability] == CAP_ALLOW) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+/// Now find out what access is given to each role
+/// going from bottom-->up - the lowest override wins unless there is a CAP_PROHIBIT somewhere above or at tested context
+    foreach ($roles as $roleid=>$ignored) {
+        if ($doanything and !$switchedrole and isset($accessdata['rdef']["{$top}:$roleid"]['moodle/site:doanything'])) {
+            if ($accessdata['rdef']["{$top}:$roleid"]['moodle/site:doanything'] == CAP_ALLOW) {
+                // doanything can not be prohibited
+                return true;
+            }
+        }
+        foreach ($paths as $path) {
+            if (isset($accessdata['rdef']["{$path}:$roleid"][$capability])) {
+                $perm = (int)$accessdata['rdef']["{$path}:$roleid"][$capability];
+                if ($perm === CAP_PROHIBIT or is_null($roles[$roleid])) {
+                    $roles[$roleid] = $perm;
+                }
+            }
+        }
+    }
+
+    if (array_search(CAP_PROHIBIT, $roles) !== false) {
+        // any CAP_PROHIBIT found means no access
+        return false;
+    }
+
+    // at least one CAP_ALLOW means user has access
+    return (array_search(CAP_ALLOW, $roles) !== false);
+}
+
+
 /**
  * Walk the accessdata array and return true/false.
  * Deals with prohibits, roleswitching, aggregating
  * capabilities, etc.
  *
  * The main feature of here is being FAST and with no
- * side effects. 
+ * side effects.
  *
  * Notes:
  *
@@ -634,9 +738,12 @@
  *
  */
 function has_capability_in_accessdata($capability, $context, $accessdata, $doanything) {
-
     global $CFG;
 
+    if (!empty($CFG->simplifiedroles)) {
+        return has_capability_in_accessdata_simple($capability, $context, $accessdata, $doanything);
+    }
+
     $path = $context->path;
 
     // build $contexts as a list of "paths" of the current
@@ -702,7 +809,7 @@
                     }
                 }
                 // As we are dealing with a switchrole,
-                // we return _here_, do _not_ walk up 
+                // we return _here_, do _not_ walk up
                 // the hierarchy any further
                 if ($can < 1) {
                     if ($doanything) {
@@ -715,7 +822,7 @@
                 } else {
                     return true;
                 }
-                
+
             }
         }
     }
@@ -3502,8 +3609,33 @@
     return $name;
 }
 
+/**
+ * @return array all the known types of risk. The array keys can be used, for example
+ *      as CSS class names, or in calls to print_risk_icon. The values are the
+ *      corresponding RISK_ constants.
+ */
+function get_all_risks() {
+    return array(
+        'riskmanagetrust' => RISK_MANAGETRUST,
+        'riskconfig' => RISK_CONFIG,
+        'riskxss' => RISK_XSS,
+        'riskpersonal' => RISK_PERSONAL,
+        'riskspam' => RISK_SPAM,
+        'riskdataloss' => RISK_DATALOSS,
+    );
+}
 
 /**
+ * @param object $capability a capability - a row from the mdl_capabilities table.
+ * @return string the human-readable capability name as a link to Moodle Docs.
+ */
+function get_capability_docs_link($capability) {
+    global $CFG;
+    $url = get_docs_url('Capabilities/' . $capability->name);
+    return '<a onclick="this.target=\'docspopup\'" href="' . $url . '">' . get_capability_string($capability->name) . '</a>';
+}
+
+/**
  * Extracts the relevant capabilities given a contextid.
  * All case based, example an instance of forum context.
  * Will fetch all forum related capabilities, while course contexts
@@ -4350,7 +4482,207 @@
     return NULL;
 }
 
+function get_users_by_capability_simple($context, $capability, $fields='', $sort='',
+        $limitfrom='', $limitnum='', $groups='', $exceptions='', $doanything=true,
+        $view=false, $useviewallgroups=false) {
+    global $CFG;
 
+    $ctxids = trim($context->path, '/'); // kill leading slash
+    $ctxids = str_replace('/', ',', $ctxids);
+
+    $isfrontpage    = false;
+    $iscoursepage   = false; // coursepage other than fp
+    if ($context->contextlevel == CONTEXT_COURSE) {
+        if ($context->instanceid == SITEID) {
+            $isfrontpage = true;
+        } else {
+            $iscoursepage = true;
+        }
+    } else {
+        $site = get_site();
+        $frontpagecontext = get_context_instance(CONTEXT_COURSE, $site->id);
+        $frontpath = $frontpagecontext->path.'/';
+        $isfrontpage = (strpos($context->path, $frontpath) === 0);
+    }
+
+    $capabilities = (array)$capability;
+
+    $neededroles   = array();
+    $prohibitroles = array();
+    $adminroles    = array();
+    foreach ($capabilities as $capability) {
+        list($needed, $prohibited, $admins) = get_roles_with_cap_in_context($context, $capability, $doanything);
+        $neededroles[]   = $needed;
+        $prohibitroles[] = $prohibited;
+        $adminroles[]    = $admins;
+    }
+
+    /// Set up hidden role-assignments sql
+    $hiddenra = '';
+    if ($view && !has_capability('moodle/role:viewhiddenassigns', $context)) {
+        $hiddenra = 'AND hidden = 0 ';
+    }
+
+    $parts = array();
+
+    foreach ($neededroles as $i=>$needed) {
+        $prohibited = $prohibitroles[$i];
+        $admins     = $adminroles[$i];
+        $rolessql = "";
+        $orconditions = array();
+        $conditions  = array();
+
+        $everybody = false;
+
+        if (!empty($CFG->defaultuserroleid)) {
+            if (isset($needed[$CFG->defaultuserroleid])) {
+                $everybody = true;
+            } else if (isset($prohibited[$CFG->defaultuserroleid])) {
+                if (empty($admins)) {
+                    // no admins means nobody can here
+                    continue;
+                }
+                // return all admins at this level - admins can not be prohibited
+                $needed     = array();
+                $prohibited = array();
+            }
+        }
+
+        if ($isfrontpage and !empty($CFG->defaultfrontpageroleid)) {
+            // site course and modules + blocks
+            if (isset($needed[$CFG->defaultfrontpageroleid])) {
+                $everybody = true;
+            } else if (isset($prohibited[$CFG->defaultfrontpageroleid])) {
+                if (empty($admins)) {
+                    // no admins means nobody can here
+                    continue;
+                }
+                // return all admins at this level - admins can not be prohibited
+                $needed     = array();
+                $prohibited = array();
+            }
+        }
+
+        if ($everybody) {
+            // means everybody except real guest user
+            $parts[] = "SELECT id FROM {$CFG->prefix}user WHERE deleted=0 AND username<>'guest'";
+            continue;
+        }
+
+        if (!$admins and !$needed) {
+            // no luck - there is no role that would satisfy this
+            continue;
+        }
+
+        if ($admins) {
+            $orconditions[] = "roleid IN (".implode(',', $admins) .")";
+        }
+        if ($needed) {
+            $conditions[] = "roleid IN (".implode(',', $needed) .")";
+        }
+        if ($prohibited) {
+            $conditions[] = "roleid NOT IN (".implode(',', $prohibited) .")";
+        }
+        if ($conditions) {
+            $orconditions[] = "(".implode(" AND ", $conditions).")";
+        }
+
+        $orconditions = "(".implode(" OR ", $orconditions).")";
+
+        $parts[] = "SELECT DISTINCT userid AS id
+                      FROM {$CFG->prefix}role_assignments
+                     WHERE $orconditions
+                           AND contextid IN ($ctxids)
+                           $hiddenra";
+    }
+
+    if (!$parts) {
+        return false;
+    }
+
+    $usersunion = implode(" UNION DISTINCT ", $parts);
+
+
+    //
+    // Prepare query clauses
+    //
+    $wheres = array();
+    $joins  = array();
+
+    // Non-deleted users. We never return deleted users.
+    $wheres[] = 'u.deleted = 0';
+
+    /// Groups
+    if ($groups) {
+        $joins[] = "{$CFG->prefix}groups_members gm ON gm.userid = u.id";
+        if (is_array($groups)) {
+            $grouptest = "gm.groupid IN (".implode(',', $groups).")";
+        } else {
+            $grouptest = "gm.groupid = $groups";
+        }
+
+        if ($useviewallgroups) {
+            if ($viewallgroupsusers = get_users_by_capability_simple($context,
+                                  'moodle/site:accessallgroups', 'u.id, u.id', '', '', '', '', $exceptions)) {
+                $grouptest = "($grouptest OR u.id IN (".implode(',', array_keys($viewallgroupsusers))."))";
+            }
+        }
+        $wheres[] = $grouptest;
+    }
+
+    /// User exceptions
+    if (!empty($exceptions)) {
+        if (is_array($exceptions)) {
+            $exceptions = implode(',', $exceptions);
+        }
+        $wheres[] = "u.id NOT IN ($exceptions)";
+    }
+
+
+    /// Set up default fields
+    if (empty($fields)) {
+        if ($iscoursepage) {
+            $fields = 'u.*, ul.timeaccess as lastaccess';
+        } else {
+            $fields = 'u.*';
+        }
+    } else {
+        if (debugging('', DEBUG_DEVELOPER) && strpos($fields, 'u.*') === false &&
+                strpos($fields, 'u.id') === false) {
+            debugging('u.id must be included in the list of fields passed to get_users_by_capability.', DEBUG_DEVELOPER);
+        }
+    }
+
+    /// Set up default sort
+    if (empty($sort)) { // default to course lastaccess or just lastaccess
+        if ($iscoursepage) {
+            $sort = 'ul.timeaccess';
+        } else {
+            $sort = 'u.lastaccess';
+        }
+    }
+    $sort = $sort ? "ORDER BY $sort" : '';
+
+    // User lastaccess JOIN
+    if ((strpos($sort, 'ul.timeaccess') !== FALSE) or (strpos($fields, 'ul.timeaccess') !== FALSE)) {
+        // user_lastaccess is required
+        $joins[] = "LEFT JOIN {$CFG->prefix}user_lastaccess ul ON (ul.userid = u.id AND ul.courseid = {$context->instanceid})";
+    }
+
+    $wheres = implode(" AND ", $wheres);
+    $joins  = implode("\n", $joins);
+
+    $sql = "SELECT $fields
+              FROM {$CFG->prefix}user u
+              JOIN ($usersunion) uids ON uids.id = u.id
+                   $joins
+             WHERE $wheres
+             $sort";
+
+    return get_records_sql($sql, $limitfrom, $limitnum);
+}
+
+
 /**
  * Who has this capability in this context?
  *
@@ -4388,6 +4720,11 @@
         $view=false, $useviewallgroups=false) {
     global $CFG;
 
+    if (!empty($CFG->simplifiedroles)) {
+        return get_users_by_capability_simple($context, $capability, $fields, $sort, $limitfrom, $limitnum,
+                                              $groups, $exceptions, $doanything, $view, $useviewallgroups);
+    }
+
     $ctxids = substr($context->path, 1); // kill leading slash
     $ctxids = str_replace('/', ',', $ctxids);
 
@@ -5786,4 +6123,264 @@
         $cap->roleid = $targetrole;
         insert_record('role_capabilities', $cap);
     }
-}?>
+}
+
+/**
+ * Returns two lists, this can be used to find out if user has capability.
+ * Having any neede role and no forbidden role in this context means
+ * user has this capability in this context,
+ *
+ * @param object $context
+ * @param string $capability
+ * @param bool $doanything include roles with do anything
+ * @return array($neededroles, $forbiddenroles, $adminroles)
+ */
+function get_roles_with_cap_in_context($context, $capability, $doanything) {
+    global $CFG;
+
+    $ctxids = trim($context->path, '/'); // kill leading slash
+    $ctxids = str_replace('/', ',', $ctxids);
+
+    $adminroles = array();
+
+    if ($doanything) {
+        $systemcontext = get_context_instance(CONTEXT_SYSTEM);
+        $sql = "SELECT roleid
+                  FROM {$CFG->prefix}role_capabilities
+                 WHERE capability = 'moodle/site:doanything'
+                       AND contextid = $systemcontext->id
+                       AND permission = ".CAP_ALLOW;
+        if ($roles = get_records_sql($sql)) {
+            foreach ($roles as $roleid=>$ignored) {
+                $adminroles[$roleid] = $roleid;
+            }
+        }
+    }
+
+    $sql = "SELECT rc.id, rc.roleid, rc.permission, ctx.depth
+              FROM {$CFG->prefix}role_capabilities rc
+              JOIN {$CFG->prefix}context ctx ON ctx.id = rc.contextid
+             WHERE rc.capability = '$capability' AND ctx.id IN ($ctxids)
+          ORDER BY rc.roleid ASC, ctx.depth DESC";
+
+    if (!$capdefs = get_records_sql($sql)) {
+        // no cap definitions --> no capability
+        return array(array(), array(), $adminroles);
+    }
+
+    $forbidden = array();
+    $needed    = array();
+    foreach($capdefs as $def) {
+        if (isset($forbidden[$def->roleid])) {
+            continue;
+        }
+        if ($def->permission == CAP_PROHIBIT) {
+            $forbidden[$def->roleid] = $def->roleid;
+            unset($needed[$def->roleid]);
+            continue;
+        }
+        if (!isset($needed[$def->roleid])) {
+            if ($def->permission == CAP_ALLOW) {
+                $needed[$def->roleid] = true;
+            } else if ($def->permission == CAP_PREVENT) {
+                $needed[$def->roleid] = false;
+            }
+        }
+    }
+    unset($capdefs);
+
+    // remove all those roles not allowing
+    foreach($needed as $key=>$value) {
+        if (!$value) {
+            unset($needed[$key]);
+        } else {
+            $needed[$key] = $key;
+        }
+    }
+
+    return array($needed, $forbidden, $adminroles);
+}
+
+
+/**
+ * This function verifies the frohibit comes from this context
+ * and there are no more prohibits in parent contexts.
+ * @param object $context
+ * @param string $capability name
+ * @return bool
+ */
+function prohibit_is_removable($roleid, $context, $capability) {
+    global $CFG;
+
+    $ctxids = trim($context->path, '/'); // kill leading slash
+    $ctxids = str_replace('/', ',', $ctxids);
+
+    $sql = "SELECT ctx.id, ctx.depth
+              FROM {$CFG->prefix}role_capabilities rc
+              JOIN {$CFG->prefix}context ctx ON ctx.id = rc.contextid
+             WHERE rc.roleid = $roleid AND rc.permission = ".CAP_PROHIBIT." AND rc.capability = '$capability' AND ctx.id IN ($ctxids)";
+
+    if (!$prohibits = get_records_sql($sql)) {
+        // no prohibits == nothing to remove
+        return true;
+    }
+
+    if (count($prohibits) > 1) {
+        // more prohibints can not be removed
+        return false;
+    }
+
+    $prohibit = reset($prohibits);
+
+    // tru only if the only one prohibit defined at this level
+    return ($context->depth == $prohibit->depth);
+}
+
+/**
+ * More user friendly capability overriding
+ * @param int $roleid
+ * @param object $context
+ * @param string $capname capability name
+ * @return void
+ */
+function simple_capability_prevent($roleid, $context, $capname) {
+    global $CFG;
+
+    $ctxids = trim($context->path, '/'); // kill leading slash
+    $ctxids = str_replace('/', ',', $ctxids);
+
+    $sql = "SELECT ctx.id, rc.permission, ctx.depth
+              FROM {$CFG->prefix}role_capabilities rc
+              JOIN {$CFG->prefix}context ctx ON ctx.id = rc.contextid
+             WHERE rc.roleid = $roleid AND rc.capability = '$capname' AND ctx.id IN ($ctxids)
+          ORDER BY ctx.depth DESC";
+
+    if (!$permissions = get_records_sql($sql)) {
+        // already prevented
+        return;
+    }
+
+    // try to find any prohibit which always prevails
+    foreach($permissions as $pid=>$permission) {
+        if ($permission->permission == CAP_PROHIBIT) {
+            return;
+        }
+    }
+
+    $lowest = reset($permissions);
+
+    if ($lowest->permission == CAP_PREVENT) {
+        // already prevent
+        return;
+    }
+
+    // force prevent cap override at this context
+    assign_capability($capname, CAP_PREVENT, $roleid, $context->id, true);
+
+    // for cap reloading
+    mark_context_dirty($context->path);
+}
+
+/**
+ * More user friendly capability overriding
+ * @param int $roleid
+ * @param object $context
+ * @param string $capname capability name
+ * @return void
+ */
+function simple_capability_allow($roleid, $context, $capname) {
+    global $CFG;
+
+    $ctxids = trim($context->path, '/'); // kill leading slash
+    $ctxids = str_replace('/', ',', $ctxids);
+
+    $sql = "SELECT ctx.id, rc.permission, ctx.depth
+              FROM {$CFG->prefix}role_capabilities rc
+              JOIN {$CFG->prefix}context ctx ON ctx.id = rc.contextid
+             WHERE rc.roleid = $roleid AND rc.capability = '$capname' AND ctx.id IN ($ctxids)
+          ORDER BY ctx.depth DESC";
+
+    if (!$permissions = get_records_sql($sql)) {
+        // nothing means prevented
+        assign_capability($capname, CAP_ALLOW, $roleid, $context->id,true);
+        // for cap reloading
+        mark_context_dirty($context->path);
+        return;
+    }
+
+    // try to find any prohibit which always prevails
+    foreach($permissions as $pid=>$permission) {
+        if ($permission->permission == CAP_PROHIBIT) {
+            return;
+        }
+    }
+
+    $lowest = reset($permissions);
+
+    if ($lowest->permission == CAP_ALLOW) {
+        // already allowed
+        return;
+    }
+
+    // force allow cap override at this context
+    assign_capability($capname, CAP_ALLOW, $roleid, $context->id, true);
+
+    // for cap reloading
+    mark_context_dirty($context->path);
+}
+
+/**
+ * More user friendly capability overriding
+ * @param int $roleid
+ * @param object $context
+ * @param string $capname capability name
+ * @return void
+ */
+function simple_capability_unprohibit($roleid, $context, $capname) {
+    unassign_capability($capname, $roleid, $context->id);
+    // for cap reloading
+    mark_context_dirty($context->path);
+}
+
+/**
+ * More user friendly capability overriding
+ * @param int $roleid
+ * @param object $context
+ * @param string $capname capability name
+ * @return void
+ */
+function simple_capability_prohibit($roleid, $context, $capname) {
+    global $CFG;
+
+    $ctxids = trim($context->path, '/'); // kill leading slash
+    $ctxids = str_replace('/', ',', $ctxids);
+
+    $sql = "SELECT ctx.id, rc.permission, ctx.depth
+              FROM {$CFG->prefix}role_capabilities rc
+              JOIN {$CFG->prefix}context ctx ON ctx.id = rc.contextid
+             WHERE rc.roleid = $roleid AND rc.capability = '$capname' AND ctx.id IN ($ctxids)
+          ORDER BY ctx.depth DESC";
+
+    if (!$permissions = get_records_sql($sql)) {
+        // nothing means prevented
+        assign_capability($capname, CAP_PROHIBIT, $roleid, $context->id,true);
+        // for cap reloading
+        mark_context_dirty($context->path);
+        return;
+    }
+
+    // try to find any prohibit which always prevails
+    foreach($permissions as $pid=>$permission) {
+        if ($permission->permission == CAP_PROHIBIT) {
+            return;
+        }
+    }
+
+    // force allow cap override at this context
+    assign_capability($capname, CAP_PROHIBIT, $roleid, $context->id, true);
+
+    // for cap reloading
+    mark_context_dirty($context->path);
+}
+
+?>
Index: moodle/lib/db/access.php
--- moodle/lib/db/access.php Base (1.75.2.18)
+++ moodle/lib/db/access.php Locally Modified (Based On 1.75.2.18)
@@ -355,6 +355,18 @@
         )
     ),
 
+    'moodle/role:review' => array(
+
+        'riskbitmask' => RISK_PERSONAL,
+
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_COURSE,
+        'legacy' => array(
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+        )
+    ),
+
     'moodle/role:override' => array(
 
         'riskbitmask' => RISK_SPAM | RISK_PERSONAL | RISK_XSS,
Index: moodle/lib/moodlelib.php
--- moodle/lib/moodlelib.php Base (1.960.2.121)
+++ moodle/lib/moodlelib.php Locally Modified (Based On 1.960.2.121)
@@ -227,7 +227,13 @@
  */
 define('PARAM_BASE64',   0x20000);
 
+/**
+ * PARAM_CAPABILITY - A capability name, like 'moodle/role:manage'. Actually
+ * checked against the list of capabilties in the database.
+ */
+define('PARAM_CAPABILITY',   0x40000);
 
+
 /// Page types ///
 /**
  * PAGE_COURSE_VIEW is a definition of a page type. For more information on the page class see moodle/lib/pagelib.php.
@@ -594,6 +600,14 @@
                 return '';
             }
 
+        case PARAM_CAPABILITY:
+            if (is_valid_capability($param)) {
+                return $param;
+            } else {
+                return '';
+            }
+
+
         default:                 // throw error, switched parameters in optional_param or another serious problem
             error("Unknown parameter type: $type");
     }
Index: moodle/lib/weblib.php
--- moodle/lib/weblib.php Base (1.970.2.134)
+++ moodle/lib/weblib.php Locally Modified (Based On 1.970.2.134)
@@ -6841,6 +6841,16 @@
 }
 
 /**
+ * @param string $path the end of the URL.
+ * @return The start of a MoodleDocs URL in the user's language.
+ *      E.g. http://docs.moodle.org/en/
+ */
+function get_docs_url($path) {
+    global $CFG;
+    return $CFG->docroot . '/' . str_replace('_utf8', '', current_language()) . '/' . $path;
+}
+
+/**
  * Returns a string containing a link to the user documentation.
  * Also contains an icon by default. Shown to teachers and admin only.
  *
Index: moodle/pix/t/add.gif
MIME: application/octet-stream; encoding: Base64; length: 61
R0lGODlhCwALAIABAGxsbP///yH5BAEAAAEALAAAAAALAAsAAAIUjI8Jm7fQ
zFOvwmCrzAzN+DVhlBQAOw==
Index: moodle/theme/standard/styles_color.css
--- moodle/theme/standard/styles_color.css Base (1.149.2.20)
+++ moodle/theme/standard/styles_color.css Locally Modified (Based On 1.149.2.20)
@@ -1129,6 +1129,7 @@
   border-bottom-color: #cecece;
 }
 
+#admin-roles-permissions .rolecap .cap-desc .cap-name,
 #admin-roles-manage .rolecap .cap-desc .cap-name,
 #admin-roles-override .rolecap .cap-desc .cap-name {
   color: #888;
Index: moodle/theme/standard/styles_fonts.css
--- moodle/theme/standard/styles_fonts.css Base (1.140.2.17)
+++ moodle/theme/standard/styles_fonts.css Locally Modified (Based On 1.140.2.17)
@@ -241,6 +241,7 @@
   font-size: 0.8em;
 }
 
+#admin-roles-permissions .rolecap .cap-desc .cap-name,
 #admin-roles-manage .rolecap .cap-desc .cap-name,
 #admin-roles-override .rolecap .cap-desc .cap-name {
   font-size: 0.75em;
Index: moodle/theme/standard/styles_layout.css
--- moodle/theme/standard/styles_layout.css Base (1.516.2.75)
+++ moodle/theme/standard/styles_layout.css Locally Modified (Based On 1.516.2.75)
@@ -978,6 +978,7 @@
   text-align:center;
 }
 
+#admin-roles-permissions .rolecap .cap-desc .cap-name,
 #admin-roles-manage .rolecap .cap-desc .cap-name,
 #admin-roles-override .rolecap .cap-desc .cap-name {
   display: block;
@@ -993,6 +994,11 @@
   text-align:center;
 }
 
+#admin-roles-permissions .allowmore,
+#admin-roles-permissions .prohibitmore {
+    float: right;
+}
+
 #admin-lang .generalbox {
   text-align:center;
   margin:auto;
Index: moodle/version.php
--- moodle/version.php Base (1.563.2.453)
+++ moodle/version.php Locally Modified (Based On 1.563.2.453)
@@ -6,7 +6,7 @@
 // This is compared against the values stored in the database to determine
 // whether upgrades should be performed (see lib/db/*.php)
 
-    $version = 2007101542;  // YYYYMMDD      = date of the 1.9 branch (don't change)
+    $version = 2007101542.01;  // YYYYMMDD      = date of the 1.9 branch (don't change)
                             //         X     = release number 1.9.[0,1,2,3,4,5...]
                             //          Y.YY = micro-increments between releases
 

