? .project
? sites/default/files
? sites/default/settings.php
Index: modules/user/user.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v
retrieving revision 1.43
diff -u -p -r1.43 user.admin.inc
--- modules/user/user.admin.inc	26 Apr 2009 19:44:40 -0000	1.43
+++ modules/user/user.admin.inc	30 Apr 2009 15:19:35 -0000
@@ -676,46 +676,39 @@ function theme_user_admin_perm($form) {
 function user_admin_role() {
   $rid = arg(4);
   if ($rid) {
-    if ($rid == DRUPAL_ANONYMOUS_RID || $rid == DRUPAL_AUTHENTICATED_RID) {
-      drupal_goto('admin/user/roles');
-    }
-    // Display the edit role form.
     $role = db_query('SELECT * FROM {role} WHERE rid = :rid', array(':rid' => $rid))->fetchObject();
+  }
+    // Display the edit role form.
     $form['name'] = array(
       '#type' => 'textfield',
       '#title' => t('Role name'),
-      '#default_value' => $role->name,
+      '#default_value' => isset($role->name) ? check_plain($role->name) : NULL,
       '#size' => 30,
       '#required' => TRUE,
       '#maxlength' => 64,
       '#description' => t('The name for this role. Example: "moderator", "editorial board", "site architect".'),
     );
+    // Disable and fill in protected role names.
+    if ($rid == DRUPAL_ANONYMOUS_RID || $rid == DRUPAL_AUTHENTICATED_RID) {
+      $form['name']['#disabled'] = true;
+      $form['name']['#value'] = t($role->name);
+    }
+    $form['description'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Description'),
+      '#default_value' => isset($role->description) ? filter_xss_admin($role->description) : NULL,
+      '#description' => t('A description of the role to explain what it is for. Example: "Can perform content administration tasks, but cannot ban users."'),
+    );
     $form['rid'] = array(
       '#type' => 'value',
       '#value' => $rid,
     );
     $form['submit'] = array(
       '#type' => 'submit',
-      '#value' => t('Save role'),
-    );
-    $form['delete'] = array(
-      '#type' => 'submit',
-      '#value' => t('Delete role'),
-    );
-  }
-  else {
-    $form['name'] = array(
-      '#type' => 'textfield',
-      '#size' => 32,
-      '#maxlength' => 64,
-    );
-    $form['submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Add role'),
+      '#value' => $rid ? t('Save role') : t('Add role'),
     );
     $form['#submit'][] = 'user_admin_role_submit';
     $form['#validate'][] = 'user_admin_role_validate';
-  }
   return $form;
 }
 
@@ -745,7 +738,8 @@ function user_admin_role_submit($form, &
   if ($form_state['values']['op'] == t('Save role')) {
     db_update('role')
       ->fields(array(
-        'name' => $form_state['values']['name'],
+        'name'        => $form_state['values']['name'],
+        'description' => $form_state['values']['description'],
       ))
       ->condition('rid', $form_state['values']['rid'])
       ->execute();
@@ -760,12 +754,55 @@ function user_admin_role_submit($form, &
     drupal_set_message(t('The role has been deleted.'));
   }
   elseif ($form_state['values']['op'] == t('Add role')) {
-    db_insert('role')->fields(array('name' => $form_state['values']['name']))->execute();
+    db_insert('role')
+      ->fields(array(
+        'name'        => $form_state['values']['name'],
+        'description' => $form_state['values']['description'],
+      ))->execute();
     drupal_set_message(t('The role has been added.'));
   }
   $form_state['redirect'] = 'admin/user/roles';
   return;
 }
+/**
+ * Implementation of confirmation form for role deletion
+ *
+ * @ingroup forms
+ * @see user_admin_role_delete_submit()
+ */
+function user_admin_role_delete($form_id, $rid) {
+  $role = db_query('SELECT * FROM {role} WHERE rid = :rid', array(':rid' => $rid))->fetchObject();
+
+  $form = array();
+  $form['rid'] = array(
+    '#type' => 'value',
+    '#value' => $rid,
+  );
+  $form = confirm_form($form,
+    t('Are you sure you want to delete the %title role?', array('%title' => $role->name)),
+    isset($_GET['destination']) ? $_GET['destination'] : 'admin/user/roles',
+    t('This action cannot be undone.'),
+    t('Delete role'),
+    t('Cancel')
+  );
+  return $form;
+}
+
+/**
+ * Submit handler for role deletion
+ *
+ * @ingroup forms
+ * @see user_admin_role_delete()
+ */
+function user_admin_role_delete_submit($form, &$form_state) {
+  db_query('DELETE FROM {role} WHERE rid = %d', $form_state['values']['rid']);
+  db_query('DELETE FROM {role_permission} WHERE rid = %d', $form_state['values']['rid']);
+  // Update the users who have this role set:
+  db_query('DELETE FROM {users_roles} WHERE rid = %d', $form_state['values']['rid']);
+  drupal_set_message(t('The role has been deleted.'));
+  $form_state['redirect'] = 'admin/user/roles';
+}
+
 
 /**
  * Theme user administration overview.
@@ -811,29 +848,34 @@ function theme_user_admin_account($form)
 
   return $output;
 }
-
 /**
- * Theme the new-role form.
+ * Displays the role admin overview page.
  *
- * @ingroup themeable
  */
-function theme_user_admin_new_role($form) {
-  $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => 2));
-  foreach (user_roles() as $rid => $name) {
-    $edit_permissions = l(t('edit permissions'), 'admin/user/permissions/' . $rid);
-    if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
-      $rows[] = array($name, l(t('edit role'), 'admin/user/roles/edit/' . $rid), $edit_permissions);
+function user_admin_role_list() {
+  $header = array(t('Name'), array('data' => t('Operations'), 'colspan' => 3));
+  $result = db_query("SELECT r.rid, r.name, r.description FROM {role} r");
+  while ($role = db_fetch_object($result)) {
+    if (!in_array($role->rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
+      $delete = l(t('delete'), 'admin/user/roles/delete/' . $role->rid);
     }
     else {
-      $rows[] = array($name, t('locked'), $edit_permissions);
+      $delete = t('required');
     }
+    $rows[] = array(
+      check_plain($role->name) . '<div class="description">'.filter_xss_admin($role->description) . '</div>',
+      l(t('permissions'), 'admin/user/permissions/' . $role->rid),
+      l(t('edit'), 'admin/user/roles/edit/' . $role->rid),
+      $delete,
+    );
   }
-  $rows[] = array(drupal_render($form['name']), array('data' => drupal_render($form['submit']), 'colspan' => 2));
-
-  $output = drupal_render_children($form);
-  $output .= theme('table', $header, $rows);
-
-  return $output;
+  $rows[] = array(
+    array(
+      'data' => l(t('Add role'), 'admin/user/roles/add' ),
+      'colspan' => 4,
+    ),
+  );
+  return theme('table', $header, $rows);
 }
 
 /**
Index: modules/user/user.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.install,v
retrieving revision 1.22
diff -u -p -r1.22 user.install
--- modules/user/user.install	13 Apr 2009 12:14:57 -0000	1.22
+++ modules/user/user.install	30 Apr 2009 15:19:35 -0000
@@ -80,6 +80,12 @@ function user_schema() {
         'default' => '',
         'description' => 'Unique role name.',
       ),
+      'description' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'default' => '',
+        'description' => t("Description of the role. Used for documenting roles' usage."),
+      ),
     ),
     'unique keys' => array(
       'name' => array('name'),
@@ -464,6 +470,28 @@ function user_update_7004(&$sandbox) {
 }
 
 /**
+ * Add descriptions to roles.
+ */
+function user_update_7005() {
+  $ret = array();
+
+  // Add description column.
+  $field = array(
+    'description' => t("Description of the role. Used for documenting roles' usage."),
+    'type' => 'varchar',
+    'length' => 255,
+    'default' => '',
+  );
+  db_add_field($ret, 'role', 'description', $field);
+
+  // Populate anonymous and autheticated role descriptions.
+  $ret[] = update_sql("UPDATE {role} SET description = 'Visitors to the website who have not yet logged in. Users have limited permissions on the site.' WHERE rid = " . DRUPAL_ANONYMOUS_RID);
+  $ret[] = update_sql("UPDATE {role} SET description = 'Any logged-in user. Other roles receive the permissions of this role, as well as any other roles to which they are assigned.' WHERE rid = " . DRUPAL_AUTHENTICATED_RID);
+
+  return $ret;
+}
+
+/**
  * @} End of "defgroup user-updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
  */
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.980
diff -u -p -r1.980 user.module
--- modules/user/user.module	26 Apr 2009 09:53:50 -0000	1.980
+++ modules/user/user.module	30 Apr 2009 15:19:35 -0000
@@ -1359,16 +1359,38 @@ function user_menu() {
   $items['admin/user/roles'] = array(
     'title' => 'Roles',
     'description' => 'List, edit, or add user roles.',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_admin_new_role'),
+    'page callback' => 'user_admin_role_list',
     'access arguments' => array('administer permissions'),
   );
-  $items['admin/user/roles/edit'] = array(
-    'title' => 'Edit role',
+  $items['admin/user/roles/list'] = array(
+    'title' => 'List',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+    'weight' => -10,
+  );
+  $items['admin/user/roles/add'] = array(
+    'title' => 'Add role',
+    'description' => 'List, edit, or add user roles.',
+    'page callback' => 'drupal_get_form',
     'page arguments' => array('user_admin_role'),
     'access arguments' => array('administer permissions'),
+    'type' => MENU_LOCAL_TASK,
+  );
+  $items['admin/user/roles/edit/%'] = array(
+    'title' => 'Edit role',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_admin_role', 4),
+    'access callback' => array('user_role_access'),
+    'access arguments' => array(3, 4),
     'type' => MENU_CALLBACK,
   );
+  $items['admin/user/roles/delete/%'] = array(
+    'title' => 'Delete role',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('user_admin_role_delete', 4),
+    'access callback' => array('user_role_access'),
+    'access arguments' => array(3, 4),
+  'type' => MENU_CALLBACK,
+  );
 
   $items['user/%user_uid_optional'] = array(
     'title' => 'My account',
@@ -2381,11 +2403,7 @@ function user_help($path, $arg) {
     case 'admin/user/permissions':
       return '<p>' . t('Permissions let you control what users can do on your site. Each user role (defined on the <a href="@role">user roles page</a>) has its own set of permissions. For example, you could give users classified as "Administrators" permission to "administer nodes" but deny this power to ordinary, "authenticated" users. You can use permissions to reveal new features to privileged users (those with subscriptions, for example). Permissions also allow trusted users to share the administrative burden of running a busy site.', array('@role' => url('admin/user/roles'))) . '</p>';
     case 'admin/user/roles':
-      return t('<p>Roles allow you to fine tune the security and administration of Drupal. A role defines a group of users that have certain privileges as defined in <a href="@permissions">user permissions</a>. Examples of roles include: anonymous user, authenticated user, moderator, administrator and so on. In this area you will define the <em>role names</em> of the various roles. To delete a role choose "edit".</p><p>By default, Drupal comes with two user roles:</p>
-      <ul>
-      <li>Anonymous user: this role is used for users that don\'t have a user account or that are not authenticated.</li>
-      <li>Authenticated user: this role is automatically granted to all logged in users.</li>
-      </ul>', array('@permissions' => url('admin/user/permissions')));
+      return t('<p>A role defines a group of users that share a common set of privileges as defined in <a href="@permissions">user permissions</a>. Examples of roles include: moderator, administrator and so on. Authenticated user and Anonymous user are two default roles that cannot be deleted.</p>', array('@permissions' => url('admin/user/permissions')));
     case 'admin/user/search':
       return '<p>' . t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username or e-mail address. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda@example.com".') . '</p>';
   }
@@ -2499,7 +2517,6 @@ function user_build_filter_query() {
 function user_forms() {
   $forms['user_admin_access_add_form']['callback'] = 'user_admin_access_form';
   $forms['user_admin_access_edit_form']['callback'] = 'user_admin_access_form';
-  $forms['user_admin_new_role']['callback'] = 'user_admin_role';
   return $forms;
 }
 
@@ -2909,4 +2926,25 @@ function _user_forms(&$edit, $account, $
 
   return empty($groups) ? FALSE : $groups;
 }
-
+/**
+ * Determine what operation can happen to which roles
+ * @param $op
+ *   The operation being performed on the role
+ *   - "edit"
+ *   - "delete"
+ * @param $rid
+ *   The unique id of the role
+ * @return
+ *   TRUE if the operation may be performed
+ */
+function user_role_access($op, $rid = NULL) {
+  $is_protected_role = ($rid == DRUPAL_ANONYMOUS_RID || $rid == DRUPAL_AUTHENTICATED_RID);
+  if(
+    !user_access('administer permissions') || //not allowed
+    !key_exists($rid, user_roles()) || //nonexistent role
+    ($op == 'delete' && $is_protected_role) //protected role
+    ){
+      return false;
+    }
+  return true;
+}
