? .project
? sites/all/themes/.DS_Store
? sites/default/.DS_Store
? sites/default/files
? sites/default/settings.php
Index: modules/comment/comment.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.test,v
retrieving revision 1.35
diff -u -p -r1.35 comment.test
--- modules/comment/comment.test	1 Jul 2009 12:06:21 -0000	1.35
+++ modules/comment/comment.test	12 Jul 2009 10:21:59 -0000
@@ -173,9 +173,9 @@ class CommentHelperCase extends DrupalWe
    */
   function setAnonymousUserComment($access_comments, $post_comments, $without_approval) {
     $edit = array();
-    $edit['1[access comments]'] = $access_comments;
-    $edit['1[post comments]'] = $post_comments;
-    $edit['1[post comments without approval]'] = $without_approval;
+    $edit['access__comments[1]'] = $access_comments;
+    $edit['post__comments[1]'] = $post_comments;
+    $edit['post__comments__without__approval[1]'] = $without_approval;
     $this->drupalPost('admin/user/permissions', $edit, t('Save permissions'));
     $this->assertText(t('The changes have been saved.'), t('Anonymous user comments ' . ($access_comments ? 'access comments' : 'not access comments'). '.'));
   }
Index: modules/contact/contact.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/contact/contact.test,v
retrieving revision 1.25
diff -u -p -r1.25 contact.test
--- modules/contact/contact.test	13 Jun 2009 20:40:07 -0000	1.25
+++ modules/contact/contact.test	12 Jul 2009 10:22:00 -0000
@@ -286,7 +286,7 @@ class ContactSitewideTestCase extends Dr
     // Create edit array from permission.
     $edit = array();
     foreach ($permissions as $name => $value) {
-      $edit[$rid . '[' . $name . ']'] = $value;
+      $edit[str_replace(' ', '__', $name) . '[' . $rid . ']'] = $value;
     }
 
     $this->drupalPost('admin/user/permissions', $edit, t('Save permissions'));
Index: modules/search/search.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.test,v
retrieving revision 1.24
diff -u -p -r1.24 search.test
--- modules/search/search.test	3 Jul 2009 19:21:54 -0000	1.24
+++ modules/search/search.test	12 Jul 2009 10:22:00 -0000
@@ -466,14 +466,14 @@ class SearchCommentTestCase extends Drup
     $this->drupalPost('admin/settings/formats/1', $edit, t('Save configuration'));
     // Allow anonymous users to search content.
     $edit = array(
-      DRUPAL_ANONYMOUS_RID . '[search content]' => 1,
+      'search__content[' . DRUPAL_ANONYMOUS_RID . ']' => 1,
       // @todo Comments are added to search index without checking first whether
       //   anonymous users are allowed to access comments.
-      DRUPAL_ANONYMOUS_RID . '[access comments]' => 1,
+      'access__comments[' . DRUPAL_ANONYMOUS_RID . ']' => 1,
       // @todo Without this permission, "Login or register to post comments" is
       //   added to the search index.  Comment.module is not guilty; that text
       //   seems to be added via node links.
-      DRUPAL_ANONYMOUS_RID . '[post comments]' => 1,
+      'post__comments[' . DRUPAL_ANONYMOUS_RID . ']' => 1,
     );
     $this->drupalPost('admin/user/permissions', $edit, t('Save permissions'));
 
Index: modules/user/user.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v
retrieving revision 1.64
diff -u -p -r1.64 user.admin.inc
--- modules/user/user.admin.inc	12 Jul 2009 08:36:35 -0000	1.64
+++ modules/user/user.admin.inc	12 Jul 2009 10:22:02 -0000
@@ -597,52 +597,60 @@ function user_admin_settings() {
  * @see theme_user_admin_permissions()
  */
 function user_admin_permissions($form_state, $rid = NULL) {
+  drupal_add_js(drupal_get_path('module', 'user') . '/user.js');
 
-  // Retrieve role names for columns.
-  $role_names = user_roles();
-  if (is_numeric($rid)) {
-    $role_names = array($rid => $role_names[$rid]);
-  }
-  // Fetch permissions for all roles or the one selected role.
-  $role_permissions = user_role_permissions($role_names);
+  // Fieldset to search the permissions form.
+  $form['search'] = array(
+    '#type' => 'fieldset',
+    '#weight' => -5,
+    '#collapsible' => FALSE,
+    '#title' => t('Search permissions'),
+  );
+
+  $form['search']['search_string'] = array(
+    '#type' => 'textfield',
+  );
 
-  // Store $role_names for use when saving the data.
-  $form['role_names'] = array(
-    '#type' => 'value',
-    '#value' => $role_names,
+  $form['search']['search_submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Search'),
+    '#submit' => array('user_admin_permissions_search_submit'),
+    // This uses a custom JS function to insert the new content into the page.
+    // See Drupal.behaviors.permissionsFormAhahSettings in user.js for details.
+    '#ahah' => array(
+      'callback' => 'user_admin_permissions_search_js',
+      'keypress' => TRUE,
+      'event' => 'click',
+    ),
   );
+
   // Render role/permission overview:
-  $options = array();
   $hide_descriptions = !system_admin_compact_mode();
+  $form['permissions'] = array(
+    '#type' => 'vertical_tabs',
+  );
+
+  if (!empty($form_state['storage']['search_string'])) {
+    $form['permissions']['search_pane'] = _user_admin_permissions_search_form($rid, $form_state['storage']['search_string']);
+  }
   foreach (module_implements('permission') as $module) {
     if ($permissions = module_invoke($module, 'permission')) {
+      $status = array();
       $info = drupal_parse_info_file(drupal_get_path('module', $module) . "/$module.info");
-      $form['permission'][] = array(
-        '#markup' => $info['name'],
-        '#id' => $module,
-        );
+      $form['permissions'][$module] = array(
+        '#type' => 'fieldset',
+        '#title' => $info['name'],
+        '#collapsible' => TRUE,
+        '#collapsed' => TRUE,
+        '#description' => '',
+      );
       foreach ($permissions as $perm => $perm_item) {
-        $options[$perm] = '';
-        $form['permission'][$perm] = array(
-          '#type' => 'item',
-          '#markup' => $perm_item['title'],
-          '#description' => $hide_descriptions ? $perm_item['description'] : NULL,
-        );
-        foreach ($role_names as $rid => $name) {
-          // Builds arrays for checked boxes for each role
-          if (isset($role_permissions[$rid][$perm])) {
-            $status[$rid][] = $perm;
-          }
-        }
+        $permission = str_replace(' ', '__', $perm);
+        $form['permissions'][$module][$permission] = _user_admin_permissions_build_row($perm, $perm_item, $rid);
       }
     }
   }
 
-  // Have to build checkboxes here after checkbox arrays are built
-  foreach ($role_names as $rid => $name) {
-    $form['checkboxes'][$rid] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => isset($status[$rid]) ? $status[$rid] : array());
-    $form['role_names'][$rid] = array('#markup' => $name, '#tree' => TRUE);
-  }
   $form['submit'] = array('#type' => 'submit', '#value' => t('Save permissions'));
 
   $form['#attached_js'] = array(drupal_get_path('module', 'user') . '/user.permissions.js');
@@ -651,25 +659,136 @@ function user_admin_permissions($form_st
 }
 
 /**
+ * Build a row for the user permissions page.
+ */
+function _user_admin_permissions_build_row($perm, $perm_item, $rid) {
+  // Retrieve role names.
+  $role_names = user_roles();
+  if (is_numeric($rid)) {
+    $role_names = array($rid => $role_names[$rid]);
+  }
+  // Fetch permissions for all roles or the one selected role.
+  $role_permissions = user_role_permissions($role_names);
+
+  $hide_descriptions = !system_admin_compact_mode();
+  $form = array(
+    '#tree' => TRUE,
+    '#theme' => 'user_admin_permissions_fieldset',
+    '#header' => array(),
+  );
+  $form['name'] = array(
+    '#markup' => $perm_item['title'],
+  );
+  $form['description'] = array(
+    '#markup' => $hide_descriptions ? $perm_item['description'] : NULL,
+  );
+  foreach ($role_names as $rid => $name) {
+    $granted = FALSE;
+    // Builds arrays for checked boxes for each role
+    if (isset($role_permissions[$rid][$perm])) {
+      $granted = TRUE;
+    }
+    $form[$rid] = array(
+      '#type' => 'checkbox', 
+      '#title' => $name,
+      '#default_value' => $granted,
+    );
+  }
+  return $form;
+}
+
+/**
+ * Submit callback for the search button on the modules form.
+ *
+ * If a search string is present, store it in $form_state['storage'].
+ */
+function user_admin_permissions_search_submit($form, &$form_state) {
+  if (isset($form_state['values']['search_string'])) {
+    $form_state['storage']['search_string'] = $form_state['values']['search_string'];
+  }
+  else {
+    unset($form_state['storage']['search_string']);
+  }
+}
+
+/**
+ * AHAH callback for the search button on the modules form.
+ */
+function user_admin_permissions_search_js($form, &$form_state) {
+  if (isset($form['permissions']['search_pane'])) {
+    $search_form = $form['permissions']['search_pane'];
+    drupal_json(array('status' => TRUE, 'data' => drupal_render($search_form)));
+  }
+}
+
+/**
+ * Creates the search result fieldset for the permissions form.
+ *
+ * This returns a fieldset similar to the normal permissions category fieldsets,
+ * but containing permissions whose names or descriptions match $search_string.
+ */
+function _user_admin_permissions_search_form($rid, $search_string) {
+  $permissions = array();
+  // Get all available permissions.
+  foreach (module_implements('permission') as $module) {
+    if ($module_permissions = module_invoke($module, 'permission')) {
+      $permissions += $module_permissions;
+    }
+  }
+
+  $search_form = array(
+    '#type' => 'fieldset',
+    '#weight' => 9999,
+    '#title' => t('Search results'),
+  );
+
+  if (!empty($search_string)) {
+    // Iterate over the permissions, and add rows for matching names or
+    // descriptions.
+    foreach ($permissions as $perm => $perm_item) {
+      if (stripos($perm_item['title'], $search_string) !== FALSE ||
+          stripos($perm_item['description'], $search_string) !== FALSE) {
+        $permission = str_replace(' ', '__', $perm);
+        $search_form[$permission] = _user_admin_permissions_build_row($perm, $perm_item, $rid);
+        $search_form[$permission] += array(
+          '#theme' => 'user_admin_permissions_fieldset',
+          '#header' => array(),
+        );
+      }
+    }
+  }
+
+  if (!element_children($search_form)) {
+    $search_form['info']['#markup'] = t('Your search did not return any results.');
+  }
+
+  return $search_form;
+}
+
+/**
  * Save permissions selected on the administer permissions page.
  *
  * @see user_admin_permissions()
  */
 function user_admin_permissions_submit($form, &$form_state) {
-  foreach ($form_state['values']['role_names'] as $rid => $name) {
-    $checked = array_filter($form_state['values'][$rid]);
-    // Delete existing permissions for the role. This handles "unchecking" checkboxes.
-    db_delete('role_permission')
-      ->condition('rid', $rid)
-      ->execute();
-    $query = db_insert('role_permission')->fields(array('rid', 'permission'));
-    foreach ($checked as $permission) {
-      $query->values(array(
-        'rid' => $rid,
-        'permission' => $permission,
-      ));
-    }
-    $query->execute();
+  foreach ($form_state['values'] as $perm => $values) {
+  	if (is_array($form_state['values'][$perm])) {
+      $permission_real_name = str_replace('__', ' ', $perm);
+      $checked = array_filter($form_state['values'][$perm]);
+      // Delete existing grants for this permission. This handles "unchecking" checkboxes.
+      db_delete('role_permission')
+        ->condition('permission', $permission_real_name)
+        ->execute();
+      // Insert new grants.
+      $query = db_insert('role_permission')->fields(array('rid', 'permission'));
+      foreach ($checked as $rid => $value) {
+      	$query->values(array(
+      	  'rid' => $rid,
+      	  'permission' => $permission_real_name,
+      	));
+      }
+      $query->execute();
+  	}
   }
 
   drupal_set_message(t('The changes have been saved.'));
@@ -679,36 +798,40 @@ function user_admin_permissions_submit($
 }
 
 /**
+ * Theme callback for the admin permissions form.
+ *
+ * @param $form
+ *   An associative array containing the structure of the form.
+ * @ingroup themeable
+ */
+function theme_user_admin_permissions_fieldset($form) {
+  $rows = array();
+  $output = '';
+  $output .= '<strong>' . drupal_render($form['name']) . '</strong>';
+  $output .= '<div class="permission-wrapper">';
+  $output .= '<div class="description">' . drupal_render($form['description']) . '</div>';
+  foreach (element_children($form) as $key) {
+  	if (is_numeric($key)) {
+  	  $permission = $form[$key];
+      $row = array();
+      $row[] = array('data' => drupal_render($permission));
+    	$rows[] = $row;
+  	}
+  }
+  $output .= theme('table', $form['#header'], $rows);
+  $output .= '</div>';
+  return $output;
+}
+
+/**
  * Theme the administer permissions page.
  *
  * @ingroup themeable
  */
 function theme_user_admin_permissions($form) {
-  $roles = user_roles();
-  foreach (element_children($form['permission']) as $key) {
-    $row = array();
-    // Module name
-    if (is_numeric($key)) {
-      $row[] = array('data' => drupal_render($form['permission'][$key]), 'class' => 'module', 'id' => 'module-' . $form['permission'][$key]['#id'], 'colspan' => count($form['role_names']['#value']) + 1);
-    }
-    else {
-      // Permission row.
-      $row[] = array(
-        'data' => drupal_render($form['permission'][$key]),
-        'class' => 'permission',
-      );
-      foreach (element_children($form['checkboxes']) as $rid) {
-        $row[] = array('data' => drupal_render($form['checkboxes'][$rid][$key]), 'class' => 'checkbox', 'title' => $roles[$rid] . ' : ' . t($key));
-      }
-    }
-    $rows[] = $row;
-  }
-  $header[] = (t('Permission'));
-  foreach (element_children($form['role_names']) as $rid) {
-    $header[] = array('data' => drupal_render($form['role_names'][$rid]), 'class' => 'checkbox');
-  }
   $output = theme('system_compact_link');
-  $output .= theme('table', $header, $rows, array('id' => 'permissions'));
+  $output .= drupal_render($form['search']);
+  $output .= drupal_render($form['permissions']);
   $output .= drupal_render_children($form);
   return $output;
 }
Index: modules/user/user.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.css,v
retrieving revision 1.11
diff -u -p -r1.11 user.css
--- modules/user/user.css	14 Jun 2009 08:04:25 -0000	1.11
+++ modules/user/user.css	12 Jul 2009 10:22:02 -0000
@@ -50,3 +50,24 @@
 .profile dd {
   margin: 0 0 1em 0;
 }
+
+/**
+ * Formatting of the user permissions form.
+ */
+#user-admin-permissions #edit-search {
+  margin-bottom: 0;
+  margin-right: 5%;
+  border-bottom: none;
+}
+
+#user-admin-permissions #edit-search .search-string-wrapper, #user-admin-permissions #edit-search #edit-search-submit {
+  float: left;
+}
+
+#user-admin-permissions #edit-search .search-string-wrapper {
+  margin: 0 1em 0 0;
+}
+
+#user-admin-permissions div.vertical-tabs {
+  margin-top: 0;
+}
Index: modules/user/user.js
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.js,v
retrieving revision 1.15
diff -u -p -r1.15 user.js
--- modules/user/user.js	13 Jun 2009 20:40:09 -0000	1.15
+++ modules/user/user.js	12 Jul 2009 10:22:03 -0000
@@ -1,6 +1,8 @@
 // $Id: user.js,v 1.15 2009/06/13 20:40:09 dries Exp $
 (function ($) {
 
+Drupal.ahah = Drupal.ahah || {};
+
 /**
  * Attach handlers to evaluate the strength of any password fields and to check
  * that its confirmation is correct.
@@ -172,4 +174,72 @@ Drupal.behaviors.userSettings = {
   }
 };
 
+/**
+ * AHAH insertNewContent callback for the search button on the user permissions form.
+ *
+ * If no search fieldset is present, this inserts the search fieldset into
+ * the form and adds a vertical tab for it. If there is already a search fieldset,
+ * it is replaced by the new one.
+ */
+Drupal.behaviors.permissionsFormAhahSettings = {
+  attach: function(context, settings) {
+    if (Drupal.ahah['edit-search-submit']) {
+      Drupal.ahah['edit-search-submit'].insertNewContent = function(response, status) {
+        new_content = $(response.data);
+  
+        // Check if there is already a search tab present, and if so, replace it with
+        // the new one.
+        // We copy over the existing verticalTab data property to reduce flickering.
+        if ($('#user-admin-permissions #edit-search-pane').size()) {
+          var tab = $('#edit-search-pane').data('verticalTab')
+          tab.fieldset = $(new_content);
+          $('#user-admin-permissions #edit-search-pane').replaceWith(new_content);
+        }
+        // Otherwise, append the search fieldset to the wrapper and add a vertical tab for it.
+        else {
+          $('#user-admin-permissions .vertical-tabs-panes').append(new_content);
+          var tab = new Drupal.verticalTab({ title: $('> legend', new_content).text(), fieldset: $(new_content) });
+          var list = new_content.parents().find('.vertical-tabs-panes').siblings('ul.vertical-tabs-list');
+          list.append(tab.item);
+        }
+  
+        // Add the tab behavior and styling to the new fieldset.
+        $(new_content)
+          .addClass('vertical-tabs-pane')
+          .data('verticalTab', tab);
+  
+        // Give the search tab the focus and update the description.
+        tab.focus();
+        Drupal.permissionsFormSetFieldsetSummary(tab.fieldset);
+        tab.updateSummary();
+
+        // Attach behaviors to the new content.
+        Drupal.attachBehaviors(new_content);
+      }
+    }
+  }
+};
+
+/**
+ * Assing the vertical tab callback to update the description to all fieldsets
+ * on the user permissions form.
+ */
+Drupal.behaviors.permissionsFormFieldsetSummaries = {
+  attach: function(context) {
+    $('#user-admin-permissions .vertical-tabs-panes > fieldset', context).each( function() {
+      Drupal.permissionsFormSetFieldsetSummary(this);
+    });
+  }
+};
+
+/**
+ * Set the summary for a fieldset on the user permissions form.
+ */
+Drupal.permissionsFormSetFieldsetSummary = function(fieldset) {
+  $(fieldset).setSummary(function(context) {
+    permissions = $('.permission-wrapper', context).size();
+    return Drupal.formatPlural(permissions, '1 permission.', '!permissions permissions.', { '!permissions': permissions });
+  });
+};
+
 })(jQuery);
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.1011
diff -u -p -r1.1011 user.module
--- modules/user/user.module	12 Jul 2009 08:36:35 -0000	1.1011
+++ modules/user/user.module	12 Jul 2009 10:22:07 -0000
@@ -61,6 +61,10 @@ function user_theme() {
       'arguments' => array('form' => NULL),
       'file' => 'user.admin.inc',
     ),
+    'user_admin_permissions_fieldset' => array(
+      'arguments' => array('form' => NULL),
+      'file' => 'user.admin.inc',
+    ),
     'user_admin_new_role' => array(
       'arguments' => array('form' => NULL),
       'file' => 'user.admin.inc',
Index: modules/user/user.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.test,v
retrieving revision 1.45
diff -u -p -r1.45 user.test
--- modules/user/user.test	12 Jul 2009 08:36:35 -0000	1.45
+++ modules/user/user.test	12 Jul 2009 10:22:09 -0000
@@ -752,7 +752,7 @@ class UserPermissionsTestCase extends Dr
     // Add a permission.
     $this->assertFalse(user_access('administer nodes', $account, TRUE), t('User does not have "administer nodes" permission.'));
     $edit = array();
-    $edit[$rid . '[administer nodes]'] = TRUE;
+    $edit['administer__nodes[' . $rid . ']'] = TRUE;
     $this->drupalPost('admin/user/permissions', $edit, t('Save permissions'));
     $this->assertText(t('The changes have been saved.'), t('Successful save message displayed.'));
     $this->assertTrue(user_access('administer nodes', $account, TRUE), t('User now has "administer nodes" permission.'));
@@ -760,7 +760,7 @@ class UserPermissionsTestCase extends Dr
     // Remove a permission.
     $this->assertTrue(user_access('access user profiles', $account, TRUE), t('User has "access user profiles" permission.'));
     $edit = array();
-    $edit[$rid . '[access user profiles]'] = FALSE;
+    $edit['access__user__profiles[' . $rid . ']'] = FALSE;
     $this->drupalPost('admin/user/permissions', $edit, t('Save permissions'));
     $this->assertText(t('The changes have been saved.'), t('Successful save message displayed.'));
     $this->assertFalse(user_access('access user profiles', $account, TRUE), t('User no longer has "access user profiles" permission.'));
