Index: fieldgroup.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/fieldgroup.module,v
retrieving revision 1.1.2.1
diff -u -r1.1.2.1 fieldgroup.module
--- fieldgroup.module	6 Dec 2006 15:42:05 -0000	1.1.2.1
+++ fieldgroup.module	14 Dec 2006 13:18:18 -0000
@@ -26,15 +26,6 @@
     if (arg(0) == 'admin' && arg(1) == 'node' && arg(2) == 'types' && arg(3)) {
       if ($type = content_types(arg(3))) {
         $items[] = array(
-          'path' => 'admin/node/types/'. arg(3) .'/groups',
-          'title' => t('manage groups'),
-          'callback' => 'fieldgroup_overview',
-          'access' => user_access('administer content types'),
-          'callback arguments' => array(arg(3)),
-          'type' => MENU_LOCAL_TASK,
-          'weight' => 0,
-          );
-        $items[] = array(
           'path' => 'admin/node/types/'. arg(3) .'/add_group',
           'title' => t('add group'),
           'callback' => 'fieldgroup_edit_group',
@@ -68,26 +59,6 @@
 
 }
 
-/*
- * Show a list of available groups for a content type
- */
-function fieldgroup_overview($content_type) {
-
-  $groups = fieldgroup_groups($content_type, TRUE);
-
-  foreach ($groups as $group) {
-    $rows[] = array(check_plain($group['label']), $group['weight'],
-                    l(t('configure'), 'admin/node/types/'. $content_type. '/groups/'. $group['group_name'] .'/edit'),
-                    l(t('remove'), 'admin/node/types/'. $content_type. '/groups/'. $group['group_name'] .'/remove'));
-  }
-  if (empty($rows)) {
-    $rows[] = array(array('data' => t('No groups available.'), 'colspan' => '4', 'class' => 'message'));
-  }
-
-  $header = array(t('Label'), t('Weight'), array('data' => t('Operations'), 'colspan' => '2'));
-  return theme('table', $header, $rows, array('id' => 'fieldgroup'));
-}
-
 function fieldgroup_edit_group($content_type, $group_name) {
   $groups = fieldgroup_groups($content_type);
   $group = $groups[$group_name];
@@ -177,7 +148,7 @@
              $form_values['label'], serialize($form_values['settings']), $form_values['description'], $form_values['weight'], $content_type, $group_name);
   }
   cache_clear_all('fieldgroup_data');
-  return 'admin/node/types/'. $content_type .'/groups';
+  return 'admin/node/types/'. $content_type .'/fields';
 }
 
 function fieldgroup_remove_group($content_type, $group_name) {
@@ -193,7 +164,7 @@
   return confirm_form('fieldgroup_remove_group', $form,
                   t('Are you sure you want to remove the group %label?',
                   array('%label' => theme('placeholder', $group['label']))),
-                  'admin/node/types/'. $content_type .'/groups', t('This action cannot be undone.'),
+                  'admin/node/types/'. $content_type .'/fields', t('This action cannot be undone.'),
                   t('Remove'), t('Cancel'));
 }
 
@@ -203,7 +174,7 @@
   cache_clear_all('fieldgroup_data');
 
   drupal_set_message('The group has been removed.');
-  return 'admin/node/types/'. $content_type .'/groups';
+  return 'admin/node/types/'. $content_type .'/fields';
 }
 
 
@@ -316,16 +287,16 @@
   if ($default != $form_values['group']) {
     if ($form_values['group'] && !$default) {
       db_query("INSERT INTO {node_group_fields} (type_name, group_name, field_name) VALUES ('%s', '%s', '%s')",
-                arg(3), $form_values['group'], arg(5));
+                $form_values['type_name'], $form_values['group'], $form_values['field_name']);
     }
     else if ($form_values['group']) {
       db_query("UPDATE {node_group_fields} SET group_name = '%s' WHERE type_name = '%s' AND field_name = '%s'",
-                $form_values['group'], arg(3), arg(5));
+                $form_values['group'], $form_values['type_name'], $form_values['field_name']);
     }
     else {
-      db_query("DELETE FROM {node_group_fields} WHERE type_name = '%s' AND field_name = '%s'", arg(3), arg(5));
+      db_query("DELETE FROM {node_group_fields} WHERE type_name = '%s' AND field_name = '%s'", $form_values['type_name'], $form_values['field_name']);
     }
-    cache_clear_all('fieldgroup_data');
+    cache_clear_all('fieldgroup_data', 'cache');
   }
 }
 
Index: content_admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/content_admin.inc,v
retrieving revision 1.12.2.16
diff -u -r1.12.2.16 content_admin.inc
--- content_admin.inc	12 Dec 2006 15:39:41 -0000	1.12.2.16
+++ content_admin.inc	14 Dec 2006 13:53:31 -0000
@@ -219,39 +219,313 @@
   }
 }
 
-
 /**
  * Menu callback; presents a listing of fields for a content type.
+ * 
+ * Form includes form widgets to set weight and group for each item
+ * and displays other form elements and their weights to make it
+ * easier to place CCK fields in the form and see where they will appear.
  */
 function _content_admin_field_overview($type_name) {
+  return drupal_get_form('content_admin_field_overview_form', content_admin_field_overview_form($type_name));
+}
+
+function content_admin_field_overview_form($type_name) {
+  $form = array();
+
   $type = content_types($type_name);
   $field_types = _content_field_types();
+  
+  // Create a dummy node and form and call hook_form_alter()
+  // to produce an array of fields and weights added to the node by all modules.
+  $dummy_node = new StdClass();
+  $dummy_node->type = $type['type_name'];
+  $dummy_form_id = $type['type_name'] .'_node_form';
+  $dummy_form = node_form_array($dummy_node);
+  foreach (module_implements('form_alter') as $module) {
+    $function = $module .'_form_alter';
+    $function($dummy_form_id, $dummy_form);
+  }
+  
+  // Move group fields into a 'fields' subgroup to make them easier to identify.
+  // Remove fields that are used in groups from the form, the group will handle them.
+  if (module_exist('fieldgroup')) {
+    $form['#groups']       = fieldgroup_groups($type['type_name']);
+    $form['#group_labels'] = _fieldgroup_groups_label($type['type_name']);
+    if (!$form['#groups']) {
+      drupal_set_message(t('There are no groups configured for this content type.'));
+    }
+    foreach ($form['#groups'] as $group) {
+      foreach ($group['fields'] as $field_name => $field) {
+        unset($dummy_form[$field_name]);
+      }
+    }
+  }
+  
+  if (!$type['fields']) {
+    drupal_set_message(t('There are no fields configured for this content type.'));
+  }
+  
+  if (!$type['fields'] && !$form['#groups']) {
+    return $form;
+  }
+  
+  // Iterate through the dummy form and add top-level fields and weights to a table.
+  // Construct the table values in an array '#table' that FAPI will ignore, keyed on the item's weight.
+  // Create separate form elements for each weight and group value and put a placeholder for each in #table.
+    
+  foreach ($dummy_form as $key => $value) {
+    
+    // Limiting weight to < 10 will keep workflow and submit elements from being added to the overview table.
+    // They're outside the weight range allowed for CCK fields, so won't interfere with field placement.
+
+    if (is_array($value) && (isset($value['#weight']) || $key == 'body_filter') && $value['#weight'] <= 10) {
+      
+      // if this item is a group, insert group info into table, then add all the group fields below it
+      if (substr($key, 0, 6) == 'group-' && isset($form['#groups'])) {
+        $row = $group_form = array();
+        $row['label']     = $form['#group_labels'][$form['#groups'][$key]['group_name']];
+        $row['name']      = $form['#groups'][$key]['group_name'];
+        $row['type']      = t('group');
+        $row['weights']   = 'form-group-weights';
+        $row['groups']    = '';
+        $row['configure'] = l(t('configure'), 'admin/content/types/'. $type['url_str'] .'/groups/'. $form['#groups'][$key]['group_name'] .'/edit');
+        $row['remove']    = l(t('remove'), 'admin/content/types/'. $type['url_str'] .'/groups/'. $form['#groups'][$key]['group_name'] .'/remove');
+        $data = $row;
+
+        $form['group-weights'][$key] = array('#type' => 'weight', '#default_value' => $value['#weight']);
+        foreach ($form['#groups'][$key]['fields'] as $field_name => $field) {
+          $row = array();
+          $field = $type['fields'][$field_name];
+          $row['label']     = $field['widget']['label'];
+          $row['name']      = $field['field_name'];
+          $row['type']      = $field_types[$field['widget']['type']]['label'];
+          $row['weights']   = 'form-field-weights';
+          $row['groups']    = 'form-field-groups';
+          $row['configure'] = l(t('configure'), 'admin/content/types/'. $type['url_str'] .'/fields/'. $field_name);
+          $row['remove']    = l(t('remove'), 'admin/content/types/'. $type['url_str'] .'/fields/'. $field_name .'/remove');
+          $group_form[$field['widget']['weight']][] = array($field_name => $row);
+
+          $form['field-weights'][$field_name] = array('#type' => 'weight', '#default_value' => $field['widget']['weight']);
+          $form['field-groups'][$field_name]  = array('#type' => 'select', '#options' => $form['#group_labels'], '#default_value' => fieldgroup_get_group($type['type_name'], $field_name));
+          $form['field-groups-defaults'][$field_name]  = array('#type' => 'hidden', '#value' => fieldgroup_get_group($type['type_name'], $field_name));
+        }
+        // sort the group fields by weight
+        ksort($group_form);
+        $group = (array) $data + array('fields' => $group_form);
+        $form['#table'][$value['#weight']][] = array($key => $group);
+      }
+
+      // else if this item is a top-level field, insert field row into the table
+      elseif (substr($key, 0, 6) == 'field_') {
+        $row = array();
+        $field = $type['fields'][$key];
+        $row['label']     = $field['widget']['label'];
+        $row['name']      = $field['field_name'];
+        $row['type']      = $field_types[$field['widget']['type']]['label'];
+        $row['weights']   = 'form-field-weights';
+        if (isset($form['#groups'])) {
+          $row['groups']  = 'form-field-groups';
+        }
+        $row['configure'] = l(t('configure'), 'admin/content/types/'. $type['url_str'] .'/fields/'. $key);
+        $row['remove']    = l(t('remove'), 'admin/content/types/'. $type['url_str'] .'/fields/'. $key .'/remove');
+        $form['#table'][$field['widget']['weight']][] = array($key => $row);
+        
+        $form['field-weights'][$key] = array('#type' => 'weight', '#default_value' => $field['widget']['weight']);
+        $form['field-groups'][$key]  = array('#type' => 'select', '#options' => $form['#group_labels'], '#default_value' => fieldgroup_get_group($type['type_name'], $key));
+      }
 
-  $header = array(t('Label'), t('Name'), t('Type'), t('Weight'), array('data' => t('Operations'), 'colspan' => 2));
-  $rows = array();
-  $rows[] = array(t($type['title_label']), 'title', '', '', '', '');
-
-  $c = db_query(db_rewrite_sql("SELECT v.*, n.type FROM {vocabulary} v INNER JOIN {vocabulary_node_types} n ON v.vid = n.vid WHERE n.type = '%s' ORDER BY v.weight, v.name", 'v', 'vid'), $type_name);
-  while ($vocabulary = db_fetch_object($c)) {
-    $rows[] = array(check_plain($vocabulary->name), 'taxonomy', '', '', '', '');
+      // otherwise this is some other form field or fieldset
+      // if it has a weight display it as a disabled item
+      else {
+        $row = array();
+        $row['label']     = $key == 'body_filter' ? t('body') : $key;
+        $row['name']      = $key;
+        $row['type']      = $key;
+        $row['weights']   = 'form-field-weights';
+        if (isset($form['#groups'])) {
+          $row['groups']  = '';
+        }
+        $row['configure'] = '';
+        $row['remove']    = '';
+        // use intval on weight because body weight is empty instead of zero
+        $form['#table'][intval($value['#weight'])][] = array($key => $row);
+        $form['disabled']['#value'][] = $key;
+        
+        $form['field-weights'][$key] = array('#type' => 'weight', '#default_value' => $value['#weight'], '#attributes' => array('disabled' => 'disabled'));
+      }
+    }
   }
+  
+  // sort the table by weight
+  ksort($form['#table']);
+  
+  // add submit buttons and hidden fields
+  $form['submit']                         = array('#type' => 'submit', '#value' => t('Update'));
+  $form['field-weights']['#tree']         = TRUE;
+  $form['group-weights']['#tree']         = TRUE;
+  $form['field-groups']['#tree']          = TRUE;
+  $form['field-groups-defaults']['#tree'] = TRUE;
+  $form['disabled']['#type']              = 'hidden';
+  $form['disabled']['#value']             = serialize($form['disabled']['#value']);
+  $form['type_name']['#type']             = 'hidden';
+  $form['type_name']['#value']            = $type['type_name'];
+  
+  return $form;
 
-  foreach ($type['fields'] as $field) {
-    $row = array();
-    $row[] = $field['widget']['label'];
-    $row[] = $field['field_name'];
-    $row[] = $field_types[$field['type']]['label'];
-    $row[] = $field['widget']['weight'];
+}
+
+/**
+ *  Theme the field overview table by iterating through the form and rendering form elements in table cells
+ */
+function theme_content_admin_field_overview_form($form) {
+  
+  if (!$form['#table']) {
+    return;
+  }
 
-    $row[] = l(t('configure'), 'admin/node/types/'. $type_name .'/fields/'. $field['field_name']);
-    $row[] = l(t('remove'), 'admin/node/types/'. $type_name .'/fields/'. $field['field_name'] .'/remove');
+  //drupal_add_css(drupal_get_path('module', 'content') .'/content.css');
+  theme_add_style(drupal_get_path('module', 'content') .'/content.css');
 
-    $rows[] = $row;
+  $disabled = unserialize($form['disabled']['#value']);
+  
+  if (module_exist('fieldgroup')) {
+    $header = array(t('Label'), t('Name'), t('Type'), t('Weight'), t('Group'), array('data' => t('Operations'), 'colspan' => 2));
+    $colspan = 7;
+  }
+  else {
+    $header = array(t('Label'), t('Name'), t('Type'), t('Weight'), array('data' => t('Operations'), 'colspan' => 2));
+    $colspan = 6;
   }
 
-  $output = theme('table', $header, $rows);
+  $rows = array();
+  $i = 0;
 
+  // The table was created in the form
+  // iterate through it and render form elements when placeholders are encountered
+  // then run the rows array through theme_table().
+  foreach ($form['#table'] as $weight => $frow) {
+    foreach ($frow as $delta => $item) {
+      foreach ($item as $fname => $field) {
+        $row = array();
+        $class = 'content-field-overview-enabled';
+        if (in_array($fname, $disabled)) {
+          $class = 'content-field-overview-disabled';
+        }
+        foreach ($field as $col => $cell) {
+          // display cols other than the group 'fields' col
+          if ($col != 'fields') {
+            switch ($cell) {
+            case 'form-field-weights':
+              $row[] = form_render($form['field-weights'][$fname]);
+              break;
+            case 'form-group-weights':
+              $row[] = form_render($form['group-weights'][$fname]);
+              break;
+            case 'form-field-groups':
+              $row[] = form_render($form['field-groups'][$fname]);
+              break;
+            default:
+              $row[] = array('data' => $cell, 'class' => $class);
+            }
+          }
+          
+          elseif (isset($form['#groups'])) {
+            // if this form contains groups info and this is a group 'fields' col, finish the previous row
+            // then theme the 'fields' col with a fieldset containing a table and the group fields
+            $grows = array();
+            
+            if (!empty($cell)) {
+              foreach ($cell as $gweight => $grow) {
+                foreach ($grow as $gdelta => $gitem) {
+                  foreach ($gitem as $gname => $gfield) {
+                    $grow = array();
+                    foreach ($gfield as $gcol => $gcell) {
+                      switch ($gcell) {
+                        case 'form-field-weights':
+                          $grow[] = form_render($form['field-weights'][$gname]);
+                          break;
+                        case 'form-field-groups':
+                          $grow[] = form_render($form['field-groups'][$gname]);
+                          break;
+                        default:
+                          $grow[] = $gcell;
+                      }
+                    }
+                    $grows[] = array('data' => $grow, 'class' => 'content-field-overview-enabled');
+                  }
+                }
+              }
+            }
+            else {
+              $grows[] = array(array('data' => t('No fields have been added to this group.'), 'colspan' => $colspan, 'class' => 'content-field-overview-empty'));
+            }
+                      
+            // add the group row in its own table above the group fields table, then reset $row().
+            $fieldset = array(
+              '#title' => t('!label (!name)', array('!label' => $form['#group_labels'][$fname], '!name' => $fname)),
+              '#collapsible' => TRUE,
+              '#collapsed' => FALSE,
+              '#value' => theme('table', array(), array(array('data' => $row, 'class' => 'content-field-overview-group'))) . theme('table', $header, $grows),
+              );
+            $row = array();
+            $row[] = array(
+              'data' => theme('fieldset', $fieldset), 
+              'colspan' => $colspan, 
+              'class' => 'active',
+              );
+            $grows = array();
+          }
+        }
+        $rows[] = $row;
+      }
+    }
+  }
+  $output  = theme('table', $header, $rows, array('class' => 'content-field-overview'));
+  $output .= form_render($form);
   return $output;
+
+}
+
+function content_admin_field_overview_form_submit($form_id, $form_values) {
+  
+  $msg = FALSE;
+  foreach ((array) $form_values['field-groups'] as $key => $value) {
+    if ($key && !in_array($key, unserialize($form_values['disabled']))) {
+      $values  = array('field_name' => $key, 'group' => $value, 'type_name' => $form_values['type_name']);
+      $default = $form_values['field-groups-defaults'][$key];
+      fieldgroup_content_admin_form_submit('_content_admin_field', $values, $default);
+      $msg = TRUE;
+    }
+  }
+  if ($msg) {
+    drupal_set_message(t('Updated field groups.'));
+  }
+  $msg = FALSE;
+  foreach ((array) $form_values['group-weights'] as $key => $value) {
+    if ($key && !in_array($key, unserialize($form_values['disabled']))) {
+      db_query("UPDATE {node_group} SET weight = %d WHERE type_name = '%s' AND group_name = '%s'",
+        $value, $form_values['type_name'], $key);
+      $msg = TRUE;  
+    }
+  }
+  if ($msg) {
+    drupal_set_message(t('Updated group weights.'));
+  }
+  $msg = FALSE;
+  foreach ((array) $form_values['field-weights'] as $key => $value) {
+    if ($key && !in_array($key, unserialize($form_values['disabled']))) {
+      db_query("UPDATE {node_field_instance} SET weight = %d WHERE type_name = '%s' AND field_name = '%s'", 
+        $value, $form_values['type_name'], $key);
+      $msg = TRUE;
+    }
+  }
+  if ($msg) {
+    drupal_set_message(t('Updated field weights.'));
+  }
+  content_clear_type_cache();
+  cache_clear_all('fieldgroup_data', 'cache');
+
 }
 
 /**
