--- sites/all/modules/cck/modules/fieldgroup/fieldgroup.module Mon Dec 01 18:43:50 2008 +++ sites/all/modules/cck/modules/fieldgroup/fieldgroup.module Tue Dec 23 11:26:22 2008 @@ -58,6 +58,7 @@ * Implementation of hook_theme(). */ function fieldgroup_theme() { + //TODO do I need to add any theme functions? return array( 'fieldgroup_simple' => array( 'template' => 'fieldgroup', @@ -160,6 +161,7 @@ $form['settings']['display']['label'] = array('#type' => 'value', '#value' => $group['settings']['display']['label']); $form['weight'] = array('#type' => 'hidden', '#default_value' => $group['weight']); $form['group_name'] = array('#type' => 'hidden', '#default_value' => $group_name); + $form['parent_group_name'] = array('#type' => 'hidden', '#default_value' => $group['parent_group_name']); $form['#content_type'] = $content_type; @@ -204,7 +206,10 @@ $form_values = $form_state['values']; $content_type = $form['#content_type']; $group_name = $form['#group_name']; - fieldgroup_delete($content_type['type'], $group_name); + $parent_group_name = db_fetch_array(db_query("SELECT parent_group_name FROM {". fieldgroup_tablename() ."} WHERE group_name = '%s' and type_name = '%s'", $group_name, $content_type['type'])); + $result = db_query("UPDATE {". fieldgroup_tablename() ."} SET parent_group_name = '%s' WHERE parent_group_name = '%s'", $parent_group_name['parent_group_name'], $group_name); + $result = db_query("UPDATE {". fieldgroup_fields_tablename() ."} SET group_name = '%s' WHERE group_name = '%s'", $parent_group_name['parent_group_name'], $group_name); + fieldgroup_delete($content_type['type'], $group_name); drupal_set_message(t('The group %group_name has been removed.', array('%group_name' => $group_name))); $form_state['redirect'] = 'admin/content/node-type/'. $content_type['url_str'] .'/fields'; } @@ -221,23 +226,13 @@ $groups_sorted = $data['groups_sorted']; } else { - $result = db_query("SELECT * FROM {". fieldgroup_tablename() ."} ORDER BY weight, group_name"); + $result = db_query("SELECT type_name, group_name FROM {". fieldgroup_tablename() ."} ORDER BY type_name"); $groups = array(); $groups_sorted = array(); while ($group = db_fetch_array($result)) { - $group['settings'] = unserialize($group['settings']); - $group['fields'] = array(); - $groups[$group['type_name']][$group['group_name']] = $group; + $groups[$group['type_name']] = _fieldgroup_get_tree($group['type_name']); $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 ". - "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"); - while ($field = db_fetch_array($result)) { - $groups[$field['type_name']][$field['group_name']]['fields'][$field['field_name']] = $field; - } cache_set('fieldgroup_data', array('groups' => $groups, 'groups_sorted' => $groups_sorted), content_cache_tablename()); } } @@ -250,6 +245,69 @@ return $sorted ? $groups_sorted[$content_type] : $groups[$content_type]; } +/** + * create a tree of fieldgroups for nesting them + */ +function _fieldgroup_get_tree($type_name, $parent_group_name = '', $depth = -1, $max_depth = null) { + static $children, $parents, $groups; + + $depth++; + // We cache trees, so it's not CPU-intensive to call get_tree() on a term + // and its children, too. + if (!isset($children[$type_name])) { + $children[$type_name] = array(); + + $s = "SELECT * FROM {". fieldgroup_tablename() ."} WHERE type_name='%s' ORDER BY weight"; + $r = db_query($s, $type_name); + while ($group = db_fetch_array($r)) { + $children[$type_name][$group['parent_group_name']][] = $group['group_name']; + $parents[$type_name][$group['group_name']][] = $group['parent_group_name']; + $groups[$type_name][$group['group_name']] = $group; + $groups[$type_name][$group['group_name']]['fields'] = array(); + $groups[$type_name][$group['group_name']]['settings'] = unserialize($group['settings']); + } + //load fields + $result = db_query("SELECT nfi.*, 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"); + while ($field = db_fetch_array($result)) { + $groups[$field['type_name']][$field['group_name']]['fields'][$field['field_name']] = $field; + } + } + + $max_depth = (is_null($max_depth)) ? count($children[$type_name]) : $max_depth; + if (isset($children[$type_name][$parent_group_name])) { + foreach ($children[$type_name][$parent_group_name] as $child_group_name) { + if ($max_depth > $depth) { + $group = $groups[$type_name][$child_group_name]; + $group['depth'] = $depth; + $group['parents'] = $parents[$type_name][$child_group_name]; + $tree[$group['group_name']] = $group; + if ($children[$type_name][$child_group_name]) { + $tree = array_merge($tree, _fieldgroup_get_tree($type_name, $child_group_name, $depth, $max_depth)); + } + } + } + } + return $tree ? $tree : array(); +} + +/** + * go through a set of fieldgroups and construct a simple representation of their hierarchy + */ +function _fieldgroup_plain_tree($items) { + $rows = array(); + $rows[''] = '<'. t('none') .'>'; + foreach ($items as $item) { + $group_name = $item['group_name']; + $label = t($item['label']); + if ($group_name) { + $rows[$group_name] = str_repeat('--', $item['depth']) . ' ' . $label; + } + } + return $rows; +} function _fieldgroup_groups_label($content_type) { $groups = fieldgroup_groups($content_type); @@ -265,53 +323,114 @@ 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_add_group_to_form(&$form, &$form_state, $form_id, $element, $group_name, $group, $groups) { + $element = array( + '#type' => 'fieldset', + '#title' => check_plain(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' => content_filter_xss(t($group['settings']['form']['description'])), + '#attributes' => array('class' => strtr($group['group_name'], '_', '-')), + ); + $has_accessible_field = FALSE; + foreach ($group['fields'] as $field_name => $field) { + if (isset($form[$field_name])) { + $element[$field_name] = $form[$field_name]; + //Track whether this group has any accessible fields within it. + if (!isset($form[$field_name]['#access']) || $form[$field_name]['#access'] !== FALSE) { + $has_accessible_field = TRUE; + } + unset($form[$field_name]); + } + } + if (!empty($group['fields']) && !element_children($form[$group_name])) { + //hide the fieldgroup, because the fields are hidden too + unset($element[$group_name]); + } + + if (!$has_accessible_field) { + // Hide the fieldgroup, because the fields are inaccessible. + $form[$group_name]['#access'] = FALSE; + } + + // Allow other modules to alter the form. + // Can't use module_invoke_all because we want + // to be able to use a reference to $form and $form_state. + foreach (module_implements('fieldgroup_form') as $module) { + $function = $module .'_fieldgroup_form'; + $function($form, $form_state, $form_id, $group); + } + + $parent_group_name = $group_name; + foreach ($groups as $group_name => $group) { + if ($group['parent_group_name'] == $parent_group_name) { + $element[$group_name] = _fieldgroup_add_group_to_form($form, $form_state, $form_id, $element[$group_name], $group_name, $group, $groups); + } + } + + return $element; +} + /** * Implementation of hook_form_alter() */ function fieldgroup_form_alter(&$form, $form_state, $form_id) { if (isset($form['type']) && isset($form['#node']) && $form['type']['#value'] .'_node_form' == $form_id) { - foreach (fieldgroup_groups($form['type']['#value']) as $group_name => $group) { - $form[$group_name] = array( - '#type' => 'fieldset', - '#title' => check_plain(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' => content_filter_xss(t($group['settings']['form']['description'])), - '#attributes' => array('class' => strtr($group['group_name'], '_', '-')), - ); - - $has_accessible_field = FALSE; - foreach ($group['fields'] as $field_name => $field) { - if (isset($form[$field_name])) { - $form[$group_name][$field_name] = $form[$field_name]; - // Track whether this group has any accessible fields within it. - if (!isset($form[$field_name]['#access']) || $form[$field_name]['#access'] !== FALSE) { - $has_accessible_field = TRUE; - } - unset($form[$field_name]); + if ((arg(0)=='node' && arg(1)=='add') || (arg(0)=='node' && is_numeric(arg(1)) && arg(2)=='edit')) { + $groups = fieldgroup_groups($form['type']['#value']); + foreach ($groups as $group_name => $group) { + //drupal_set_message('
Name:'.print_r($group_name, 1).'
'); + //drupal_set_message('
Group:'.print_r($group, 1).'
'); + $parent_group_name = $group['parent_group_name']; + if ($parent_group_name) { + $groups[$group_name]['weight'] = $groups[$parent_group_name]['weight'] + abs($groups[$group_name]['depth'] * .1) + abs($groups[$group_name]['weight'] * .01); } } - if (!empty($group['fields']) && !element_children($form[$group_name])) { - //hide the fieldgroup, because the fields are hidden too - unset($form[$group_name]); - } - - if (!$has_accessible_field) { - // Hide the fieldgroup, because the fields are inaccessible. - $form[$group_name]['#access'] = FALSE; + foreach ($groups as $group_name => $group) { + $parent_group_name = $group['parent_group_name']; + if (!$parent_group_name) { + $form[$group_name] = _fieldgroup_add_group_to_form($form, $form_state, $form_id, $form[$group_name], $group_name, $group, $groups); + } } - - // Allow other modules to alter the form. - // Can't use module_invoke_all because we want - // to be able to use a reference to $form and $form_state. - foreach (module_implements('fieldgroup_form') as $module) { - $function = $module .'_fieldgroup_form'; - $function($form, $form_state, $form_id, $group); + } + else { + //Sort groups by weight + foreach ($groups 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]); + } + + if (!$has_accessible_field) { + // Hide the fieldgroup, because the fields are inaccessible. + $form[$group_name]['#access'] = FALSE; + } + + // Allow other modules to alter the form. + // Can't use module_invoke_all because we want + // to be able to use a reference to $form and $form_state. + foreach (module_implements('fieldgroup_form') as $module) { + $function = $module .'_fieldgroup_form'; + $function($form, $form_state, $form_id, $group); + } } - } - } // The group is only added here so it will appear in the export // when using Content Copy. @@ -435,6 +554,8 @@ // Parse incoming rows. $add_field_rows = array('_add_new_field', '_add_existing_field'); $field_rows = array_merge($form['#fields'], $add_field_rows); + $add_group_rows = array($new_group_name); + $group_rows = array_merge($form['#groups'], $add_group_rows); foreach ($form_values as $key => $values) { // If 'field' row: update field parenting. if (in_array($key, $field_rows)) { @@ -458,18 +579,71 @@ // TODO: check the parent group does exist ? fieldgroup_update_fields(array('field_name' => $key, 'group' => $parent, 'type_name' => $type_name)); } + } - // If 'group' row: update groups weights + $top_groups = array(); + $parent_child_list = array(); + reset($form_values); + foreach ($form_values as $key => $values) { + if (in_array($key, $group_rows)) { + if (empty($values['parent']) || $values['parent'] == $values['hidden_name']) { + $top_groups[$values['weight']][] = $values['hidden_name'];//this allows for groups that are the same weight after submission + } + else { + $parent_child_list[$values['parent']][] = $values['hidden_name']; + } + } + } + $low_index = 0; + foreach ($top_groups as $weight => $data) { + if ($weight < $low_index) { + $low_index = $weight; + } + sort($top_groups[$weight]); + } + //we don't want top level groups to have the same weight as each other, so let's change that here + $top_groups_reordered = array($low_index => $top_groups[$low_index][0]); + foreach ($top_groups as $weight => $data) { + foreach ($data as $index => $name) { + if (($weight != $low_index) || ($index != 0)) { + $top_groups_reordered[] = $name; + } + } + } + foreach ($top_groups_reordered as $weight => $name) { + $form_state['values'][$name]['weight'] = $weight; + } + foreach ($top_groups_reordered as $index => $name) { + fieldgroup_parent_child_recurse($form_state, $name, $index, $parent_child_list); + } + //drupal_set_message('
Values: ' . print_r($form_state['values'], TRUE) . '
'); + foreach ($form_state['values'] as $key => $values) { + // If 'group' row: update groups weights and parent // (possible newly created group has already been taken care of). - elseif (in_array($key, $form['#groups'])) { - db_query("UPDATE {". fieldgroup_tablename() ."} SET weight = %d WHERE type_name = '%s' AND group_name = '%s'", - $values['weight'], $type_name, $key); + if (in_array($key, $group_rows)) { + $parent = ($values['parent'] == '_add_new_group' && isset($new_group_name)) ? $new_group_name : $values['parent']; + $weight = $values['weight']; + //drupal_set_message('
Key: ' . print_r($key, TRUE) . '
'); + //drupal_set_message('
Parent: ' . print_r($parent, TRUE) . '
'); + //drupal_set_message('
Weight: ' . print_r($weight, TRUE) . '
'); + db_query("UPDATE {". fieldgroup_tablename() ."} SET weight = %d, parent_group_name = '%s' WHERE type_name = '%s' AND group_name = '%s'", $weight, $parent, $type_name, $key); } } - + cache_clear_all('fieldgroup_data', content_cache_tablename()); } +function fieldgroup_parent_child_recurse(&$form_state, $name, $index, $list) { + //drupal_set_message('
Name: ' . print_r($name, TRUE) . '
'); + //drupal_set_message('
Index - weight: ' . print_r($index, TRUE) . '
'); + if (isset($list[$name])) { + foreach ($list[$name] as $index2 => $group_name) { + $form_state['values'][$group_name]['weight'] = $index; + fieldgroup_parent_child_recurse($form_state, $group_name, $index, $list); + } + } +} + function field_group_default_settings($group_type) { $settings = array( 'form' => array('style' => 'fieldset', 'description' => ''), @@ -609,7 +783,7 @@ return $content; } -/* +/** * Get the group name for a field. * If the field isn't in a group, FALSE will be returned. * @return The name of the group, or FALSE. @@ -681,15 +855,15 @@ if (!isset($groups[$group['group_name']])) { // Accept group name from programmed submissions if valid. - db_query("INSERT INTO {". fieldgroup_tablename() ."} (group_type, type_name, group_name, label, settings, weight)". - " VALUES ('%s', '%s', '%s', '%s', '%s', %d)", $group['group_type'], $type_name, $group['group_name'], $group['label'], serialize($group['settings']), $group['weight']); + db_query("INSERT INTO {". fieldgroup_tablename() ."} (parent_group_name, group_type, type_name, group_name, label, settings, weight)". + " VALUES ('%s','%s', '%s', '%s', '%s', '%s', %d)", $group['parent_group_name'], $group['group_type'], $type_name, $group['group_name'], $group['label'], serialize($group['settings']), $group['weight']); cache_clear_all('fieldgroup_data', content_cache_tablename()); return SAVED_NEW; } else { - db_query("UPDATE {". fieldgroup_tablename() ."} SET group_type = '%s', label = '%s', settings = '%s', weight = %d ". - "WHERE type_name = '%s' AND group_name = '%s'", - $group['group_type'], $group['label'], serialize($group['settings']), $group['weight'], $type_name, $group['group_name']); + db_query("UPDATE {". fieldgroup_tablename() ."} SET parent_group_name = '%s', group_type = '%s', label = '%s', settings = '%s', weight = %d ". + "WHERE type_name = '%s' AND group_name = '%s'", + $group['parent_group_name'], $group['group_type'], $group['label'], serialize($group['settings']), $group['weight'], $type_name, $group['group_name']); cache_clear_all('fieldgroup_data', content_cache_tablename()); return SAVED_UPDATED; } @@ -740,7 +914,9 @@ $element['#attributes']['class'] .= ' collapsed'; } } - return ''. ($element['#title'] ? ''. $element['#title'] .'' : '') . (isset($element['#description']) && $element['#description'] ? '
'. $element['#description'] .'
' : '') . (!empty($element['#children']) ? $element['#children'] : '') . (isset($element['#value']) ? $element['#value'] : '') ."\n"; + return ''. ($element['#title'] ? ''. $element['#title'] .'' : '') + . (isset($element['#description']) && $element['#description'] ? '
'. $element['#description'] .'
' : '') + . (!empty($element['#children']) ? $element['#children'] : '') . (isset($element['#value']) ? $element['#value'] : '') ."\n"; } @@ -759,6 +935,7 @@ function fieldgroup_preprocess_fieldgroup_simple(&$vars) { $element = $vars['element']; + $vars['parent_group_name'] = $element['#parent_group_name']; $vars['group_name'] = $element['#group_name']; $vars['group_name_css'] = strtr($element['#group_name'], '_', '-'); $vars['label'] = isset($element['#title']) ? $element['#title'] : '';;