Index: advuser.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advuser/advuser.module,v
retrieving revision 1.14.2.7.2.7
diff -u -p -r1.14.2.7.2.7 advuser.module
--- advuser.module	11 Apr 2010 22:31:53 -0000	1.14.2.7.2.7
+++ advuser.module	14 Apr 2010 22:15:00 -0000
@@ -40,6 +40,40 @@ Language: %user_language
 Administor user at %uri for %site");
 
 /**
+ * Implementation of hook_help().
+ */
+function advuser_help($path, $arg) {
+  switch ($path) {
+    case 'admin/help#advuser': {
+      $output = '<p>';
+      $output .= t('This module provides greater control of filtering of the
+users and allows for persistent selection of users between multiple pages of
+user data.  Besides the normal actions of block, unblock, delete, role
+assignment and role unassignment you can also select all filtered users,
+deselect all users and email the selected users.');
+      $output .= '</p><p>';
+      $output .= t('The filtering selection is a multipart form where you
+first select the field you want to filter by.  Lets use the mail address for
+example as the selected field.  You then press Continue and you choose the
+operator for the data that you enter then you click Filter.  If you chose the
+wrong field you can go back to the field selection by clicking the Back button.
+Once you have one filter in place you can refine the filter with and/or
+conjunctors and another field type or the same field type.');
+      $output .= '</p>';
+    } break;
+    case 'admin/user/user/advuser': {
+      $output = '<p>';
+      $output .= t('Advanced User module provides filtering of users with 
+persistent selections of users between mulitple pages of the users list.  The
+module also adds an action for email to be sent to the selected user set as
+well as the normal actions already available.');
+      $output .= '</p>';
+    } break;
+  }
+  return $output;
+}
+
+/**
  * Implementation of hook_perm().
  */
 function advuser_perm() {
@@ -69,8 +103,8 @@ function advuser_menu() {
   $items['admin/user/user/advuser'] = array(
     'title' => t('Advanced'),
     'description' => t('List, add, edit and email users.'),
-    'page callback' => 'drupal_get_form', 
-    'page arguments' => array('advuser_admin'), 
+    'page callback' => 'advuser_admin', 
+    'page arguments' => array('list'), 
     'access callback' => 'advuser_admin_access',
     'access arguments' => array('access advuser', 'administer users'),
     'type' => MENU_LOCAL_TASK,
@@ -99,7 +133,7 @@ function advuser_admin_access () {
  */
 function advuser_theme() {
   return array(
-    'advuser_admin' => array(
+    'advuser_admin_account' => array(
       'arguments' => array('form' => NULL),
     ),
   );
@@ -108,12 +142,79 @@ function advuser_theme() {
 /**
  * Email functionality
  */
-function advuser_advuser_operations() {
+function advuser_advuser_operations($form_state = array()) {
   $operations = array(
+    'saveselect' => array(
+      'label' => t('Save selection criteria'),
+    ),
+    'selectall' => array(
+      'label' => t('Select all filtered users'),
+    ),
+    'deselectall' => array(
+      'label' => t('Deselect all users'),
+    ),
     'email' => array(
-    'label' => t('Email selected users')
-    )
+      'label' => t('Email selected users'),
+    ),
+    'block' => array(
+      'label' => t('Block the selected users'),
+    ),
+    'unblock' => array(
+      'label' => t('Unblock the selected users'),
+    ),
+    'delete' => array(
+      'label' => t('Delete the selected users'),
+    ),
   );
+
+  // Copied directly from user.module user_user_operations.
+  if (user_access('administer permissions')) {
+    $roles = user_roles(TRUE);
+    unset($roles[DRUPAL_AUTHENTICATED_RID]);  // Can't edit authenticated role.
+
+    $add_roles = array();
+    foreach ($roles as $key => $value) {
+      $add_roles['add_role-'. $key] = $value;
+    }
+
+    $remove_roles = array();
+    foreach ($roles as $key => $value) {
+      $remove_roles['remove_role-'. $key] = $value;
+    }
+
+    if (count($roles)) {
+      $role_operations = array(
+        t('Add a role to the selected users') => array(
+          'label' => $add_roles,
+        ),
+        t('Remove a role from the selected users') => array(
+          'label' => $remove_roles,
+        ),
+      );
+
+      $operations += $role_operations;
+    }
+  }
+
+  // If the form has been posted, we need to insert the proper data for
+  // role editing if necessary.
+  if (!empty($form_state['submitted'])) {
+    $operation_rid = explode('-', $form_state['values']['operation']);
+    $operation = $operation_rid[0];
+    if ($operation == 'add_role' || $operation == 'remove_role') {
+      $rid = $operation_rid[1];
+      if (user_access('administer permissions')) {
+        $operations[$form_state['values']['operation']] = array(
+          'callback' => 'advuser_multiple_role_edit',
+          'callback arguments' => array($operation, $rid),
+        );
+      }
+      else {
+        watchdog('security', 'Detected malicious attempt to alter protected user fields.', array(), WATCHDOG_WARNING);
+        return;
+      }
+    }
+  }
   return $operations;
 }
 
@@ -315,80 +416,120 @@ function advuser_user_roles() {
 }
 
 /**
+ * Get the sql query string.
+ */
+function advuser_build_query ($type = 'users') {
+  $filter = advuser_build_filter_query();
+
+  // Array used for user profile DB query joins.
+  $pf = array();
+
+  foreach (advuser_profile_fields() as $field) {
+    if (isset($field->name)) {
+      $pf[] = "LEFT JOIN {profile_values} $field->name ON $field->name.fid = $field->fid AND $field->name.uid = u.uid";
+    }
+  }
+
+  $filter['join'] .= count($pf) ? ' ' . implode(' ', array_unique($pf)) : NULL;
+
+  switch ($type) {
+    case 'users': {
+      $sql = 'SELECT DISTINCT u.uid, u.name, u.mail, u.status, u.created, u.access FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
+    } break;
+    case 'uid': {
+      $sql = 'SELECT DISTINCT u.uid as uid FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
+    } break;
+    case 'count': {
+      $sql = 'SELECT COUNT(DISTINCT u.uid) FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
+    } break;
+  }
+
+  return $sql;
+}
+
+/**
  * Build query for advuser administration filters based on session.
  */
-function advuser_build_filter_query(&$form_state) {
-  $filters = advuser_filters();
+function advuser_build_filter_query($reset = FALSE) {
+  static $filter_array = array();
+  if (empty($filter_array) || $reset) {
+    $advuser = &$_SESSION['advuser'];
+    $filters = &$advuser['filters'];
+
+    // Build query
+    $where = $args = $join = array();
+
+    foreach ($filters as $filter) {
+      list($key, $op, $qop, $value) = array_values($filter);
+      // This checks to see if this permission filter is an enabled permission 
+      // for the authenticated role.  If so, then all users would be listed, and 
+      // we can skip adding it to the filter query.
+      switch ($key) {
+        case 'permission': {
+          $account = new stdClass();
+          $account->uid = 'advuser_filter';
+          $account->roles = array(DRUPAL_AUTHENTICATED_RID => 1);
+          if (user_access($value, $account)) {
+            continue;
+          }
+        } break;
+        case 'created':
+        case 'last_access': {
+          $value = strtotime($value);
+        } break;
+      }
 
-  // Build query
-  $where = $args = $join = array();
+      $arg_prefix = $arg_suffix = NULL;
+      switch ($qop) {
+        case 'NOT LIKE':
+        case 'LIKE': {
+          $arg_prefix = $arg_suffix = '%';
+        } break;
+        case 'BEGINS WITH': {
+          $qop = 'LIKE';
+          $arg_suffix = '%';
+        } break;
+        case 'ENDS WITH': {
+          $qop = 'LIKE';
+          $arg_prefix = '%';
+        } break;
+      }
 
-  foreach ($form_state['storage']['filters'] as $filter) {
-    list($key, $op, $qop, $value) = array_values($filter);
-    // This checks to see if this permission filter is an enabled permission 
-    // for the authenticated role.  If so, then all users would be listed, and 
-    // we can skip adding it to the filter query.
-    switch ($key) {
-      case 'permission': {
-        $account = new stdClass();
-        $account->uid = 'advuser_filter';
-        $account->roles = array(DRUPAL_AUTHENTICATED_RID => 1);
-        if (user_access($value, $account)) {
-          continue;
+      switch ($qop) {
+        case '!=':
+        case 'NOT LIKE': {
+          $in = 'NOT IN';
+          $eq = '!=';
+          $andor = 'AND';
+        } break;
+        default: {
+          $in = 'IN';
+          $eq = '=';
+          $andor = 'OR';
         }
-      } break;
-      case 'created':
-      case 'last_access': {
-        $value = strtotime($value);
-      } break;
-    }
-
-    $arg_prefix = $arg_suffix = NULL;
-    switch ($qop) {
-      case 'NOT LIKE':
-      case 'LIKE': {
-        $arg_prefix = $arg_suffix = '%';
-      } break;
-      case 'BEGINS WITH': {
-        $qop = 'LIKE';
-        $arg_suffix = '%';
-      } break;
-      case 'ENDS WITH': {
-        $qop = 'LIKE';
-        $arg_prefix = '%';
-      } break;
-    }
-
-    switch ($qop) {
-      case '!=':
-      case 'NOT LIKE': {
-        $in = 'NOT IN';
-        $eq = '!=';
-        $andor = 'AND';
-      } break;
-      default: {
-        $in = 'IN';
-        $eq = '=';
-        $andor = 'OR';
       }
-    }
 
-    $_where = $op.' '.str_ireplace("%op", $qop, $filters[$key]['where']);
-    $_where = str_ireplace("%eq", $eq, $_where);
-    $_where = str_ireplace("%andor", $andor, $_where);
-    $where[] = str_ireplace("%in", $in, $_where);
-    $args[] = $arg_prefix . $value . $arg_suffix;
-    $join[] = $filters[$key]['join'];
-  }
+    $advuser_filters = advuser_filters();
 
-  $where = count($where) ? 'AND ('. implode(' ', $where) . ')' : '';
-  $join = count($join) ? ' '. implode(' ', array_unique($join)) : '';
+      $_where = $op.' '.str_ireplace("%op", $qop, $advuser_filters[$key]['where']);
+      $_where = str_ireplace("%eq", $eq, $_where);
+      $_where = str_ireplace("%andor", $andor, $_where);
+      $where[] = str_ireplace("%in", $in, $_where);
+      $args[] = $arg_prefix . $value . $arg_suffix;
+      $join[] = $advuser_filters[$key]['join'];
+    }
+
+    $where = count($where) ? 'AND ('. implode(' ', $where) . ')' : '';
+    $join = count($join) ? ' '. implode(' ', array_unique($join)) : '';
+
+    $filter_array = array(
+      'where' => $where,
+      'join' => $join,
+      'args' => $args,
+    );
+  }
 
-  return array(
-    'where' => $where,
-    'join' => $join,
-    'args' => $args,
-  );
+  return $filter_array;
 }
 
 /**
@@ -495,4 +636,73 @@ function advuser_filters() {
   return $filters;
 }
 
+/**
+ * Callback function for admin mass adding/deleting a user role.
+ */
+function advuser_multiple_role_edit($accounts, $operation, $rid) {
+  // The role name is not necessary as user_save() will reload the user
+  // object, but some modules' hook_user() may look at this first.
+  $advuser = &$_SESSION['advuser'];
+  $accounts = &$advuser['accounts'];
+  $selectall = &$advuser['selectall'];
+  $deselected = &$advuser['deselected'];
+
+  $filter = advuser_build_filter_query();
+
+  $role_name = db_result(db_query('SELECT name FROM {role} WHERE rid = %d', $rid));
+
+  switch ($operation) {
+    case 'add_role': {
+      if ($selectall) {
+        $sql = advuser_build_query('uid');
+        $result = db_query($sql, $filter['args']);
+        while ($user = db_fetch_array($result)) {
+          $account = user_load($user);
+          if ($account !== FALSE && !isset($account->roles[$rid])) {
+            $roles = $account->roles + array($rid => $role_name);
+            user_save($account, array('roles' => $roles));
+          }
+        }
+        $selectall = FALSE;
+      }
+      else {
+        foreach ($accounts as $uid) {
+          $account = user_load(array('uid' => (int)$uid));
+          // Skip adding the role to the user if they already have it.
+          if ($account !== FALSE && !isset($account->roles[$rid])) {
+            $roles = $account->roles + array($rid => $role_name);
+            user_save($account, array('roles' => $roles));
+          }
+          unset($accounts[$uid]);
+        }
+      }
+    } break;
+    case 'remove_role': {
+      if ($selectall) {
+        $sql = advuser_build_query('uid');
+        $result = db_query($sql, $filter['args']);
+        while ($user = db_fetch_array($result)) {
+          $account = user_load($user);
+          if ($account !== FALSE && isset($account->roles[$rid])) {
+            $roles = array_diff($account->roles, array($rid => $role_name));
+            user_save($account, array('roles' => $roles));
+          }
+        }
+        $selectall = FALSE;
+      }
+      else {
+        foreach ($accounts as $uid) {
+          $account = user_load(array('uid' => (int)$uid));
+          // Skip removing the role from the user if they already don't have it.
+          if ($account !== FALSE && isset($account->roles[$rid])) {
+            $roles = array_diff($account->roles, array($rid => $role_name));
+            user_save($account, array('roles' => $roles));
+          }
+          unset($accounts[$uid]);
+        }
+      }
+    } break;
+  }
+}
+
 // vim:ft=php:sts=2:sw=2:ts=2:et:ai:sta:ff=unix
Index: forms/advuser_admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advuser/forms/Attic/advuser_admin.inc,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 advuser_admin.inc
--- forms/advuser_admin.inc	10 Apr 2010 17:47:36 -0000	1.1.2.2
+++ forms/advuser_admin.inc	14 Apr 2010 22:15:00 -0000
@@ -2,129 +2,58 @@
 
 require_once 'advuser_filter_ui.inc';
 
-function advuser_admin(&$form_state) {
-  $function = &$form_state['storage']['function'];
-
-  if ($_POST['accounts'] && $_POST['operation'] == 'delete') {
-    $function = 'advuser_multiple_delete_confirm';
-    require_once "${function}.inc";
-    return $function($form_state);
-  } 
-  elseif ($_POST['accounts'] && $_POST['operation'] == 'email') {
-    $function = 'advuser_multiple_email_confirm';
-    require_once "${function}.inc";
-    return $function($form_state);
-  } 
-  else {
-    $function = 'advuser_filter_ui';
-    $form = $function($form_state);
-    $function = 'advuser_admin_account';
-    require_once "${function}.inc";
-    $form2 = $function($form_state);
-    $function = 'advuser_admin';
-    return array_merge_recursive($form, $form2);
-  }
-
-  return array();
-}
-
-function advuser_admin_validate(&$form, &$form_state) {
-  $function = &$form_state['storage']['function'];
-  $validate = "${function}_validate";
-  if (function_exists($validate) && __FUNCTION__ != $validate) {
-    return $validate($form, $form_state);
-  }
-}
-
-function advuser_admin_submit(&$form, &$form_state) {
-  $function = &$form_state['storage']['function'];
-  $submit = "${function}_submit";
-  if (function_exists($submit) && __FUNCTION__ != $submit) {
-    return $submit($form, $form_state);
-  }
-}
-
 /**
- * Theme user administration overview.
+ * Callback form controller.
+ *
+ * This form is cannot be called by drupal_get_form but returns forms that are.
+ * Because it is not loaded by drupal_get_form then $form_state isn't passed
+ * to it.
  */
-function theme_advuser_admin(&$form) {
-  static $profile_fields = array();
-  // Overview table:
-  $header = array(
-    theme('table_select_header_cell'),
-    array('data' => t('Username'), 'field' => 'u.name'),
-    array('data' => t('Mail'), 'field' => 'u.mail'),
-    array('data' => t('Status'), 'field' => 'u.status'),
-  );
-  $roles = advuser_user_roles();
-  if (count($roles)) {
-    $header[] = t('Roles');
-  }
-  $header = array_merge($header, array(
-    array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
-    array('data' => t('Last access'), 'field' => 'u.access'),
-  ));
-
-  $ff = array();
-  foreach (advuser_profile_fields() as $field) {
-    $ff[] = array('data'=>t($field->title), 'field'=>$field->name);
-  }
-  $header = array_merge($header, $ff);
-  $header[] = t('Operations');
+function advuser_admin() {
+  $output = NULL;
 
-  $output = drupal_render($form['filters']);
-  $output .= drupal_render($form['options']);
-  if (isset($form['name']) && is_array($form['name'])) {
-    foreach (element_children($form['name']) as $key) {
-      $row = array(
-        drupal_render($form['accounts'][$key]),
-        drupal_render($form['name'][$key]),
-        drupal_render($form['mail'][$key]),
-        drupal_render($form['status'][$key]),
-      );
-      $roles = advuser_user_roles();
-      if (count($roles)) {
-        $row[] = drupal_render($form['roles'][$key]);
-      }
-      $row = array_merge($row, array(
-        drupal_render($form['member_for'][$key]),
-        drupal_render($form['last_access'][$key]),
-      ));
-
-      if (module_exists('profile')) {
-        $fields = variable_get('advuser_profile_fields', NULL);
-
-        if (is_array($fields)) {
-          foreach ( $fields as $fid => $value) {
-            if ( $value ) {
-              if (empty($profile_fields[$fid])) {
-
-                $field = db_fetch_object(db_query('SELECT * FROM {profile_fields} WHERE fid = %d', $fid));
-                $profile_fields[$fid] = $field;
-              }
-              else {
-                $field = $profile_fields[$fid];
-              }
-              $row[] = drupal_render($form[$field->name][$key]);
-            }
-          }
-        }
-      }
-      $row[] = drupal_render($form['operations'][$key]);
-      $rows[] = $row;
+  // Control the persistent data in the session.
+  $advuser = &$_SESSION['advuser'];
+  if (!isset($advuser)) {
+    $advuser = array('accounts' => array(), 'operation' => NULL, 'selectall' => FALSE);
+  }
+
+  $accounts = &$advuser['accounts'];
+  $operation = &$advuser['operation'];
+  $return = &$advuser['return'];
+  $selectall = &$advuser['selectall'];
+  $post = &$_POST;
+
+  if (isset($post['operation'])) {
+    $operation = $post['operation'];
+  }
+
+  if ($accounts && !$return) {
+    switch ($operation) {
+      case 'delete': {
+        $return = TRUE;
+        $form = 'advuser_multiple_delete_confirm';
+        require_once "${form}.inc";
+        $output = drupal_get_form($form);
+      } break;
+      case 'email': {
+        $return = TRUE;
+        $form = 'advuser_multiple_email_confirm';
+        require_once "${form}.inc";
+        $output = drupal_get_form($form);
+      } break;
     }
   }
-  else  {
-    $rows[] = array(array('data' => t('No users available.'), 'colspan' => '7'));
-  }
 
-  $output .= theme('table', $header, $rows);
-  if ($form['pager']['#value']) {
-    $output .= drupal_render($form['pager']);
+  if (!isset($output)) {
+    $form = 'advuser_filter_ui';
+    $output = drupal_get_form($form);
+    $form = 'advuser_admin_account';
+    require_once "${form}.inc";
+    $output .= drupal_get_form($form);
+    $return = FALSE;
   }
 
-  $output .= drupal_render($form);
-
   return $output;
 }
 
Index: forms/advuser_admin_account.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advuser/forms/Attic/advuser_admin_account.inc,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 advuser_admin_account.inc
--- forms/advuser_admin_account.inc	10 Apr 2010 17:47:36 -0000	1.1.2.2
+++ forms/advuser_admin_account.inc	14 Apr 2010 22:15:00 -0000
@@ -1,64 +1,77 @@
 <?php
 
+/**
+ * Provide the list of filtered users.
+ */
 function advuser_admin_account(&$form_state) {
-  $filter = advuser_build_filter_query($form_state);
+  // Get the filters for the user data.
+  $filter = advuser_build_filter_query();
+
+  // Get the list of user roles to be displayed.
+  $roles = advuser_user_roles();
+
+  // Array used for user profile title and value display in list.
+  $ff = array();
+
+  foreach (advuser_profile_fields() as $field) {
+    if (isset($field->name)) {
+      $ff[] = array('data'=>t($field->title), 'field'=>"$field->name.value");
+    }
+  }
+
   $header = array(
     array(),
     array('data' => t('Username'), 'field' => 'u.name'),
     array('data' => t('Mail'), 'field' => 'u.mail'),
     array('data' => t('Status'), 'field' => 'u.status'),
   );
-  $roles = advuser_user_roles();
+
   if (count($roles)) {
     $header[] = t('Roles');
   }
+
   $header = array_merge($header, array(
     array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
     array('data' => t('Last access'), 'field' => 'u.access'),
   ));
 
-  $query = '';
-  $ff = array();
-  $pf = array();
-  foreach (advuser_profile_fields() as $field) {
-    if (isset($field->name)) {
-      $ff[] = array('data'=>t($field->title), 'field'=>"$field->name.value");
-      $pf[] = "LEFT JOIN {profile_values} $field->name ON $field->name.fid = $field->fid AND $field->name.uid = u.uid";
-    }
-  }
   $header = array_merge($header, $ff);
+
   $header[] = t('Operations');
 
-  $filter['join'] .= count($pf) ? ' ' . implode(' ', array_unique($pf)) : NULL;
+  $sql = advuser_build_query();
+  $sql .= tablesort_sql($header);
 
-  $sql = 'SELECT DISTINCT u.uid, u.name, u.mail, u.status, u.created, u.access '.$pquery.' FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
+  $query_count = advuser_build_query('count');
 
-  $sql .= tablesort_sql($header);
-  $query_count = 'SELECT COUNT(DISTINCT u.uid) FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
   $result = pager_query($sql, variable_get('advuser_listno', 50), 0, $query_count, $filter['args']);
 
   $form['options'] = array(
     '#type' => 'fieldset',
-    '#title' => t('Update options'),
+    '#title' => t('Action options'),
     '#prefix' => '<div class="container-inline">',
     '#suffix' => '</div>',
+    '#collapsible' => FALSE,
   );
   $options = array();
 
-  $operations = module_invoke_all('user_operations');
-  $operations = array_merge($operations,module_invoke_all('advuser_operations'));
+  // We don't want to call the user_operations here because we can't control
+  // the functioning of the callbacks to the saved accounts in the session.
+  // The callbacks only operate on the current screenfull of data and know
+  // nothing about the Select All Users mode.
+  $operations = module_invoke_all('advuser_operations');
+
   foreach ($operations as $operation => $array) {
     $options[$operation] = $array['label'];
   }
   $form['options']['operation'] = array(
     '#type' => 'select',
     '#options' => $options,
-    '#default_value' => 'unblock',
+    '#default_value' => 'saveselect',
   );
   $form['options']['submit'] = array(
     '#type' => 'submit',
-    '#value' => t('Update'),
-    '#submit' => array('advuser_admin_account_submit'),
+    '#value' => t('Apply action'),
   );
 
   $destination = drupal_get_destination();
@@ -113,34 +126,190 @@ function advuser_admin_account(&$form_st
  * Submit the user administration update form.
  */
 function advuser_admin_account_submit($form, &$form_state) {
-  $operations = module_invoke_all('user_operations', $form_state);
-  $operations = array_merge($operations,module_invoke_all('advuser_operations'));
+  $operations = module_invoke_all('advuser_operations', $form_state);
   $operation = $operations[$form_state['values']['operation']];
   $destination = $form_state['values']['destination'];
   // Filter out unchecked accounts.
-  $accounts = array_filter($form_state['values']['accounts']);
+  $accounts_selected = array_filter($form_state['values']['accounts']);
+  $form_accounts = $form['accounts']['#options'];
+
+  $advuser = &$_SESSION['advuser'];
+  $accounts = &$advuser['accounts'];
+  $selectall = &$advuser['selectall'];
+  $deselected = &$advuser['deselected'];
+
+  switch ($form_state['values']['operation']) {
+    case 'saveselect': {
+      foreach ($form_accounts as $form_user_id => $value) {
+        if (isset($accounts_selected[$form_user_id])) {
+          $accounts[$form_user_id] = $form_user_id;
+          unset($deselected[$form_user_id]);
+        }
+        else {
+          $deselected[$form_user_id] = $form_user_id;
+          unset($accounts[$form_user_id]);
+        }
+      }
+    } break;
+    case 'deselectall': {
+      $selectall = FALSE;
+      $accounts = array();
+      $deselected = array();
+      drupal_set_message(t('All selections have been reset.'));
+    } break;
+    case 'selectall': {
+      $selectall = TRUE;
+      $accounts = array();
+      $deselected = array();
+      drupal_set_message(t('All filtered users have been selected.'));
+    } break;
+    case 'block': {
+      foreach ($accounts as $user_id) {
+        $account = user_load(array('uid' => $user_id));
+        if ($account !== FALSE && $account->status == 1) {
+          user_save($account, array('status' => 0));
+        }
+        unset($accounts[$user_id]);
+      }
+      drupal_set_message(t('The selected users have been blocked.'));
+    } break;
+    case 'unblock': {
+      foreach ($accounts as $user_id) {
+        $account = user_load(array('uid' => $user_id));
+        if ($account !== FALSE && $account->status == 0) {
+          user_save($account, array('status' => 1));
+        }
+        unset($accounts[$user_id]);
+      }
+      drupal_set_message(t('The selected users have been unblocked.'));
+    } break;
+  }
+
   if ($function = $operation['callback']) {
     // Add in callback arguments if present.
     if (isset($operation['callback arguments'])) {
-      $args = array_merge(array($accounts), $operation['callback arguments']);
+      $args = array_merge(array($accounts_selected), $operation['callback arguments']);
     }
     else {
-      $args = array($accounts);
+      $args = array($accounts_selected);
     }
     call_user_func_array($function, $args);
 
-    cache_clear_all('*', 'cache_menu', TRUE);
-    drupal_set_message(t('The update has been performed.'));
-    extract(parse_url($destination));
-    drupal_goto($path, $query);
+    $act = str_replace('_', ' ', $operation['callback arguments'][0]);
+    drupal_set_message(t('The !action action has been applied.', array('!action' => t($act))));
   }
+
+  extract(parse_url($destination));
+  drupal_goto($path, $query);
 }
 
-function advuser_admin_account_validate($form, &$form_state) {
-  $form_state['values']['accounts'] = array_filter($form_state['values']['accounts']);
-  if (count($form_state['values']['accounts']) == 0) {
-    form_set_error('', t('No users selected.'));
+/**
+ * Theme user administration overview.
+ */
+function theme_advuser_admin_account(&$form) {
+  static $profile_fields = array();
+
+  $advuser = &$_SESSION['advuser'];
+  $accounts = &$advuser['accounts'];
+  $selectall = &$advuser['selectall'];
+  $deselected = &$advuser['deselected'];
+
+  // Overview table:
+  $header = array(
+    theme('table_select_header_cell'),
+    array('data' => t('Username'), 'field' => 'u.name'),
+    array('data' => t('Mail'), 'field' => 'u.mail'),
+    array('data' => t('Status'), 'field' => 'u.status'),
+  );
+  $roles = advuser_user_roles();
+  if (count($roles)) {
+    $header[] = t('Roles');
+  }
+  $header = array_merge($header, array(
+    array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
+    array('data' => t('Last access'), 'field' => 'u.access'),
+  ));
+
+  $ff = array();
+  foreach (advuser_profile_fields() as $field) {
+    $ff[] = array('data'=>t($field->title), 'field'=>$field->name);
+  }
+
+  $header = array_merge($header, $ff);
+  $header[] = t('Operations');
+
+  if (!count($accounts) && !$selectall) {
+    $form['options']['noselectedusers'] = array(
+      '#value' => t('No selected users have been saved.'),
+      '#prefix' => '<span class="error">',
+      '#suffix' => '</span>',
+    );
+  }
+  $output = drupal_render($form['options']);
+
+  if (isset($form['name']) && is_array($form['name'])) {
+    foreach (element_children($form['name']) as $key) {
+      if (($selectall || in_array($key, $accounts)) && !in_array($key, $deselected)) {
+        $form['accounts'][$key]['#value'] = TRUE;
+      }
+      $row = array(
+        drupal_render($form['accounts'][$key]),
+        drupal_render($form['name'][$key]),
+        drupal_render($form['mail'][$key]),
+        drupal_render($form['status'][$key]),
+      );
+      $roles = advuser_user_roles();
+      if (count($roles)) {
+        $row[] = drupal_render($form['roles'][$key]);
+      }
+      $row = array_merge($row, array(
+        drupal_render($form['member_for'][$key]),
+        drupal_render($form['last_access'][$key]),
+      ));
+
+      if (module_exists('profile')) {
+        $fields = variable_get('advuser_profile_fields', NULL);
+
+        if (is_array($fields)) {
+          foreach ( $fields as $fid => $value) {
+            if ( $value ) {
+              if (empty($profile_fields[$fid])) {
+
+                $field = db_fetch_object(db_query('SELECT * FROM {profile_fields} WHERE fid = %d', $fid));
+                $profile_fields[$fid] = $field;
+              }
+              else {
+                $field = $profile_fields[$fid];
+              }
+              $row[] = drupal_render($form[$field->name][$key]);
+            }
+          }
+        }
+      }
+      $row[] = drupal_render($form['operations'][$key]);
+      $rows[] = $row;
+    }
   }
+  else  {
+    $rows[] = array(array('data' => t('No users available.'), 'colspan' => '8'));
+  }
+
+  $output .= theme('table', $header, $rows);
+
+  $form['caution'] = array(
+    '#value' => t('Caution, you must "Save selection criteria" to apply other actions to the selected users or before changing pages.'),
+    '#prefix' => '<div class="warning">',
+    '#suffix' => '</div>',
+  );
+  $output .= drupal_render($form['caution']);
+
+  if ($form['pager']['#value']) {
+    $output .= drupal_render($form['pager']);
+  }
+
+  $output .= drupal_render($form);
+
+  return $output;
 }
 
 // vim:ft=php:sts=2:sw=2:ts=2:et:ai:sta:ff=unix
Index: forms/advuser_filter_ui.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advuser/forms/Attic/advuser_filter_ui.inc,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 advuser_filter_ui.inc
--- forms/advuser_filter_ui.inc	8 Apr 2010 16:37:50 -0000	1.1.2.1
+++ forms/advuser_filter_ui.inc	14 Apr 2010 22:15:00 -0000
@@ -1,8 +1,11 @@
 <?php
 
 function advuser_filter_ui(&$form_state) {
-  $phase = &$form_state['storage']['phase'];
-  $filters = &$form_state['storage']['filters'];
+  $advuser = &$_SESSION['advuser'];
+  $phase = &$advuser['phase'];
+  $filters = &$advuser['filters'];
+  $accounts = &$advuser['accounts'];
+  $selectall = &$advuser['selectall'];
 
   $form['filters'] = array(
     '#type' => 'fieldset',
@@ -16,6 +19,10 @@ function advuser_filter_ui(&$form_state)
     $phase['id'] = 0;
   }
 
+  if ($phase['id'] == 0 && (count($accounts) || $selectall)) {
+    $form['filters']['#collapsed'] = TRUE;
+  }
+
   if (empty($filters)) {
     $filters = array();
   }
@@ -69,7 +76,11 @@ function advuser_filter_ui_submit(&$form
 }
 
 function _advuser_filter_ui_0(&$form, &$form_state) {
-  $filters = &$form_state['storage']['filters'];
+  $advuser = &$_SESSION['advuser'];
+  $filters = &$advuser['filters'];
+  $accounts = &$advuser['accounts'];
+  $selectall = &$advuser['selectall'];
+  $deselected = &$advuser['deselected'];
 
   $form['filters']['conjunction'] = array(
     '#type' => 'select',
@@ -106,11 +117,19 @@ function _advuser_filter_ui_0(&$form, &$
       '#submit' => array('_advuser_filter_ui_0_reset'),
     );
   }
+  if (count($accounts) || $selectall) {
+    $form['filters']['accountsselected'] = array(
+      '#value' => t('You will lose your selections by changing the filters.'),
+      '#prefix' => '<span class="error">',
+      '#suffix' => '</span>',
+    );
+  }
 }
 
 function _advuser_filter_ui_0_submit(&$form, &$form_state) {
-  $phase = &$form_state['storage']['phase'];
-  $filters = &$form_state['storage']['filters'];
+  $advuser = &$_SESSION['advuser'];
+  $phase = &$advuser['phase'];
+  $filters = &$advuser['filters'];
   $phase['values']['field'] = $form_state['values']['field'];
   if (count($filters)) {
     $phase['values']['conjunction'] = $form_state['values']['conjunction'];
@@ -122,19 +141,31 @@ function _advuser_filter_ui_0_submit(&$f
 }
 
 function _advuser_filter_ui_0_undo(&$form, &$form_state) {
-  $filters = &$form_state['storage']['filters'];
+  $advuser = &$_SESSION['advuser'];
+  $filters = &$advuser['filters'];
+  $accounts = &$advuser['accounts'];
+  $selectall = &$advuser['selectall'];
   array_pop($filters);
+  $accounts = array();
+  $selectall = FALSE;
 }
 
 function _advuser_filter_ui_0_reset(&$form, &$form_state) {
-  drupal_goto('admin/user/user/advuser');
+  $advuser = &$_SESSION['advuser'];
+  $filters = &$advuser['filters'];
+  $accounts = &$advuser['accounts'];
+  $selectall = &$advuser['selectall'];
+  $filters = array();
+  $accounts = array();
+  $selectall = FALSE;
 }
 
 function _advuser_filter_ui_1(&$form, &$form_state) {
-  $phase = &$form_state['storage']['phase'];
+  $advuser = &$_SESSION['advuser'];
+  $phase = &$advuser['phase'];
   $field = &$phase['values']['field'];
   $conjunction = &$phase['values']['conjunction'];
-  $filters = &$form_state['storage']['filters'];
+  $filters = &$advuser['filters'];
 
   $form['filters']['conjunction'] = array(
     '#type' => 'select',
@@ -188,17 +219,24 @@ function _advuser_filter_ui_1(&$form, &$
 }
 
 function _advuser_filter_ui_1_submit(&$form, &$form_state) {
-  $phase = &$form_state['storage']['phase'];
-  $filters = &$form_state['storage']['filters'];
+  $advuser = &$_SESSION['advuser'];
+  $phase = &$advuser['phase'];
+  $filters = &$advuser['filters'];
+  $accounts = &$advuser['accounts'];
+  $selectall = &$advuser['selectall'];
+
   $phase['values']['operations'] = $form_state['values']['operations'];
   $phase['values']['data'] = $form_state['values']['data'];
   $filters[] = $phase['values'];
   $phase['values'] = array();
   $phase['id'] = 0;
+  $accounts = array();
+  $selectall = FALSE;
 }
 
 function _advuser_filter_ui_1_back(&$form, &$form_state) {
-  $phase = &$form_state['storage']['phase'];
+  $advuser = &$_SESSION['advuser'];
+  $phase = &$advuser['phase'];
   $phase['values'] = array();
   $phase['id'] = 0;
 }
Index: forms/advuser_multiple_delete_confirm.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advuser/forms/Attic/advuser_multiple_delete_confirm.inc,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 advuser_multiple_delete_confirm.inc
--- forms/advuser_multiple_delete_confirm.inc	8 Apr 2010 16:37:50 -0000	1.1.2.1
+++ forms/advuser_multiple_delete_confirm.inc	14 Apr 2010 22:15:00 -0000
@@ -1,21 +1,25 @@
 <?php
 
 function advuser_multiple_delete_confirm() {
-  $edit = $_POST;
+  $accounts = &$_SESSION['advuser']['accounts'];
 
   $form['accounts'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Selected users'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
     '#prefix' => '<ul>', 
     '#suffix' => '</ul>', 
     '#tree' => TRUE
   );
   // array_filter returns only elements with TRUE values
-  foreach (array_filter($edit['accounts']) as $uid => $value) {
+  foreach (array_filter($accounts) as $uid => $value) {
     $user = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid));
     $form['accounts'][$uid] = array(
-      '#type' => 'hidden', 
-      '#value' => $uid, 
+      '#type' => 'markup', 
+      '#value' => check_plain($user), 
       '#prefix' => '<li>', 
-      '#suffix' => check_plain($user) ."</li>\n"
+      '#suffix' => "</li>"
     );
   }
   $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
@@ -30,13 +34,15 @@ function advuser_multiple_delete_confirm
 }
 
 function advuser_multiple_delete_confirm_submit($form, &$form_state) {
+  $accounts = &$_SESSION['advuser']['accounts'];
   if ($form_state['values']['confirm']) {
-    foreach ($form_state['values']['accounts'] as $uid => $value) {
+    foreach ($accounts as $uid => $value) {
       user_delete($form_state['values'], $uid);
     }
     drupal_set_message(t('The users have been deleted.'));
   }
   $form_state['redirect'] = 'admin/user/user/advuser';
+  unset($accounts);
 }
 
 // vim:ft=php:sts=2:sw=2:ts=2:et:ai:sta:ff=unix
Index: forms/advuser_multiple_email_confirm.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/advuser/forms/Attic/advuser_multiple_email_confirm.inc,v
retrieving revision 1.1.2.1
diff -u -p -r1.1.2.1 advuser_multiple_email_confirm.inc
--- forms/advuser_multiple_email_confirm.inc	8 Apr 2010 16:37:50 -0000	1.1.2.1
+++ forms/advuser_multiple_email_confirm.inc	14 Apr 2010 22:15:00 -0000
@@ -1,17 +1,23 @@
 <?php
 
-function advuser_multiple_email_confirm() {
-  $edit = $_POST;
+function advuser_multiple_email_confirm(&$form_state) {
+  $accounts =& $_SESSION['advuser']['accounts'];
 
   $form['accounts'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
   // array_filter returns only elements with TRUE values
-  foreach (array_filter($edit['accounts']) as $uid => $value) {
+  $form['accounts'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Selected accounts'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+  foreach (array_filter($accounts) as $uid => $value) {
     $user = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid));
     $form['accounts'][$uid] = array(
-      '#type' => 'hidden', 
-      '#value' => $uid, 
+      '#type' => 'markup', 
+      '#value' => check_plain($user), 
       '#prefix' => '<li>', 
-      '#suffix' => check_plain($user) ."</li>\n"
+      '#suffix' => "</li>",
     );
   }
   $form['operation'] = array(
@@ -49,8 +55,9 @@ function advuser_multiple_email_confirm(
 }
 
 function advuser_multiple_email_confirm_submit($form, &$form_state) {
+  $accounts = &$_SESSION['advuser']['accounts'];
   if ($form_state['values']['confirm']) {
-    foreach ($form_state['values']['accounts'] as $uid => $value) {
+    foreach ($accounts as $uid => $value) {
       $account = user_load(array('uid' => $uid));
       $from = variable_get("site_mail", "nobody@$_SERVER[SERVER_NAME]");
       // these are invariant for all sent emails
