Index: fieldgroup.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/fieldgroup.install,v
retrieving revision 1.32
diff -u -r1.32 fieldgroup.install
--- fieldgroup.install	13 Jan 2008 12:38:35 -0000	1.32
+++ fieldgroup.install	15 Feb 2008 21:51:57 -0000
@@ -1,5 +1,5 @@
 <?php
-// $Id: fieldgroup.install,v 1.32 2008/01/13 12:38:35 karens Exp $
+// $Id: fieldgroup.install,v 1.30 2008/01/09 01:34:22 yched Exp $
 
 // Updates happen in random order, whether or not the module is enabled,
 // so include critical code here just to be sure.
@@ -51,22 +51,72 @@
 function fieldgroup_schema() {
   $schema['content_group'] = array(
     'fields' => array(
-      'type_name'  => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => ''),
-      'group_name' => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => ''),
-      'label'      => array('type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => ''),
-      'settings'   => array('type' => 'text', 'size' => 'medium', 'not null' => TRUE),
-      'weight'     => array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0),
+      'gid' => array(
+        'type' => 'serial',
+        'not null' => TRUE,
+        'description' => t('Primary Key: Unique group ID.')
+      ),
+      'mlid' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => t('Relationship to {menu_links}.mlid.')
+      ),
+      'type_name' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+        'description' => t('Content type the group is a member of, listed in {node_type}.type.')
+      ),
+      'group_name' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => ''
+      ),
+      'label' => array(
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => ''
+      ),
+      'settings' => array(
+        'type' => 'text',
+        'size' => 'medium',
+        'not null' => TRUE
+      )
     ),
-    'primary key' => array('type_name', 'group_name'),
+    'indexes' => array(
+      'mlid'       => array('mlid'),
+      'type_name'  => array('type_name'),
+      'group_name' => array('group_name')
+    ),
+    'primary key' => array('gid')
   );
 
   $schema['content_group_fields'] = array(
     'fields' => array(
-      'type_name'  => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => ''),
-      'group_name' => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => ''),
-      'field_name' => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, 'default' => ''),
+      'type_name'  => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => ''
+      ),
+      'group_name' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => ''
+      ),
+      'field_name' => array(
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => ''
+      )
     ),
-    'primary key' => array('type_name', 'group_name', 'field_name'),
+    'primary key' => array('type_name', 'group_name', 'field_name')
   );
 
   return $schema;
Index: fieldgroup.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/cck/fieldgroup.module,v
retrieving revision 1.69
diff -u -r1.69 fieldgroup.module
--- fieldgroup.module	7 Feb 2008 18:43:15 -0000	1.69
+++ fieldgroup.module	15 Feb 2008 21:51:57 -0000
@@ -89,9 +89,14 @@
   cache_clear_all('fieldgroup_data', content_cache_tablename());
 }
 
-function fieldgroup_edit_group_form(&$form_state, $content_type, $group_name, $action) {
+function fieldgroup_edit_group_form(&$form_state, $content_type, $gid, $action) {
   $groups = fieldgroup_groups($content_type['type']);
 
+  $group_options[0] = '<'. t('Top') .'>';
+  foreach ($groups as $name => $item) {
+    $group_options[$item['mlid']] = $item['label'];
+  }
+
   if ($action == 'add') {
     //adding a new one
     $group = array();
@@ -101,7 +106,7 @@
       '#weight' => 10,
     );
   }
-  elseif ($group = $groups[$group_name]) {
+  elseif ($group = $groups[$gid]) {
     $form['submit'] = array(
       '#type' => 'submit',
       '#value' => t('Save'),
@@ -119,6 +124,17 @@
     '#default_value' => isset($group['label']) ? $group['label'] : '',
     '#required' => TRUE,
   );
+
+  // don't let the group be the parent of itself
+  if (isset($group['mlid'])) {
+    unset($group_options[$group['mlid']]);
+  }
+  $form['parent'] = array(
+    '#type' => 'select',
+    '#title' => t('Parent Group'),
+    '#default_value' => isset($group['group_name']) && isset($groups[$group['group_name']]['plid']) ? $groups[$group['group_name']]['plid'] : '',
+    '#options' => $group_options
+  );
   $form['settings']['#tree'] = TRUE;
   $form['settings']['form'] = array(
     '#type' => 'fieldset',
@@ -160,8 +176,18 @@
   foreach (array_merge(array_keys(_content_admin_display_contexts(CONTENT_CONTEXTS_SIMPLE)), array('label')) as $key) {
     $form['settings']['display'][$key] = array('#type' => 'value', '#value' => isset($group['settings']['display'][$key]) ? $group['settings']['display'][$key] : 'fieldset');
   }
-  $form['weight'] = array('#type' => 'hidden', '#default_value' => isset($group['weight']) ? $group['weight'] : 0);
-  $form['group_name'] = array('#type' => 'hidden', '#default_value' => $group_name);
+  $form['weight'] = array(
+    '#type' => 'hidden',
+    '#default_value' => isset($group['weight']) ? $group['weight'] : 0
+  );
+  $form['group_name'] = array(
+    '#type' => 'hidden',
+    '#default_value' => isset($group['group_name']) ? $group['group_name'] : ''
+  );
+  $form['mlid'] = array(
+    '#type' => 'hidden',
+    '#default_value' => isset($group['mlid']) ? $group['mlid'] : ''
+  );
 
   $form['#content_type'] = $content_type;
   $form['#group_action'] = $action;
@@ -182,18 +208,18 @@
   $content_type = $form['#content_type'];
   $action = $form['#group_action'];
 
-  if (!empty($form_values['group_name']) && $action == 'add') {
+  if (!empty($form_values['group_id']) && $action == 'add') {
 
     $groups = fieldgroup_groups($content_type['type']);
-    $group = $groups[$form_values['group_name']];
+    $group = $groups[$form_values['group_id']];
 
-    if (isset($group[$form_values['group_name']])) {
+    if (isset($group[$form_values['group_id']])) {
       form_set_error('group_name', t('The group name %name already exists.', array(
-        '%group_name' => $form_values['group_name'])));
+        '%group_name' => $form_values['group_id'])));
     }
-    if (!preg_match('!^[a-z0-9_]+$!', $form_values['group_name'])) {
+    if (!preg_match('!^[a-z0-9_]+$!', $form_values['group_id'])) {
       form_set_error('group_name', t('The group name %name is invalid.', array(
-        '%group_name' => $form_values['group_name'])));
+        '%group_name' => $form_values['group_id'])));
     }
   }
 }
@@ -254,7 +280,7 @@
       $groups_sorted = $data['groups_sorted'];
     }
     else {
-      $result = db_query("SELECT * FROM {". fieldgroup_tablename() ."} ORDER BY weight, group_name");
+      $result = db_query("SELECT fg.*, ml.plid, ml.menu_name, ml.weight FROM {". fieldgroup_tablename() ."} fg INNER JOIN {menu_links} ml ON ml.mlid = fg.mlid GROUP BY ml.menu_name ORDER BY ml.weight, fg.group_name");
       $groups = array();
       $groups_sorted = array();
       while ($group = db_fetch_array($result)) {
@@ -264,10 +290,11 @@
         $groups_sorted[$group['type_name']][] = &$groups[$group['type_name']][$group['group_name']];
       }
       //load fields
-      $result = db_query("SELECT nfi.*, ng.group_name FROM {". fieldgroup_tablename() ."} ng ".
+      $result = db_query("SELECT nfi.*, ml.weight, ng.group_name FROM {". fieldgroup_tablename() ."} ng ".
  "INNER JOIN {". fieldgroup_fields_tablename() ."} ngf ON ngf.type_name = ng.type_name AND ngf.group_name = ng.group_name ".
  "INNER JOIN {". content_instance_tablename() ."} nfi ON nfi.field_name = ngf.field_name AND nfi.type_name = ngf.type_name ".
- "WHERE nfi.widget_active = 1 ORDER BY nfi.weight");
+ "INNER JOIN {menu_links} ml ON ml.mlid = ng.mlid ".
+ "WHERE nfi.widget_active = 1 ORDER BY ml.weight");
       while ($field = db_fetch_array($result)) {
         $groups[$field['type_name']][$field['group_name']]['fields'][$field['field_name']] = $field;
       }
@@ -298,33 +325,17 @@
   return db_result(db_query("SELECT group_name FROM {". fieldgroup_fields_tablename() ."} WHERE type_name = '%s' AND field_name = '%s'", $content_type, $field_name));
 }
 
+function fieldgroup_collect_fieldsets($arr) {
+  return array("gid_{$group['pid']}" => $arr);
+}
+
 /*
  * Implementation of hook_form_alter()
  */
 function fieldgroup_form_alter(&$form, $form_state, $form_id) {
   if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
-    foreach (fieldgroup_groups($form['type']['#value']) as $group_name => $group) {
-      $form[$group_name] = array(
-        '#type' => 'fieldset',
-        '#title' => t($group['label']),
-        '#collapsed' => $group['settings']['form']['style'] == 'fieldset_collapsed',
-        '#collapsible' => in_array($group['settings']['form']['style'], array('fieldset_collapsed', 'fieldset_collapsible')),
-        '#weight' => $group['weight'],
-        '#description' => t($group['settings']['form']['description']),
-        '#attributes' => array('class' => strtr($group['group_name'], '_', '-')),
-      );
-      foreach ($group['fields'] as $field_name => $field) {
-        if (isset($form[$field_name])) {
-          $form[$group_name][$field_name] = $form[$field_name];
-          unset($form[$field_name]);
-        }
-      }
-      if (!empty($group['fields']) && !element_children($form[$group_name])) {
-        //hide the fieldgroup, because the fields are hidden too
-        unset($form[$group_name]);
-      }
-    }
-
+    $groups = fieldgroup_groups($form['type']['#value']);
+    $form += fieldgroup_add_fieldsets($groups);
   }
   elseif ($form_id == '_content_admin_field') {
     $content_type = content_types($form['type_name']['#value']);
@@ -354,6 +365,71 @@
   }
 }
 
+function fieldgroup_add_child_fieldset(&$groups, &$form = array()) {
+
+  list($group_name, $group) = each($groups);
+  array_shift($groups);
+  $menu = menu_link_load($group['mlid']);
+  $form[$group_name] = array(
+    '#type' => 'fieldset',
+    '#title' => t($group['label']),
+    '#collapsed' => $group['settings']['form']['style'] == 'fieldset_collapsed',
+    '#collapsible' => in_array($group['settings']['form']['style'], array('fieldset_collapsed', 'fieldset_collapsible')),
+    '#description' => t($group['settings']['form']['description']),
+    '#weight' => $group['weight'],
+    '#attributes' => array('class' => strtr($group['group_name'], '_', '-')),
+  );
+  if (!empty($menu['has_children'])) {
+    $form[$group_name] += fieldgroup_add_child_fieldset($groups, $form[$group_name]);
+  }
+  foreach ($group['fields'] as $field_name => $field) {
+    if (isset($form[$field_name])) {
+      $form[$group_name][$field_name] = $form[$field_name];
+      unset($form[$field_name]);
+    }
+  }
+  if (!empty($group['fields']) && !element_children($form[$group_name])) {
+    //hide the fieldgroup, because the fields are hidden too
+    unset($form[$group_name]);
+  }
+  reset($groups);
+  return $form;
+}
+
+function fieldgroup_add_fieldsets(&$groups, &$form = array()) {
+  reset($groups);
+  while (list($group_name, $group) = each($groups)) {
+
+    array_shift($groups);
+    $menu = menu_link_load($group['mlid']);
+    $form[$group_name] = array(
+      '#type' => 'fieldset',
+      '#title' => t($group['label']),
+      '#collapsed' => $group['settings']['form']['style'] == 'fieldset_collapsed',
+      '#collapsible' => in_array($group['settings']['form']['style'], array('fieldset_collapsed', 'fieldset_collapsible')),
+      '#description' => t($group['settings']['form']['description']),
+      '#weight' => $group['weight'],
+      '#attributes' => array('class' => strtr($group['group_name'], '_', '-')),
+    );
+    if (!empty($menu['has_children'])) {
+      $form[$group_name] += fieldgroup_add_child_fieldset($groups, $form[$group_name]);
+    }
+    foreach ($group['fields'] as $field_name => $field) {
+      if (isset($form[$field_name])) {
+        $form[$group_name][$field_name] = $form[$field_name];
+        unset($form[$field_name]);
+      }
+    }
+    if (!empty($group['fields']) && !element_children($form[$group_name])) {
+      //hide the fieldgroup, because the fields are hidden too
+      unset($form[$group_name]);
+    }
+    reset($groups);
+  }
+
+  return $form;
+}
+
 function fieldgroup_content_admin_form_submit($form, &$form_state) {
   $form_values = $form_state['values'];
   fieldgroup_update_fields($form_values);
@@ -370,7 +446,7 @@
     }
     // Update groups weights.
     elseif (in_array($key, $form['#groups'])) {
-      db_query("UPDATE {". fieldgroup_tablename() ."} SET weight = %d WHERE type_name = '%s' AND group_name = '%s'",
+      db_query("UPDATE {menu_links} SET weight = %d WHERE mlid IN (SELECT mlid FROM ". fieldgroup_tablename() ." WHERE type_name = '%s' AND group_name = '%s')",
         $values['weight'], $type_name, $key);
     }
   }
@@ -481,6 +557,16 @@
   return FALSE;
 }
 
+function fieldgroup_lookup_gid($gid) {
+  $result = db_query('SELECT * FROM {content_group} WHERE gid = %d', $gid);
+  if ($group = db_fetch_array($result)) {
+    return $group;
+  }
+  else {
+    return FALSE;
+  }
+}
+
 /**
  *  Implementation of hook_node_type()
  *  React to change in node types
@@ -522,38 +608,61 @@
  * Saves the given group for this content-type
  */
 function fieldgroup_save_group($type_name, $group) {
-  $groups = fieldgroup_groups($type_name);
+  $group['type_name'] = $type_name;
+  unset($type_name);
 
-  if (!isset($groups[$group['group_name']])) {
-    // Accept group name from programmed submissions if valid.
-    if (!empty($group['group_name'])) {
-      $group_name = $group['group_name'];
-    }
-    else {
-      // Otherwise, find a valid, computer-friendly name.
-      $group_name = trim($group['label']);
-      $group_name = drupal_strtolower($group_name);
-      $group_name = str_replace(array(' ', '-'), '_', $group_name);
-      $group_name = preg_replace('/[^a-z0-9_]/', '', $group_name);
-      $group_name = 'group_'. $group_name;
-      $group_name = substr($group_name, 0, 30);
-      if (isset($groups[$group_name])) {
-        $group_name_base = $group_name;
-        $counter = 0;
-        while (isset($groups[$group_name])) {
-          $group_name = $group_name_base .'_'. $counter++;
-        }
+  $groups = fieldgroup_groups($group['type_name']);
+
+  if (!empty($group['group_name'])) {
+    $group_name = $group['group_name'];
+  }
+  else {
+    // Otherwise, find a valid, computer-friendly name.
+    $group_name = trim($group['label']);
+    $group_name = drupal_strtolower($group_name);
+    $group_name = str_replace(array(' ', '-'), '_', $group_name);
+    $group_name = preg_replace('/[^a-z0-9_]/', '', $group_name);
+    $group_name = 'group_'. $group_name;
+    $group_name = substr($group_name, 0, 30);
+    if (isset($groups[$group_name])) {
+      $group_name_base = $group_name;
+      $counter = 0;
+      while (isset($groups[$group_name])) {
+        $group_name = $group_name_base .'_'. $counter++;
       }
     }
-    db_query("INSERT INTO {". fieldgroup_tablename() ."} (type_name, group_name, label, settings, weight)
-             VALUES ('%s', '%s', '%s', '%s', %d)", $type_name, $group_name, $group['label'], serialize($group['settings']), $group['weight']);
+  }
+  $group['group_name'] = $group_name;
+  unset($group_name);
+
+  $group['menu'] = array(
+    'menu_name'   => fieldgroup_menu_name($group),
+    'link_path'   => 'group:admin/content/types/'. $group['type_name'] .'/groups/'. $group['group_name'] .'/edit',
+    'router_path' => 'admin/content/types/'. $group['type_name'] .'/groups/'. $group['group_name'] .'/edit',
+    'link_title'  => $group['group_name'],
+    'module'      => 'fieldgroup',
+    'weight'      => empty($group['weight']) ? 0 : $group['weight'],
+    'mlid'        => isset($group['mlid']) ? $group['mlid'] : NULL,
+    'plid'        => empty($group['parent']) ? 0 : $group['parent']
+  );
+  menu_link_save($group['menu']);
+
+  if (!isset($groups[$group['group_name']])) {
+    // fix a chicken/egg problem where the ID portion of menu_name isn't
+    // created yet, so go back and add it to the menu_name
+    if (empty($group['mlid'])) {
+      $group['mlid'] = db_last_insert_id('menu_links', 'mlid');
+      db_query("UPDATE {menu_links} SET menu_name = '%s' WHERE mlid = %d LIMIT 1", fieldgroup_menu_name($group), $group['mlid']);
+    }
+
+    db_query('INSERT INTO {'. fieldgroup_tablename() ."} (mlid, type_name, group_name, label, settings)
+             VALUES ('%s', '%s', '%s', '%s', '%s')", $group['menu']['mlid'], $group['type_name'], $group['group_name'], $group['label'], serialize($group['settings']));
     cache_clear_all('fieldgroup_data', content_cache_tablename());
     return SAVED_NEW;
   }
   else {
-    db_query("UPDATE {". fieldgroup_tablename() ."} SET label = '%s', settings = '%s', weight = %d ".
-             "WHERE type_name = '%s' AND group_name = '%s'",
-             $group['label'], serialize($group['settings']), $group['weight'], $type_name, $group['group_name']);
+    db_query('UPDATE {'. fieldgroup_tablename() ."} SET mlid = %d, label = '%s', settings = '%s' WHERE mlid = %d",
+             $group['menu']['mlid'], $group['label'], serialize($group['settings']), $group['mlid']);
     cache_clear_all('fieldgroup_data', content_cache_tablename());
     return SAVED_UPDATED;
   }
@@ -583,3 +692,13 @@
   db_query("DELETE FROM {". fieldgroup_fields_tablename() ."} WHERE  type_name = '%s' AND group_name = '%s'", $content_type, $group_name);
   cache_clear_all('fieldgroup_data', content_cache_tablename());
 }
+
+function fieldgroup_menu_name(&$group) {
+  if (empty($group['parent'])) {
+    $mlid = empty($group['mlid']) ? '' : $group['mlid'];
+    return "fieldgroup-$mlid";
+  }
+  else {
+    return db_result(db_query_range('SELECT menu_name FROM {menu_links} WHERE mlid = %d', $group['parent'], 0, 1));
+  }
+}
