diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 6c81cfc0f54bcd26c6a1517150aea449f2d476ae..087d150bb105bf05173178b5136e7580d400fd6d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -32,6 +32,7 @@ Drupal x.x.x, xxxx-xx-xx (development version) - user module: * added hook_profile_alter(). * e-mail verification is made optional. + * added mass editing on admin/user/user. - PHP Template engine: * add the ability to look for a series of suggested templates. * look for page templates based upon the path. diff --git a/modules/user/user.module b/modules/user/user.module index acd22b470f802216d765ca5abcbd38dfcca489f8..8469051b291e9bedc272d2829fa33b3c1a1ecf1e 100644 --- a/modules/user/user.module +++ b/modules/user/user.module @@ -1378,13 +1378,7 @@ function user_edit($category = 'account') { if (arg(2) == 'delete') { if ($edit['confirm']) { - db_query('DELETE FROM {users} WHERE uid = %d', $account->uid); - db_query('DELETE FROM {sessions} WHERE uid = %d', $account->uid); - db_query('DELETE FROM {users_roles} WHERE uid = %d', $account->uid); - db_query('DELETE FROM {authmap} WHERE uid = %d', $account->uid); - watchdog('user', t('Deleted user: %name %email.', array('%name' => theme('placeholder', $account->name), '%email' => theme('placeholder', '<'. $account->mail .'>'))), WATCHDOG_NOTICE); - drupal_set_message(t('The account has been deleted.')); - module_invoke_all('user', 'delete', $edit, $account); + user_delete($edit, $account->uid); drupal_goto('admin/user/user'); } else { @@ -1413,6 +1407,24 @@ function user_edit($category = 'account') { return drupal_get_form('user_edit', $form); } +/** + * Delete a user. + * + * @param $edit An array of submitted form values. + * @param $uid The user ID of the user to delete. + */ +function user_delete($edit, $uid) { + $account = user_load(array('uid' => $uid)); + db_query('DELETE FROM {users} WHERE uid = %d', $uid); + db_query('DELETE FROM {sessions} WHERE uid = %d', $uid); + db_query('DELETE FROM {users_roles} WHERE uid = %d', $uid); + db_query('DELETE FROM {authmap} WHERE uid = %d', $uid); + $array = array('%name' => theme('placeholder', $account->name), '%email' => theme('placeholder', '<'. $account->mail .'>')); + watchdog('user', t('Deleted user: %name %email.', $array), WATCHDOG_NOTICE); + drupal_set_message(t('%name has been deleted.', $array)); + module_invoke_all('user', 'delete', $edit, $account); +} + function user_edit_validate($form_id, $form_values) { user_module_invoke('validate', $form_values, $form_values['_account'], $form_values['_category']); // Validate input to ensure that non-privileged users can't alter protected data. @@ -1898,31 +1910,248 @@ function theme_user_admin_new_role($form) { } function user_admin_account() { + if ($_POST['edit']['accounts'] && $_POST['edit']['operation'] == 'delete') { + return user_multiple_delete_confirm(); + } + $header = array( + array(), array('data' => t('Username'), 'field' => 'u.name'), array('data' => t('Status'), 'field' => 'u.status'), + t('Roles'), array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'), array('data' => t('Last access'), 'field' => 'u.access'), t('Operations') ); + $sql = 'SELECT u.uid, u.name, u.status, u.created, u.access FROM {users} u WHERE uid != 0'; $sql .= tablesort_sql($header); $result = pager_query($sql, 50); + $form['options'] = array( + '#type' => 'fieldset', + '#title' => t('Update options'), + '#prefix' => '<div class="container-inline">', + '#suffix' => '</div>', + ); + $options = array(); + foreach (module_invoke_all('user_operations') as $key => $value) { + $options[$key] = $value[0]; + } + $form['options']['operation'] = array( + '#type' => 'select', + '#options' => $options, + '#default_value' => 'unblock', + ); + $form['options']['submit'] = array( + '#type' => 'submit', + '#value' => t('Update'), + ); + + $destination = drupal_get_destination(); + $status = array(t('blocked'), t('active')); + $roles = user_roles(1); + while ($account = db_fetch_object($result)) { - $rows[] = array(theme('username', $account), - $status[$account->status], - format_interval(time() - $account->created), - $account->access ? t('%time ago', array('%time' => format_interval(time() - $account->access))) : t('never'), - l(t('edit'), "user/$account->uid/edit", array())); + $accounts[$account->uid] = ''; + $form['name'][$account->uid] = array('#value' => theme('username', $account)); + $form['status'][$account->uid] = array('#value' => $status[$account->status]); + $users_roles = array(); + $roles_result = db_query('SELECT rid FROM {users_roles} WHERE uid = %d', $account->uid); + while ($user_role = db_fetch_object($roles_result)) { + $users_roles[] = $roles[$user_role->rid]; + } + asort($users_roles); + $form['roles'][$account->uid][0] = array('#value' => theme('item_list', $users_roles)); + $form['member_for'][$account->uid] = array('#value' => format_interval(time() - $account->created)); + $form['last_access'][$account->uid] = array('#value' => $account->access ? t('%time ago', array('%time' => format_interval(time() - $account->access))) : t('never')); + $form['operations'][$account->uid] = array('#value' => l(t('edit'), "user/$account->uid/edit", array(), $destination)); + } + $form['accounts'] = array( + '#type' => 'checkboxes', + '#options' => $accounts + ); + $form['pager'] = array('#value' => theme('pager', NULL, 50, 0)); + + // Call the form first, to allow for the form_values array to be populated. + $output .= drupal_get_form('user_admin_account', $form); + + return $output; +} + +/** + * Theme user administration overview. + */ +function theme_user_admin_account($form) { + // Overview table: + $header = array( + array(), + array('data' => t('Username'), 'field' => 'u.name'), + array('data' => t('Status'), 'field' => 'u.status'), + t('Roles'), + array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'), + array('data' => t('Last access'), 'field' => 'u.access'), + t('Operations') + ); + + $output .= form_render($form['options']); + if (isset($form['name']) && is_array($form['name'])) { + foreach (element_children($form['name']) as $key) { + $rows[] = array( + form_render($form['accounts'][$key]), + form_render($form['name'][$key]), + form_render($form['status'][$key]), + form_render($form['roles'][$key]), + form_render($form['member_for'][$key]), + form_render($form['last_access'][$key]), + form_render($form['operations'][$key]), + ); + } } + else { + $rows[] = array(array('data' => t('No users available.'), 'colspan' => '7')); + } + + $output .= theme('table', $header, $rows); + if ($form['pager']['#value']) { + $output .= form_render($form['pager']); + } + + $output .= form_render($form); - $output = theme('table', $header, $rows); - $output .= theme('pager', NULL, 50, 0); return $output; } +/** + * Submit the user administration update form. + */ +function user_admin_account_submit($form_id, $edit) { + $operations = module_invoke_all('user_operations'); + $operation = $operations[$edit['operation']]; + // Filter out unchecked accounts. + $accounts = array_filter($edit['accounts']); + if ($function = $operation[1]) { + call_user_func($function, $accounts); + cache_clear_all(); + drupal_set_message(t('The update has been performed.')); + } +} + +function user_admin_account_validate($form_id, $edit) { + $edit['accounts'] = array_filter($edit['accounts']); + if (count($edit['accounts']) == 0) { + form_set_error('', t('No users selected.')); + } +} + +/** + * Implementation of hook_user_operations(). + */ +function user_user_operations() { + global $form_values; + + $roles = user_roles(1); + unset($roles[2]); // 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; + } + + $operations = array( + 'unblock' => array(t('Unblock the selected users'), 'user_user_operations_unblock'), + 'block' => array(t('Block the selected users'), 'user_user_operations_block'), + t('Add a role to the selected users') => array($add_roles), + t('Remove a role from the selected users') => array($remove_roles), + 'delete' => array(t('Delete the selected users'), ''), + ); + + // If the form has been posted, we need to insert the proper data for role editing if necessary. + if ($form_values) { + $operation = explode('-', $form_values['operation']); + if ($operation[0] == 'add_role' || $operation[0] == 'remove_role') { + $operations[$form_values['operation']] = array(NULL, 'user_multiple_role_edit'); + } + } + + return $operations; +} + +/** + * Callback function for admin mass unblocking users. + */ +function user_user_operations_unblock($accounts) { + db_query('UPDATE {users} SET status = 1 WHERE uid IN(%s)', implode(',', $accounts)); +} + +/** + * Callback function for admin mass blocking users. + */ +function user_user_operations_block($accounts) { + db_query('UPDATE {users} SET status = 0 WHERE uid IN(%s)', implode(',', $accounts)); +} + +/** + * Callback function for admin mass adding/deleting a user role. + */ +function user_multiple_role_edit($accounts) { + global $form_values; + + // Get the operation and role from the posted form. + $operation_rid = explode('-', $form_values['operation']); + $operation = $operation_rid[0]; + $rid = $operation_rid[1]; + + switch ($operation) { + case 'add_role': + foreach ($accounts as $uid) { + // Skip adding the role to the user if they already have it. + if (!db_result(db_query('SELECT uid FROM {users_roles} WHERE uid = %d AND rid = %d', $uid, $rid))) { + db_query('INSERT INTO {users_roles} VALUES (%d, %d)', $uid, $rid); + } + } + break; + case 'remove_role': + foreach ($accounts as $uid) { + db_query('DELETE FROM {users_roles} WHERE rid = %d AND uid IN(%s)', $rid, implode(',', $accounts)); + } + break; + } +} + +function user_multiple_delete_confirm() { + $edit = $_POST['edit']; + + $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) { + $user = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid)); + $form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '<li>', '#suffix' => check_plain($user) ."</li>\n"); + } + $form['operation'] = array('#type' => 'hidden', '#value' => 'delete'); + + return confirm_form('user_multiple_delete_confirm', $form, + t('Are you sure you want to delete these users?'), + 'admin/user/user', t('This action cannot be undone.'), + t('Delete all'), t('Cancel')); +} + +function user_multiple_delete_confirm_submit($form_id, $edit) { + if ($edit['confirm']) { + foreach ($edit['accounts'] as $uid => $value) { + user_delete($edit, $uid); + } + drupal_set_message(t('The users have been deleted.')); + } + return 'admin/user/user'; +} + function user_admin_settings() { // User registration settings. $form['registration'] = array('#type' => 'fieldset', '#title' => t('User registration settings'));