Drupal: Hiding CCK fields with fieldgroups in hook_form_alter

So the task I had was to conditionally hide two fields in drupal CCK custom content type. When the record had one of three values in a select field, it should show the upload file fields. Otherwise it should hide it.

This is pretty straightforward in a regular module. One makes the changes in hook_form_alter. To hide, we would unset the fields.

function random_module_form_alter(&$form, $form_state, $form_id) {
    // make your changes here: change values, set defaults, hide fields
    // the easy life!
  }

This won't work if one is using CCK. The reason for that, as webchick explains in her blog entry, is that CCK fields are not present at hook_form_alter. She then presents the right approach, which is to use form API #after_build.

/**
* Implementation of hook_form_alter().
*/
function example_form_alter(&$form, $form_state, $form_id) {
  // Check for a particular content type's node form.
  if ($form_id == 'example_node_form') {
    // Add an after_build function to process when everything's complete.
    $form['#after_build'][] = 'example_after_build';
  }
}
 
/**
* Modify CCK form elements on the example node form.
*/
function example_after_build($form, &$form_state) {
  // TODO: Stuff!
 
  return $form;
}

This is the basic code structure for solving this problem. From this point, it should have been easy, right? Wrong. I ran into two problems: getting the values from the form and reaching the right form field to turn off.

The most natural solution for getting a value and setting a field to hide is to just reach for that field in the form

$value = $form["height"][0]["value"];
unset($form["height"]);

However, when dealing with CCK fields, the first one won't work, and the second one, in drupal 6, according to a stack overflow thread, can be dangerous since it can do unpredictable things.

So I examined the form object via print_r($form); followed by an exit; statement. There I saw that I could reach for the field that I wanted via $form["#node"]. This returns the node object.

$value = $form["#node"]->height[0]["value"];

Then I attempted to hide the field by unsetting the node values. This was a mistake, since the node object doesn't have anything to do with the form. Yet I couldn't find the form entry for the fields that I needed. Reading through the comments of webchick's entry, someone mentioned the field groups. Ah! Looking back, it seems self evident. I needed to reach the field via the group field first. And following the direction given in the stack overflow page, hiding the field uses the following syntax.

$form["measurements_group"]["height"][0]["#access"] = false;

Altogether, the code to hide a field in a CCK content type form looks like this:

function example_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'measurements_node_form') {
    // Add an after_build function to process when everything's complete.
    $form['#after_build'][] = 'example_after_build';
  }
}
 
function example_after_build($form, &$form_state) {
  $show = array("Edit more", "Incorrect");
  $term_id = $form["#node"]->height[0]["value"];
 
  $term = taxonomy_get_term($term_id);
 
  if ($term->name != "" && !in_array($term->name, $show)){
     $form["measurements_group"]["height"]["#access"] = false;
  }
  return $form;
}

Sources:
drupal 6 api on hook_form_alter
stack overflow
webchick's blog on hook_form_alter and CCK on drupal.org