I have created a module that is supposed to add a new node type. Nodes of this type are created using a multistep form. The necessary hooks are called, but they do not get the data from the form: there is node $node->point for example.

I will include the complete source code of the module here. First gastro.info

name = Gastro
description = gastronomy entry with address and marker on a map which is derived from the address
package = Seculogix Custom
core = 6.x

Next ist gastro.install:


/**
 * Implementation of hook_schema()
 */
function gastro_schema() {
  $schema['gastro_location'] = array(
    'description' => t('Stores the address and the calculated coordinates.'),
    'fields' => array(
      'nid'       => array('type' => 'int',   'unsigned' => TRUE, 'not null' => TRUE, 'description' => t('The {node} this location belongs to.')),
      'vid'       => array('type' => 'int',   'unsigned' => TRUE, 'not null' => TRUE, 'description' => t('The {node_revision} for this location.')),
      'street'    => array('type' => 'varchar', 'length' => 255,  'not null' => TRUE, 'description' => t('The street part of the address. Includes house number.')),
      'postal'    => array('type' => 'varchar', 'length' => 5,    'not null' => TRUE, 'description' => t('The postal code of the address. Note this is not a number.')),
      'city'      => array('type' => 'varchar', 'length' => 100,  'not null' => TRUE, 'description' => t('This is the city, town, village, or place of the address.')),
      'point'     => array('type' => 'varchar', 'length' => 40,   'not null' => TRUE, 'description' => t('The pait of coordinates for this address')),
    ),
    'primary key' => array('nid', 'vid'),
    'indexes' => array(
      'street_index' => array('street'),
      'postal_index' => array('postal'),
      'city_index'   => array('city'),
    ),
  );

  dsm($schema);
  return $schema;
}


/**
 * Implementation of hook_install()
 */
function gastro_install() {
  dsm("gastro_install");
  drupal_install_schema('gastro');
}

/** 
 * Implementation of hook_uninstall()
 */
function gastro_uninstall() {
  dsm("gastro_uninstall");
  drupal_uninstall_schema('gastro');
}

And finally gastro.module:


/**
 * Implementation of hook_node_info()
 */
function gastro_node_info() {
  return array(
    'gastro' => array(
      'name' => t('Restaurant'),
      'module' => 'gastro',
      'has_title' => TRUE,
      'title_label' => t('Name of the restaurant'),
      'has_body' => FALSE,
      'description' => 'foo',
    ),
  );
}

/**
 * Implementation of hook_form()
 *
 * This function will be called twice. The first time $node and $form_state 
 * will be almost empty. The second tme, $node->step will be set to one, and
 * $form_state will contain the $form_state['values']['test1'] element.
 */
function gastro_form(&$node, $form_state) {
  if (empty($form_state['values'])) {
    return gastro_address_form($node, $form_state);
  }
  else {
    return gastro_map_form($node, $form_state);
  }
}


function gastro_address_form(&$node, $form_state) {
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Name of the restaurant'),
    '#default_value' => $node->title,
    '#required' => TRUE,
  );

  $form['address'] = array(
    '#type' => 'fieldset',
    '#title' => t('Address'),
    '#collapsible' => FALSE,
    '#weight' => -5,
  );

  $form['address']['street'] = array(
    '#type' => 'textfield',
    '#title' => t('Street name and house number'),
    '#default_value' => $node->street,
    '#description' => t('Provide the street name and house number, just like are used to from letters.'),
    '#size' => 40,
    '#required' => TRUE,
  );

  $form['address']['postal'] = array(
    '#type' => 'textfield',
    '#title' => t('Postal code'),
    '#default_value' => $node->postal,
    '#description' => t('The postal code for the street above in the city below.'),
    '#size' => 6,
    '#maxlength' => 5,
    '#required' => TRUE,
  );

  $form['address']['city'] = array(
    '#type' => 'textfield',
    '#title' => t('City'),
    '#default_value' => $node->city,
    '#description' => t('The city, town, village, or place where the restaurant is.'),
    '#size' => 40,
    '#required' => TRUE,
  );

  return $form;
}

function gastro_map_form(&$node, $form_state) {
  $form['map'] = array(
    '#type' => 'fieldset',
    '#title' => t('Map View'),
    '#collapsible' => FALSE,
    '#weight' => -5,
  );

  $form['map']['gmapez'] = array(
    '#type' => 'markup',
    '#prefix' => '<div class="GMapEZ" id="gastro-gmapez">',
    '#suffix' => '</div>',
    '#value' => '<a href="http://maps.google.com/maps?ll='. gastro_calculate_point($form_state) .'"></a>',
  );

  $form['point'] = array(
    '#type' => 'item',
    '#title' => 'Point',
    '#value' => gastro_calculate_point($form_state),
  );

  return $form;
}

function gastro_calculate_point($form_state) {
  $output = 'csv';
  $gl = 'de';
  $key = variable_get('googlemap_api_key',NULL);

  $street = str_replace(' ', '+', $form_state['values']['street']);
  $postal = str_replace(' ', '+', $form_state['values']['postal']);
  $city   = str_replace(' ', '+', $form_state['values']['city']);
  $q = "$street,$postal+$city,Germany";

  $url = 'http://maps.google.com/maps/geo?gl=de&output='. $output .'&key='. $key .'&q='. $q; // is this secure code?
  $result = drupal_http_request($url);
  list($status_code, $precision, $p1, $p2) = explode(',', $result->data);

  if ($status_code == '200') {
    return "$p1,$p2";
  }

  return '';
}

/**
 * Implementation of hook_validate()
 */
function gastro_validate($node, &$form) {
}

/**
 * Implementation of hook_form_alter()
 */
function gastro_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'gastro_node_form') {
    if (empty($form_state['values'])) {
      $form['#rebuild'] = TRUE;
      unset($form['buttons']['submit']);
      $form['buttons']['preview']['#value'] = t('Next');

    }
    else {
      $form['#rebuild'] = FALSE;
      $form['#redirect'] = TRUE;
      unset($form['buttons']['preview']);
    }
  }
}

/**
 * Implementation of hook_insert()
 */
function gastro_insert($node) {
  $query = "
  INSERT
  INTO {gastro_location} (nid, vid, street, postal, city, point)
  VALUES (%d, %d, '%s', '%s', '%s', '%s')";
  dsm($node);
  db_query($query, $node->nid, $node->vid, $node->street, $node->postal, $node->city, $node->point);
}

/**
 * Implementation of hook_update()
 */
function gastro_update($node) {
  if ($node->revision) {
    gastro_insert($node);
  }
  else {
    $query = "
    UPDATE {gastro_location}
    SET street = '%s', postal = '%s', city = '%s', point = '%s'
    WHERE vid = %d";

    db_query($query, $node->street, $node->postal, $node->city, $node->point);
    }
}

/**
 * Implementation of hook_load()
 */
function gastro_load($node) {
  $query = "
  SELECT street, postal, city, point
  FROM {gastro_location}
  WHERE vid = %d";
  
  $result = db_query($query, $node->vid);
  $object = db_fetch_object($result);
  dsm($object);
  return $object;
}

/**
 * Implementation of hook_nodeapi()
 *
 * When a node revision is deleted, we need to remove the corresponding record
 * from our table. The only way to handle revision deletion is by implementing
 * hook_nodeapi().
 */
function gastro_nodeapi(&$node, $op, $teaser=NULL, $page=NULL) {
  dsm("op=$op");
  dsm($node);
  switch ($op) {
    case 'delete revision':
      $query = "
      DELETE
      FROM {gastro_location}
      WHERE vid = %d";
      db_query($query, $node->vid);
      break;
  }
}

/**
 * Implementation of hook_delete()
 *
 * When a node is deleted, we need to remove all related records from our table
 */
function gastro_delete($node) {
  $query = "
  DELETE
  FROM {gastro_location}
  WHERE nid = %d";
  db_query($query, $node->nid);
}

The multistep form seems to work, but somewhere between clicking "Submit" and gastro_insert() being called, some things are lost.

I have marked this as support request because I assume I have forgotten something. I am willing to try everything, as I am at my wit's end now.

Comments

housetier’s picture

Status: Active » Closed (won't fix)

It's been over a week with no response, only wild guesses on IRC. I guess I have hit a wall and will have to find a way to do it differently.

Going to close it now...