### Eclipse Workspace Patch 1.0
#P moodle19b
Index: theme/standard/styles_fonts.css
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/standard/styles_fonts.css,v
retrieving revision 1.140.2.17
diff -u -r1.140.2.17 styles_fonts.css
--- theme/standard/styles_fonts.css	27 Feb 2008 04:46:15 -0000	1.140.2.17
+++ theme/standard/styles_fonts.css	27 Jul 2008 12:28:21 -0000
@@ -242,8 +242,13 @@
 }
 
 #admin-roles-manage .rolecap .cap-desc .cap-name,
-#admin-roles-override .rolecap .cap-desc .cap-name {
-  font-size: 0.75em;
+#admin-roles-override .rolecap .cap-desc .cap-name,
+#user-permissions .rolecap .cap-desc .cap-name {
+    font-size: 0.75em;
+}
+
+#user-permissions .rolecap .permission {
+  text-align: center;
 }
 
 #adminsettings .form-shortname {
Index: theme/standard/styles_layout.css
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/standard/styles_layout.css,v
retrieving revision 1.516.2.59
diff -u -r1.516.2.59 styles_layout.css
--- theme/standard/styles_layout.css	24 Jul 2008 14:03:17 -0000	1.516.2.59
+++ theme/standard/styles_layout.css	27 Jul 2008 12:28:23 -0000
@@ -932,11 +932,20 @@
 
 #admin-roles-manage .selector,
 #admin-roles-assign .selector,
-#admin-roles-override .selector {
+#admin-roles-override .selector,
+#user-permissions .selector {
   text-align:center;
   margin-bottom:1em;
 }
 
+#user-permissions .rolecap .hidden {
+  display:none;
+}
+
+#user-permissions div.showhidebuttons {
+  text-align:right;
+}
+
 #admin-roles-manage table.roledesc,
 #admin-roles-override table.roledesc {
   margin-left:auto;
@@ -944,7 +953,8 @@
 }
 
 #admin-roles-manage table.rolecap,
-#admin-roles-override table.rolecap {
+#admin-roles-override table.rolecap,
+#user-permissions table.rolecap {
   margin-left:auto;
   margin-right:auto;
 }
@@ -957,8 +967,9 @@
 }
 
 #admin-roles-manage .rolecap .cap-desc .cap-name,
-#admin-roles-override .rolecap .cap-desc .cap-name {
-  display: block;
+#admin-roles-override .rolecap .cap-desc .cap-name,
+#user-permissions .rolecap .cap-desc .cap-name {
+    display: block;
 }
 
 #admin-roles-override .cell.c1,
Index: theme/standard/styles_color.css
===================================================================
RCS file: /cvsroot/moodle/moodle/theme/standard/styles_color.css,v
retrieving revision 1.149.2.16
diff -u -r1.149.2.16 styles_color.css
--- theme/standard/styles_color.css	26 May 2008 12:06:20 -0000	1.149.2.16
+++ theme/standard/styles_color.css	27 Jul 2008 12:28:21 -0000
@@ -1103,15 +1103,29 @@
 }
 
 #admin-roles-manage .rolecap,
-#admin-roles-override .rolecap {
+#admin-roles-override .rolecap,
+#user-permissions .rolecap {
   border:none;
   border-bottom:1px solid;
   border-bottom-color: #cecece;
 }
 
 #admin-roles-manage .rolecap .cap-desc .cap-name,
-#admin-roles-override .rolecap .cap-desc .cap-name {
-  color: #888;
+#admin-roles-override .rolecap .cap-desc .cap-name,
+#user-permissions .rolecap .cap-desc .cap-name {
+    color: #888;
+}
+
+#user-permissions .rolecap tr.haspermission {
+  background-color:#eeFFee;
+}
+
+#user-permissions .rolecap tr.nopermission {
+  background-color:#FFeeee;
+}
+
+#user-permissions .doanything tr.nopermission {
+  background-color:#FFFFee;
 }
 
 form.mform .required label {
Index: user/tabs.php
===================================================================
RCS file: /cvsroot/moodle/moodle/user/tabs.php,v
retrieving revision 1.43.2.4
diff -u -r1.43.2.4 tabs.php
--- user/tabs.php	18 Apr 2008 03:10:31 -0000	1.43.2.4
+++ user/tabs.php	27 Jul 2008 12:28:23 -0000
@@ -240,6 +240,16 @@
     }
 /// Add second row to display if there is one
 
+    if (!empty($user)) {
+        if (has_capability('moodle/user:viewpermissions', get_context_instance(CONTEXT_COURSE, $course->id))) {
+            if ($currenttab == 'permissions') {
+                $inactive = array('permissions');
+            }
+            $toprow[] = new tabobject('permissions', $CFG->wwwroot.'/user/permissions.php?id='.$course->id.
+                                      '&amp;user='.$user->id, get_string('userpermissions','role'));
+        }
+    }
+
     if (!empty($secondrow)) {
         $tabs = array($toprow, $secondrow);
     } else {
Index: lib/db/access.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/db/access.php,v
retrieving revision 1.75.2.9
diff -u -r1.75.2.9 access.php
--- lib/db/access.php	24 Jul 2008 21:58:07 -0000	1.75.2.9
+++ lib/db/access.php	27 Jul 2008 12:28:21 -0000
@@ -831,6 +831,17 @@
         )
     ),
 
+    'moodle/user:viewpermissions' => array(
+
+        'captype' => 'read',
+        'contextlevel' => CONTEXT_COURSE,
+        'legacy' => array(
+            'teacher' => CAP_ALLOW,
+            'editingteacher' => CAP_ALLOW,
+            'admin' => CAP_ALLOW
+        )
+    ),
+
     'moodle/question:managecategory' => array(
 
         'captype' => 'write',
Index: version.php
===================================================================
RCS file: /cvsroot/moodle/moodle/version.php,v
retrieving revision 1.563.2.188
diff -u -r1.563.2.188 version.php
--- version.php	27 Jul 2008 01:37:49 -0000	1.563.2.188
+++ version.php	27 Jul 2008 12:28:20 -0000
@@ -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 = 2007101520.03;  // YYYYMMDD      = date of the 1.9 branch (don't change)
+    $version = 2007101520.04;  // YYYYMMDD      = date of the 1.9 branch (don't change)
                             //         X     = release number 1.9.[0,1,2,3...]
                             //          Y.YY = micro-increments between releases
 
Index: lang/en_utf8/role.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lang/en_utf8/role.php,v
retrieving revision 1.47.2.15
diff -u -r1.47.2.15 role.php
--- lang/en_utf8/role.php	23 Jul 2008 16:09:13 -0000	1.47.2.15
+++ lang/en_utf8/role.php	27 Jul 2008 12:28:20 -0000
@@ -67,6 +67,7 @@
 $string['defaultrole'] = 'Default role';
 $string['defineroles'] = 'Define roles';
 $string['deleterolesure'] = 'Are you sure that you want to delete role \"$a->name ($a->shortname)\"?</p><p>Currently this role is assigned to $a->count users.';
+$string['doanythingpermissionnote'] = 'Note: User has <em>Allowed to do everything</em> permission in this context.';
 $string['duplicaterolesure'] = 'Are you sure that you want to duplicate role \"$a->name ($a->shortname)\"?</p>';
 $string['duplicaterole'] = 'Duplicate role';
 $string['editrole'] = 'Edit role';
@@ -120,6 +121,7 @@
 $string['resetrolenolegacy'] = 'Clear permissions';
 $string['resetrolesure'] = 'Are you sure that you want to reset role \"$a->name ($a->shortname)\" to defaults?<p></p>The defaults are taken from the selected legacy capability ($a->legacytype).';
 $string['resetrolesurenolegacy'] = 'Are you sure that you want to clear all permissions defined in this role \"$a->name ($a->shortname)\"?';
+$string['userpermissions'] = 'Permissions';
 $string['risks'] = 'Risks';
 $string['role:assign'] = 'Assign roles to users';
 $string['role:manage'] = 'Create and manage roles';
@@ -133,6 +135,7 @@
 $string['roletoassign'] = 'Role to assign';
 $string['roletooverride'] = 'Role to override';
 $string['safeoverridenotice'] = 'Note: Capabilities with higher risks are locked because you are only allowed to override safe capabilities.';
+$string['selectcontext'] = 'Select context';
 $string['selectrole'] = 'Select a role';
 $string['showallroles'] = 'Show all roles';
 $string['site:accessallgroups'] = 'Access all groups';
@@ -168,6 +171,7 @@
 $string['user:update'] = 'Update user profiles';
 $string['user:viewdetails'] = 'View user profiles';
 $string['user:viewhiddendetails'] = 'View hidden details of users';
+$string['user:viewpermissions'] = 'View user\'s permissions';
 $string['user:viewuseractivitiesreport'] = 'See user activity reports';
 $string['userhashiddenassignments'] = 'This user has one or more hidden role assignments in this course';
 $string['userswithrole'] = 'All users with a role';
Index: user/permissions.php
===================================================================
RCS file: user/permissions.php
diff -N user/permissions.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ user/permissions.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,275 @@
+<?php  // $Id:$
+require('../config.php');
+require_once($CFG->dirroot.'/notes/lib.php');
+require_once($CFG->dirroot.'/course/lib.php');
+require_once($CFG->libdir.'/formslib.php');
+
+$userid    = required_param('user', PARAM_INT);         // user id
+$id        = optional_param('id', SITEID, PARAM_INT);   // course id
+$contextid = optional_param('contextid', 0, PARAM_INT); // selecetd context id
+
+if (!$course = get_record('course', 'id', $id)) {
+    error('Course ID is incorrect');
+}
+
+require_login($course);
+
+if (!$user = get_record('user', 'id', $userid, 'deleted', 0)) {
+    error('Incorrect user id');
+}
+
+$coursecontext = get_context_instance(CONTEXT_COURSE, $course->id);
+$usercontext   = get_context_instance(CONTEXT_USER, $user->id);
+$systemcontext = get_context_instance(CONTEXT_SYSTEM);
+
+$context_menu = array();
+
+if (has_capability('moodle/user:viewpermissions', $systemcontext)) {
+    $context_menu[$systemcontext->id] = get_string('coresystem');
+}
+
+if (has_capability('moodle/user:viewpermissions', $usercontext)) {
+    $context_menu[$usercontext->id] = get_string('user');
+}
+
+$cats = array();
+if ($course->category) {
+    if ($category = get_record('course_categories', 'id', $course->category)) {
+        $catcontext = get_context_instance(CONTEXT_COURSECAT, $category->id);
+        if (has_capability('moodle/user:viewpermissions', $catcontext)) {
+            $cats[$catcontext->id] = format_string($category->name);
+        }
+        while ($parent = get_record('course_categories', 'id', $category->parent)) {
+            $category = $parent;
+            $catcontext = get_context_instance(CONTEXT_COURSECAT, $category->id);
+            if (has_capability('moodle/user:viewpermissions', $catcontext)) {
+                $cats[$catcontext->id] = format_string($category->name);
+            }
+        }
+    }
+}
+if ($cats) {
+    $cats = array_reverse($cats, true);
+    $context_menu[-2] = '--'.get_string('categories');
+    $context_menu = $context_menu + $cats;
+}
+
+if (has_capability('moodle/user:viewpermissions', $coursecontext)) {
+    $context_menu[-1] = '--'.get_string('course');
+    $context_menu[$coursecontext->id] = format_string($course->shortname);
+}
+
+$modinfo = get_fast_modinfo($course);
+
+$mods = array();
+
+foreach ($modinfo->cms as $cm) {
+    if (!$cm->uservisible) {
+        continue;
+    }
+    $modcontext = get_context_instance(CONTEXT_MODULE, $cm->id);
+    if (has_capability('moodle/user:viewpermissions', $modcontext)) {
+        $mods[$modcontext->id] = format_string($cm->name);
+    }
+}
+
+if ($mods) {
+    $context_menu[-3] = '--'.get_string('activities');
+    $context_menu = $context_menu + $mods;
+}
+
+if (!$contextid) {
+    $selected_context = $coursecontext;
+    $contextid = $selected_context->id;
+
+} else if (isset($context_menu[$contextid])) {
+    $selected_context = get_context_instance_by_id($contextid);
+
+} else {
+    error('Incorrect context id');
+}
+
+require_capability('moodle/user:viewpermissions', $selected_context);
+
+require_js(array('yui_yahoo',
+                 'yui_dom',
+                 'yui_event'));
+
+/// Print headers
+
+$struserpermissions = get_string('userpermissions', 'role');
+$strparticipants    = get_string('participants');
+$stryes             = get_string('yes');
+$strno              = get_string('no');
+
+$userfullname       = fullname($user, true);
+
+$navlinks = array();
+if (has_capability('moodle/course:viewparticipants', $coursecontext) || has_capability('moodle/site:viewparticipants', $systemcontext)) {
+    $navlinks[] = array('name' => $strparticipants, 'link' => "index.php?id=$course->id", 'type' => 'misc');
+}
+$navlinks[] = array('name' => $userfullname,
+                    'link' => "view.php?id=$user->id&amp;course=$course->id",
+                    'type' => 'misc');
+$navlinks[] = array('name' => $struserpermissions, 'link' => null, 'type' => 'misc');
+$navigation = build_navigation($navlinks);
+print_header("$course->shortname: $struserpermissions: $userfullname", $course->fullname, $navigation, "");
+
+// this will contain all available the based On select options, but we'll disable some on them on a per user basis
+
+$currentgroup = groups_get_course_group($course, true);
+if (!$currentgroup) {      // To make some other functions work better later
+    $currentgroup  = NULL;
+}
+
+/// setting up tags
+$filtertype   = 'user';
+$filterselect = $course->id;
+$showroles    = 1;
+$currenttab   = 'permissions';
+
+require_once($CFG->dirroot .'/user/tabs.php');
+
+print_heading($struserpermissions);
+
+echo '<div class="selector">'.get_string('selectcontext', 'role').'&nbsp;';
+popup_form("$CFG->wwwroot/user/permissions.php?id=$course->id&amp;user=$user->id&amp;contextid=",
+            $context_menu, 'contextselect', $selected_context->id, '', 'contextid', get_string('userpermissions', 'role'));
+echo '</div>';
+
+$capabilities = fetch_context_capabilities($selected_context);
+$doanything   = has_capability('moodle/site:doanything', $selected_context, $user->id);
+$strcapabilities = 'Capabilities';
+
+if ($doanything) {
+    $doanythingclass = 'doanything';
+} else {
+    $doanythingclass = '';
+}
+
+$lang = str_replace('_utf8', '', current_language());
+
+print_box_start('generalbox boxaligncenter boxwidthwide');
+
+$yesimage = '<img src="'.$CFG->pixpath.'/i/tick_green_big.gif" class="icon" alt="'.$stryes.'" title="'.$stryes.'" />';
+$noimage  = '<img src="'.$CFG->pixpath.'/i/cross_red_big.gif" class="icon" alt="'.$strno.'" title="'.$strno.'" />';
+
+$showyes = get_string('show').$yesimage;
+$hideyes = get_string('hide').$yesimage;
+$showno = get_string('show').$noimage;
+$hideno = get_string('hide').$noimage;
+
+if (ajaxenabled()) {
+    echo '<div class="showhidebuttons">';
+    echo '<button id="toggle-yes-button">'.$hideyes.'</button>';
+    echo '<button id="toggle-no-button">'.$hideno.'</button>';
+    echo '</div>';
+}
+
+echo '<table class="rolecap '.$doanythingclass.'">';
+echo '<tr>';
+echo '<th class="name" align="left" scope="col">'.get_string('capabilities','role').'</th>';
+echo '<th class="inherit" scope="col">'.get_string('permissions', 'role');
+echo '</th>';
+echo '</tr>';
+
+// init these 2
+$contextlevel = 0;
+$component = '';
+
+foreach ($capabilities as $capability) {
+
+    $hascap = has_capability($capability->name, $selected_context, $user->id, false);
+
+    if ($hascap) {
+        $image = $yesimage;
+        $class = 'haspermission';
+    } else {
+        $image = $noimage;
+        $class = 'nopermission';
+    }
+
+    // prints a breaker if component or name or context level
+    if (component_level_changed($capability, $component, $contextlevel)) {
+        echo ('<tr class="rolecapheading header"><td colspan="2" class="header"><strong>'.get_component_string($capability->component, $capability->contextlevel).'</strong></td></tr>');
+    }
+
+    // these 2 are used to see to group same mod/core capabilities together
+    $contextlevel = $capability->contextlevel;
+    $component = $capability->component;
+
+    echo '<tr class="rolecap '.$class.'">';
+    echo '<td class="name"><span class="cap-desc">';
+    echo '<a onclick="this.target=\'docspopup\'" href="'.$CFG->docroot.'/'.$lang.'/'.$strcapabilities.'/'.$capability->name.'">';
+    echo get_capability_string($capability->name);
+    echo '</a><span class="cap-name">'.$capability->name.'</span></span></td>';
+
+    echo '<td class="permission">';
+    echo $image;
+    echo '</td>';
+    echo '</tr>';
+}
+
+echo '</table>';
+
+if ($doanything) {
+    echo get_string('doanythingpermissionnote', 'role');
+}
+?>
+<script type="text/javascript">
+//<![CDATA[
+  var hidden_flag_yes = false;
+  var hide_yes_str = '<?php echo addslashes_js($hideyes)?>';
+  var show_yes_str = '<?php echo addslashes_js($showyes)?>';
+  var toggle_collapsing_yes = function() {
+    var rows = YAHOO.util.Dom.getElementsByClassName('haspermission', 'tr');
+    var button_yes = YAHOO.util.Dom.get('toggle-yes-button');
+    if (hidden_flag_yes) {
+      hidden_flag_yes = false;
+      var i;
+      for (i in rows) {
+        YAHOO.util.Dom.removeClass(rows[i], 'hidden')
+      }
+      button_yes.innerHTML = hide_yes_str;
+    } else {
+      hidden_flag_yes = true;
+      var i;
+      for (i in rows) {
+        YAHOO.util.Dom.addClass(rows[i], 'hidden');
+      }
+      button_yes.innerHTML = show_yes_str;
+    }
+  };
+
+  var hidden_flag_no = false;
+  var hide_no_str = '<?php echo addslashes_js($hideno)?>';
+  var show_no_str = '<?php echo addslashes_js($showno)?>';
+  var toggle_collapsing_no = function() {
+    var rows = YAHOO.util.Dom.getElementsByClassName('nopermission', 'tr');
+    var button_no = YAHOO.util.Dom.get('toggle-no-button');
+    if (hidden_flag_no) {
+      hidden_flag_no = false;
+      var i;
+      for (i in rows) {
+        YAHOO.util.Dom.removeClass(rows[i], 'hidden')
+      }
+      button_no.innerHTML = hide_no_str;
+    } else {
+      hidden_flag_no = true;
+      var i;
+      for (i in rows) {
+        YAHOO.util.Dom.addClass(rows[i], 'hidden');
+      }
+      button_no.innerHTML = show_no_str;
+    }
+  };
+
+  YAHOO.util.Event.on('toggle-yes-button', 'click', toggle_collapsing_yes);
+  YAHOO.util.Event.on('toggle-no-button', 'click', toggle_collapsing_no);
+//]]>
+</script>
+<?php
+
+print_box_end();
+
+print_footer($course);
