I am in the process of developing a module which creates a custom content type stock with fields name(title), description(body) unique_name, type_name, organism_name, & crossblock_name. The creation form is working (both form display & creation of node ->saving extra fields into a separate db table) and viewing stocks is working. However, after viewing a stock node ->which has all the values being displayed, the edit form is blank ->even for the title and body fields.

As you can see in my chado_stock_form() I have all the default values set to $node->value (thus it's not the problem stated here - [730238] ).
I've checked the database and all the values are being saved correctly (as evidenced by the viewing of stock nodes working). I tried adding a print_r($node) to the top of my hook_form but nothing printed (either when create or edit form was displayed).

I also tried adding $node = node_load($node->nid); at the top of the form just in case the node being passed in wasn't loading correctly. This didn't fix the lack of values on edit and nothing was printed with the print_r($node) after the node_load().

I'm still a little unclear on which hooks get called when -Is there a diagram showing this somewhere? When displaying the edit form where does hook_form get called from and where is the $node being passed in coming from?

Here is my chado_stock.module file:

// $Id$

/**
 * Implementation of hook_help()
 */
function chado_stock_help($path, $arg) {
  if ($path == 'admin/help#chado_stock') {
    $txt = 'There will be help text here whenever there is anything to help with...';
    $replace = array();
    return '<p>' . t($txt, $replace) . '<p>';
  }
}

/**
 * Implements hook_node_info()
 */
function chado_stock_node_info() {
  return array(
    'chado_stock' => array(
      'name' => t('Chado Stock'),
      'module' => 'chado_stock',
      'description' => t('The Mapping to a GMOD Chado Stock'),
      'has_title' => TRUE,
      'title_label' => t('Stock Name'),
      'has_body' => TRUE,
      'body_label' => t('Description'),
    ),
  );
}

/**
 * Implements hook_form()
 */
function chado_stock_form() {
  $type = node_get_types('type', $node);

  // Existing files: title (Stock Name) and body (Description)
    $form['title'] = array(
      '#type' => 'textfield',
      '#title' => t('Stock Name'),
      '#required' => TRUE,
      '#default_value' => $node->title,
      '#weight' => -5
    );

    $form['body_field'] = node_body_field(
      $node,
      t('Description'),
      $type->min_word_count
    );

  // Our custom fields:      'unique_name'        'type_name'        'organism_name'        'crossblock_name'
  $form['unique_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Unique Stock Identifier'),
    '#required' => TRUE,
    '#default_value' => $node->unique_name
  );

  $form['type_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Type of Stock'),
    '#required' => TRUE,
    '#default_value' => $node->type_name
  );

  $form['organism_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Source Organism Name'),
    '#required' => TRUE,
    '#default_value' => $node->organism_name
  );

  $form['crossblock_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Crossing Block'),
    '#required' => TRUE,
    '#default_value' => $node->crossblock_name
  );

  return $form;
}

/**
 * Implements hook_perm()
 */
function chado_stock_perm() {
  return array(
    'access Chado Stocks',
    'create Chado Stocks',
    'edit Chado Stocks',
    'delete Chado Stocks',
  );
}

/**
 * Implements hook_access()
 */
function chado_stock_access($op, $node, $account) {
  switch ($op) {
    case 'view':
      return user_access('access Chado Stocks', $account);
    case 'create':
      return user_access('create Chado Stocks', $account);
    case 'edit':
      return user_access('edit Chado Stocks', $account);
    case 'delete':
      return user_access('delete Chado Stocks', $account);
  }
}

/**
 * Implements hook_insert()
 */
function chado_stock_insert($node) {
  drupal_write_record('chado_stock', $node);
}

/**
 * Implements hook_update()
 */
function chado_stock_update($node) {
  if ($node->revision) {
    chado_stock_insert($node);
  } else {
    $result = db_query(
      "UPDATE {chado_stock} SET unique_name='%s', type_name='%s', organism_name='%s', crossingblock_name='%s' WHERE vid=%d",
      $node->unique_name,
      $node->type_name,
      $node->organism_name,
      $node->crossingblock_name,
      $node->vid
    );
  }
}

/**
 * Implements hook_delete()
 */
function chado_stock_delete($node) {
  db_query(
    "DELETE FROM {chado_stock} WHERE nid=%d",
    $node->nid
  );
}

/**
 * Implements hook_nodeapi()
 * This implementation just handles deleting node revisions
 */
function chado_stock_nodeapi(&$node, $op, $teaser, $page) {
  if ($op=='delete revision') {
    db_query(
      "DELETE FROM {chado_stock} WHERE vid=%d",
      $node->vid
    );
  }
}

/**
 * Implements hook_load()
 */
function chado_stock_load($node) {
  //---------------------
  //get node before custom fields
  // not sure this is necessary but..

  // Retrieve a field list based on the site's schema.
  $fields = drupal_schema_fields_sql('node', 'n');
  $fields = array_merge($fields, drupal_schema_fields_sql('node_revisions', 'r'));
  $fields = array_merge($fields, array('u.name', 'u.picture', 'u.data'));
  // Remove fields not needed in the query: n.vid and r.nid are redundant,
  // n.title is unnecessary because the node title comes from the
  // node_revisions table.  We'll keep r.vid, r.title, and n.nid.
  $fields = array_diff($fields, array('n.vid', 'n.title', 'r.nid'));
  $fields = implode(', ', $fields);
  // Rename timestamp field for clarity.
  $fields = str_replace('r.timestamp', 'r.timestamp AS revision_timestamp', $fields);
  // Change name of revision uid so it doesn't conflict with n.uid.
  $fields = str_replace('r.uid', 'r.uid AS revision_uid', $fields);

  $cnode = db_fetch_object(
    db_query(
      'SELECT '. $fields .' FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE n.nid=%d AND n.vid=%d',
      $node->nid,
      $node->vid
    )
  );

  //---------------------
  //get custom fields
  $result = db_query(
    "SELECT c.unique_name, c.type_name, c.organism_name, c.crossblock_name FROM {chado_stock} c WHERE vid=%d",
    $node->vid
  );
  $custom_fields = db_fetch_array($result);

  //add custom fields to node
  $cnode->unique_name = $custom_fields['unique_name'];
  $cnode->type_name = $custom_fields['type_name'];
  $cnode->organism_name = $custom_fields['organism_name'];
  $cnode->crossblock_name = $custom_fields['crossblock_name'];

  return $cnode;
}

Comments

laceysanderson’s picture

After changing crossingblock_name to crossblock_name n the update hook, filling in each value and then clicking save does change the values on the display page and in the database... thus only showing the default values in the edit form seems to be a problem.

Cannot delete without first filling in values. (After manually filling in random values, delete works).

nevets’s picture

A few pointers

1) chado_stock_form() should be chado_stock_form($node, $form_state)

2) chado_stock_load() should only be adding your fields, not building the whole node

3) You can update the node with drupal_write_record('chado_stock', $node, 'vid')

laceysanderson’s picture

Changing the function definition for hook_form to chado_stock_form($node, $form_state) fixed it.
Thanks!

I've already switch #3 -> didn't even know I could do that

As for #2, I didn't think that was necessary but when I couldn't get the edit fields to load I wondered inf there wasn't a problem in node_load. I tried to check the contents of node in the form but it wasn't printing for some reason so I added that to make sure. I'll take it out too.

For completeness, #2 and #3 change the code as follows:

/**
* Implements hook_load()
*/
function chado_stock_load($node) {
  //get custom fields
  $result = db_query(
    "SELECT c.unique_name, c.type_name, c.organism_name, c.crossblock_name FROM {chado_stock} c WHERE vid=%d",
    $node->vid
  );
  $custom_fields = db_fetch_array($result);

  //add custom fields to node
  $node->unique_name = $custom_fields['unique_name'];
  $node->type_name = $custom_fields['type_name'];
  $node->organism_name = $custom_fields['organism_name'];
  $node->crossblock_name = $custom_fields['crossblock_name'];

  return $node;
}

/**
* Implements hook_update()
*/
function chado_stock_update($node) {
  if ($node->revision) {
    chado_stock_insert($node);
  } else {
    drupal_write_record('chado_stock', $node, 'vid');
  }
}

nevets’s picture

You can simplify

  $custom_fields = db_fetch_array($result);

  //add custom fields to node
  $node->unique_name = $custom_fields['unique_name'];
  $node->type_name = $custom_fields['type_name'];
  $node->organism_name = $custom_fields['organism_name'];
  $node->crossblock_name = $custom_fields['crossblock_name'];

  return $node;

to

return db_fetch_object($result);