Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.762 diff -u -p -r1.762 common.inc --- includes/common.inc 31 Mar 2008 20:50:05 -0000 1.762 +++ includes/common.inc 6 Apr 2008 06:43:46 -0000 @@ -2767,7 +2767,10 @@ function drupal_render(&$elements) { } $prefix = isset($elements['#prefix']) ? $elements['#prefix'] : ''; $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : ''; - return $prefix . $content . $suffix; + $content = $prefix . $content . $suffix; + // Store the rendered content, so higher level elements can reuse it. + $elements['#content'] = $content; + return $content; } } @@ -3005,6 +3008,9 @@ function drupal_common_theme() { 'file' => array( 'arguments' => array('element' => NULL), ), + 'tableselect' => array( + 'arguments' => array('element' => NULL), + ), 'form_element' => array( 'arguments' => array('element' => NULL, 'value' => NULL), ), Index: includes/form.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/form.inc,v retrieving revision 1.268 diff -u -p -r1.268 form.inc --- includes/form.inc 15 Mar 2008 11:02:47 -0000 1.268 +++ includes/form.inc 8 Apr 2008 03:33:37 -0000 @@ -1897,6 +1897,82 @@ function expand_checkboxes($element) { } /** + * Render the element as a table, with the expanded children in the first row. + * + * @param $element + * An associative array containing the properties of the element. + * + * @return + * A themed HTML string representing the table. + * + * @ingroup themeable + */ +function theme_tableselect($element) { + $rows = array(); + foreach ($element['#options'] as $key => $value) { + $row = array(); + + // Render the checkbox / radio element. + $row[] = $element[$key]['#content']; + + foreach ($element['#header'] as $fieldname => $title) { + $row[] = $element['#options'][$key][$fieldname]; + } + $rows[] = $row; + } + $first_col = $element['#advanced_select'] ? array(theme('table_select_header_cell')) : array(''); + $header = array_merge($first_col, $element['#header']); + return theme('table', $header, $rows); +} + +/** + * Create the right amount of checkboxes or radios to populate the table. + */ +function expand_tableselect($element) { + + if ($element['#multiple']) { + $value = is_array($element['#value']) ? $element['#value'] : array(); + } + else { + // Advanced select is only possible if #multiple is true. + $element['#advanced_select'] = FALSE; + } + + $element['#tree'] = TRUE; + + if (count($element['#options']) > 0) { + if (!isset($element['#default_value']) || $element['#default_value'] === 0) { + $element['#default_value'] = array(); + } + + foreach ($element['#options'] as $key => $choice) { + if ($element['#multiple']) { + $element[$key] = array( + '#type' => 'checkbox', + '#processed' => TRUE, + '#title' => '', + '#return_value' => $key, + '#default_value' => isset($value[$key]), + '#attributes' => $element['#attributes'], + ); + } + else { + $element[$key] = array( + '#type' => 'radio', + '#title' => '', + '#return_value' => $key, + '#default_value' => ($element['#default_value'] == $key) ? $key : NULL, + '#attributes' => $element['#attributes'], + '#parents' => $element['#parents'], + '#spawned' => TRUE, + ); + } + } + } + return $element; +} + +/** * Theme a form submit button. * * @ingroup themeable Index: includes/tablesort.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/tablesort.inc,v retrieving revision 1.47 diff -u -p -r1.47 tablesort.inc --- includes/tablesort.inc 4 Jan 2008 09:31:48 -0000 1.47 +++ includes/tablesort.inc 8 Apr 2008 03:31:14 -0000 @@ -165,13 +165,14 @@ function tablesort_get_order($headers) { return $default; } else { - // The first column specified is initial 'order by' field unless otherwise specified - if (is_array($headers[0])) { - $headers[0] += array('data' => NULL, 'field' => NULL); - return array('name' => $headers[0]['data'], 'sql' => $headers[0]['field']); + // The first column specified is the initial 'order by' field unless otherwise specified. + $first = current($headers); + if (is_array($first)) { + $first += array('data' => NULL, 'field' => NULL); + return array('name' => $first['data'], 'sql' => $first['field']); } else { - return array('name' => $headers[0]); + return array('name' => $first, 'sql' => ''); } } } Index: modules/system/system.module =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.module,v retrieving revision 1.594 diff -u -p -r1.594 system.module --- modules/system/system.module 1 Apr 2008 20:05:15 -0000 1.594 +++ modules/system/system.module 6 Apr 2008 07:04:33 -0000 @@ -281,6 +281,14 @@ function system_elements() { '#size' => 60, ); + $type['tableselect'] = array( + '#input' => TRUE, + '#advanced_select' => TRUE, + '#multiple' => TRUE, + '#process' => array('expand_tableselect'), + '#options' => array(), + ); + /** * Form structure. Index: modules/user/user.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.admin.inc,v retrieving revision 1.19 diff -u -p -r1.19 user.admin.inc --- modules/user/user.admin.inc 20 Feb 2008 13:46:43 -0000 1.19 +++ modules/user/user.admin.inc 6 Apr 2008 09:53:15 -0000 @@ -130,13 +130,12 @@ function user_admin_account() { $filter = user_build_filter_query(); $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') + 'username' => array('data' => t('Username'), 'field' => 'u.name'), + 'status' => array('data' => t('Status'), 'field' => 'u.status'), + 'roles' => t('Roles'), + 'member_for' => array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'), + 'last_access' => array('data' => t('Last access'), 'field' => 'u.access'), + 'operations' => t('Operations'), ); $sql = 'SELECT DISTINCT u.uid, u.name, 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']; @@ -159,6 +158,7 @@ function user_admin_account() { '#options' => $options, '#default_value' => 'unblock', ); + $form['options']['submit'] = array( '#type' => 'submit', '#value' => t('Update'), @@ -168,26 +168,33 @@ function user_admin_account() { $status = array(t('blocked'), t('active')); $roles = user_roles(TRUE); - $accounts = array(); + + $options = array(); + while ($account = db_fetch_object($result)) { - $accounts[$account->uid] = ''; - $form['name'][$account->uid] = array('#value' => theme('username', $account)); - $form['status'][$account->uid] = array('#value' => $status[$account->status]); + $options[$account->uid] = array( + 'username' => theme('username', $account), + 'status' => $status[$account->status], + 'member_for' => format_interval(time() - $account->created), + 'last_access' => $account->access ? t('@time ago', array('@time' => format_interval(time() - $account->access))) : t('never'), + 'operations' => l(t('edit'), "user/$account->uid/edit", array('query' => $destination)), + ); + $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('query' => $destination))); + $options[$account->uid]['roles'] = theme('item_list', $users_roles); } + $form['accounts'] = array( - '#type' => 'checkboxes', - '#options' => $accounts + '#type' => 'tableselect', + '#header' => $header, + '#options' => $options, ); + $form['pager'] = array('#value' => theme('pager', NULL, 50, 0)); return $form; @@ -912,51 +919,6 @@ function user_admin_access() { } /** - * Theme user administration overview. - * - * @ingroup themeable - */ -function theme_user_admin_account($form) { - // Overview table: - $header = array( - theme('table_select_header_cell'), - 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 = drupal_render($form['options']); - if (isset($form['name']) && is_array($form['name'])) { - foreach (element_children($form['name']) as $key) { - $rows[] = array( - drupal_render($form['accounts'][$key]), - drupal_render($form['name'][$key]), - drupal_render($form['status'][$key]), - drupal_render($form['roles'][$key]), - drupal_render($form['member_for'][$key]), - drupal_render($form['last_access'][$key]), - drupal_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 .= drupal_render($form['pager']); - } - - $output .= drupal_render($form); - - return $output; -} - -/** * Theme the new-role form. * * @ingroup themeable Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.898 diff -u -p -r1.898 user.module --- modules/user/user.module 31 Mar 2008 20:50:05 -0000 1.898 +++ modules/user/user.module 6 Apr 2008 06:43:46 -0000 @@ -59,10 +59,6 @@ function user_theme() { 'arguments' => array('form' => NULL), 'file' => 'user.admin.inc', ), - 'user_admin_account' => array( - 'arguments' => array('form' => NULL), - 'file' => 'user.admin.inc', - ), 'user_filter_form' => array( 'arguments' => array('form' => NULL), 'file' => 'user.admin.inc',