Sfoglia il codice sorgente

Added ability to add properties to a contact via the node

spficklin 12 anni fa
parent
commit
9aebe34712

+ 572 - 0
tripal_contact/includes/tripal_contact.form.inc

@@ -0,0 +1,572 @@
+<?php
+/**
+ * Implementation of tripal_contact_form().
+ *
+ *
+ *
+ *  @parm &$node
+ *    The node that is created when the database is initialized
+ *
+ *  @parm $form_state
+ *    The state of the form, that has the user entered information that is neccessary for, setting
+ *    up the database tables for the contact
+ *
+ *  @return $form
+ *    The information that was enterd allong with
+ *
+ */
+function chado_contact_form(&$node, $form_state) {
+  tripal_core_ahah_init_form();
+  $form = array();
+
+  $contact = $node->contact;
+  $contact_id = $contact->contact_id;
+    
+  $d_title        = $form_state['values']['title']       ? $form_state['values']['title']       : $contact->name;
+  $d_description  = $form_state['values']['description'] ? $form_state['values']['description'] : $contact->description;
+  $d_type_id      = $form_state['values']['type_id']     ? $form_state['values']['type_id'] : $contact->type_id->cvterm_id;
+  
+  // on AHAH callbacks we want to keep a list of all the properties that have been removed
+  // we'll store this info in a hidden field and retrieve it here
+  $d_removed = $form_state['values']['removed'];
+
+  // get the number of new fields that have been aded via AHAH callbacks
+  $num_new = $form_state['values']['num_new'] ? $form_state['values']['num_new'] : 0;
+
+  // initialze default properties array. This is where we store the property defaults
+  $d_properties = array();
+
+  // get the contact default values.  When this module was first created
+  // the contact description was incorrectly stored in the $node->body field.
+  // It is better to store it in the Chado tables.  However, the 'description'
+  // field of the contact table is only 255 characters.  So, we are going
+  // to follow the same as the contact module and store the description in
+  // the contactprop table and leave the contact.description field blank.
+  // however, for backwards compatibitily, we check to see if the description
+  // is in the $node->body field. If it is we'll use that.  When the node is
+  // edited the text will be moved out of the body and into the contactprop
+  // table where it should belong.
+  if ($node->body) {
+    $description = $node->body;
+  }
+  else {
+    $description = $node->description;
+  }
+  if (!$description) {
+    $contactprop = tripal_contact_get_property($contact->contact_id, 'contact_description');
+    $description = $contactprop->value;
+  }
+
+  // keep track of the contact id if we have.  If we do have one then
+  // this is an update as opposed to an insert.
+  $form['contact_id'] = array(
+    '#type' => 'hidden',
+    '#value' => $contact_id,
+  );;
+  
+  // get the contact type
+  $sql = "
+    SELECT CVTS.cvterm_id, CVTS.name
+    FROM {cvtermpath} CVTP
+      INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id
+      INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id
+      INNER JOIN {cv} CV       ON CVTO.cv_id = CV.cv_id
+    WHERE 
+      CV.name = 'tripal_contact' AND 
+      CVTO.name = 'Contact Type' AND
+      CVTP.pathdistance = 1      
+    ORDER BY CVTS.name ASC 
+  ";
+  $results = chado_query($sql);
+  $contact_types = array();
+  while ($contact_type = db_fetch_object($results)) {
+    $contact_types[$contact_type->cvterm_id] = $contact_type->name;
+    if (strcmp($contact_type->name,"Person") == 0 and !$d_type_id) {
+      $d_type_id = $contact_type->cvterm_id;
+    }
+  }
+  
+  // get the contact properties 
+  $properties_select = array();
+  $properties_select[] = 'Select a Property';
+  $properties_list = array();
+  $sql = "
+    SELECT CVTS.cvterm_id, CVTS.name
+    FROM {cvtermpath} CVTP
+      INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id
+      INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id
+      INNER JOIN {cv} CV       ON CVTO.cv_id = CV.cv_id
+    WHERE 
+      CV.name = 'tripal_contact' AND 
+      NOT CVTO.name = 'Contact Type' 
+    ORDER BY CVTS.name ASC 
+  ";
+  $prop_types = chado_query($sql);
+  while ($prop = db_fetch_object($prop_types)) {
+    $properties_select[$prop->cvterm_id] = $prop->name;
+    $properties_list[$prop->cvterm_id] = $prop;
+  }
+  
+  $form['type_id'] = array(
+    '#type' => 'select',
+    '#title' => t('Contact Type'),
+    '#options' => $contact_types,
+    '#required' => TRUE,
+    '#default_value' => $d_type_id,
+  );
+  
+  $form['title']= array(
+    '#type'          => 'textfield',
+    '#title'         => t('Contact Name'),
+    '#description'   => t('Enter the name of this contact'),
+    '#required'      => TRUE,
+    '#default_value' => $d_title,
+    '#weight'        => 1,
+    '#maxlength'     => 255,
+  );
+
+  $form['description']= array(
+    '#type'          => 'textarea',
+    '#title'         => t('Contact Description'),
+    '#description'   => t('A brief description of the contact'),
+    '#required'      => TRUE,
+    '#default_value' => $d_description,
+    '#weight'        => 5
+  );
+  
+  // add in the properties from the contactprop table
+  $num_properties += chado_contact_node_form_add_contactprop_table_props($form, $form_state, $contact_id, $d_properties, $d_removed);
+
+  // add in any new properties that have been added by the user through an AHAH callback
+  $num_new = chado_contact_node_form_add_new_props($form, $form_state, $d_properties, $d_removed);
+
+  // add an empty row of field to allow for addition of a new property
+  chado_contact_node_form_add_new_empty_props($form, $properties_select);
+  
+
+  return $form;
+
+}
+
+/**
+ *  validates submission of form when adding or updating a contact node
+ *
+ * @ingroup tripal_contact
+ */
+function chado_contact_validate($node, &$form) {
+  $title          = trim($node->title);
+  $contact_id     = trim($node->contact_id);
+  $unittype_id    = trim($node->unittype_id);
+  $description    = trim($node->description);
+  $num_properties = $node->num_properties;
+  $num_new = $node->num_new;
+  
+  $contact = 0;
+  // check to make sure the name on the contact is unique
+  // before we try to insert into chado. If this is an update then we will
+  // have a contact_id, therefore we want to look for another contact with this
+  // name but with a different contact_id. If this is an insert, just look
+  // for a case where the name already exists.
+  if ($node->contact_id) {
+    $sql = "
+      SELECT * FROM {contact} 
+      WHERE name = '%s' AND NOT contact_id = %d
+    ";
+    $contact = db_fetch_object(chado_query($sql, $title, $contact_id));
+  }
+  else {
+    $sql = "SELECT * FROM {contact} WHERE name = '%s'";
+    $contact = db_fetch_object(chado_query($sql, $title));
+  }
+  if ($contact) {
+    form_set_error('title', t('The contact name already exists. Please choose another'));
+  }
+  
+}
+/*
+ *
+ */
+function chado_contact_node_form_add_new_empty_props(&$form, $properties_select) {
+
+  // add one more blank set of property fields
+  $form['properties']['new']["new_id"] = array(
+    '#type'          => 'select',
+    '#options'       => $properties_select,
+    '#ahah' => array(
+      'path'    => "tripal_contact/properties/description",
+      'wrapper' => 'tripal-contact-new_value-desc',
+      'event'   => 'change',
+      'method'  => 'replace',          
+  ),
+  );
+  $form['properties']['new']["new_value"] = array(
+    '#type'          => 'textarea',
+    '#default_value' => '',
+    '#cols'          => 5,
+    '#rows'          => $rows,
+    '#description'   => '<div id="tripal-contact-new_value-desc"></div>'
+    );
+    $form['properties']['new']["add"] = array(
+    '#type'         => 'image_button',      
+    '#value'        => t('Add'),
+    '#src'          => drupal_get_path('theme', 'tripal') . '/images/add.png',
+    '#ahah' => array(
+      'path'    => "tripal_contact/properties/add",
+      'wrapper' => 'tripal-contact-edit-properties-table',
+      'event'   => 'click',
+      'method'  => 'replace',          
+    ),
+    '#attributes' => array('onClick' => 'return false;'),
+    );
+}
+/*
+ *
+ */
+function chado_contact_node_form_add_new_props(&$form, $form_state, &$d_properties, &$d_removed) {
+   
+  // first, add in all of the new properties that were added through a previous AHAH callback
+  $j = 0;
+  $num_properties++;
+
+  // we need to find the
+  if ($form_state['values']) {
+    foreach ($form_state['values'] as $element_name => $value) {
+      if (preg_match('/new_value-(\d+)-(\d+)/', $element_name, $matches)) {
+        $new_id = $matches[1];
+        $rank = $matches[2];
+
+        // skip any properties that the user requested to delete through a previous
+        // AHAH callback or through the current AHAH callback
+        if($d_removed["$new_id-$rank"]) {
+          continue;
+        }
+        if($form_state['post']['remove-' . $new_id . '-' . $rank]) {
+          $d_removed["$new_id-$rank"] = 1;
+          continue;
+        }
+
+        // get this new_id information
+        $cvterm = tripal_core_chado_select('cvterm', array('name', 'definition'), array('cvterm_id' => $new_id));
+
+        // add it to the $d_properties array
+        $d_properties[$new_id][$rank]['name']  = $cvterm->name;
+        $d_properties[$new_id][$rank]['id']    = $new_id;
+        $d_properties[$new_id][$rank]['value'] = $value;
+        $d_properties[$new_id][$rank]['definition']  = $cvterm->definition;
+        $num_properties++;
+
+        // determine how many rows we need in the textarea
+        $rows = 1;
+        if (preg_match('/Abstract/', $cvterm[0]->name)) {
+          $rows = 10;
+        }
+        if ($cvterm[0]->name == 'Authors') {
+          $rows = 2;
+        }
+
+        // add the new fields
+        $form['properties']['new'][$new_id][$rank]["new_id-$new_id-$rank"] = array(
+          '#type'          => 'item',
+          '#value'         => $cvterm[0]->name
+        );
+        $form['properties']['new'][$new_id][$rank]["new_value-$new_id-$rank"] = array(
+          '#type'          => 'textarea',
+          '#default_value' => $value,
+          '#cols'          => 50,
+          '#rows'          => $rows,
+          '#description'   => $cvterm->definition,
+        );
+
+        $form['properties']['new'][$new_id][$rank]["remove-$new_id-$rank"] = array(
+          '#type'         => 'image_button',
+          '#value'        => t('Remove'),
+          '#src'          => drupal_get_path('theme', 'tripal') . '/images/minus.png',
+          '#ahah' => array(
+            'path'    => "tripal_contact/properties/minus/$new_id/$rank",
+            'wrapper' => 'tripal-contact-edit-properties-table',
+            'event'   => 'click',
+            'method'  => 'replace',
+        ),
+          '#attributes' => array('onClick' => 'return false;'),
+        );
+      }
+    }
+  }
+
+
+  // second add in any new properties added during this callback
+  if($form_state['post']['add']) {
+    $new_id = $form_state['values']['new_id'];
+    $new_value = $form_state['values']['new_value'];
+
+    // get the rank by counting the number of entries
+    $rank = count($d_properties[$new_id]);
+
+    // get this new_id information
+    $cvterm = tripal_core_chado_select('cvterm', array('name', 'definition'), array('cvterm_id' => $new_id));
+
+    // add it to the $d_properties array
+    $d_properties[$new_id][$rank]['name']  = $cvterm->name;
+    $d_properties[$new_id][$rank]['id']    = $new_id;
+    $d_properties[$new_id][$rank]['value'] = $value;
+    $d_properties[$new_id][$rank]['definition']  = $cvterm->definition;
+    $num_properties++;
+
+    // determine how many rows we need in the textarea
+    $rows = 1;
+    if (preg_match('/Abstract/', $cvterm[0]->name)) {
+      $rows = 10;
+    }
+    if ($cvterm[0]->name == 'Authors') {
+      $rows = 2;
+    }
+
+    // add the new fields
+    $form['properties']['new'][$new_id][$rank]["new_id-$new_id-$rank"] = array(
+      '#type'          => 'item',
+      '#value'         => $cvterm[0]->name
+    );
+    $form['properties']['new'][$new_id][$rank]["new_value-$new_id-$rank"] = array(
+      '#type'          => 'textarea',
+      '#default_value' => $new_value,
+      '#cols'          => 50,
+      '#rows'          => $rows,
+      '#description'   => $cvterm->definition,
+    );
+
+    $form['properties']['new'][$new_id][$rank]["remove-$new_id-$rank"] = array(
+      '#type'         => 'image_button',
+      '#value'        => t('Remove'),
+      '#src'          => drupal_get_path('theme', 'tripal') . '/images/minus.png',
+      '#ahah' => array(
+        'path'    => "tripal_contact/properties/minus/$new_id/$rank",
+        'wrapper' => 'tripal-contact-edit-properties-table',
+        'event'   => 'click',
+        'method'  => 'replace',
+    ),
+      '#attributes' => array('onClick' => 'return false;'),
+    );
+
+  }
+
+  return $num_properties;
+}
+/*
+ *
+ */
+function chado_contact_node_form_add_contactprop_table_props(&$form, $form_state, $contact_id, &$d_properties, &$d_removed) {
+
+  // get the properties for this contact
+  $num_properties = 0;
+
+  if(!$contact_id) {
+    return $num_properties;
+  }
+
+  $sql = "
+    SELECT CVT.cvterm_id, CVT.name, CVT.definition, PP.value, PP.rank
+    FROM {contactprop} PP
+      INNER JOIN {cvterm} CVT on CVT.cvterm_id = PP.type_id
+    WHERE PP.contact_id = %d
+    ORDER BY CVT.name, PP.rank
+  ";
+  $contact_props = chado_query($sql, $contact_id);
+  while ($prop = db_fetch_object($contact_props)) {
+
+    $type_id = $prop->cvterm_id;
+    $rank = count($d_properties[$type_id]);
+    
+    // skip the description as we have a separate form element for that
+    if($prop->name == "contact_description") {
+      continue;
+    }
+
+    // skip any properties that the user requested to delete through a previous
+    // AHAH callback or through the current AHAH callback
+    if($d_removed["$type_id-$rank"]) {
+      continue;
+    }
+    if($form_state['post']['remove-' . $type_id . '-' . $rank]) {
+      $d_removed["$type_id-$rank"] = 1;
+      continue;
+    }
+
+    $d_properties[$type_id][$rank]['name']  = $prop->name;
+    $d_properties[$type_id][$rank]['id']    = $type_id;
+    $d_properties[$type_id][$rank]['value'] = $prop->value;
+    $d_properties[$type_id][$rank]['definition']  = $prop->definition;
+    $num_properties++;
+
+    $form['properties'][$type_id][$rank]["prop_id-$type_id-$rank"] = array(
+      '#type'          => 'item',
+      '#value'         => $prop->name,
+    );
+    $form['properties'][$type_id][$rank]["prop_value-$type_id-$rank"] = array(
+      '#type'          => 'textarea',
+      '#default_value' => $prop->value,
+      '#cols'          => 50,
+      '#rows'          => $rows,
+      '#description'   => $prop->definition,
+    );
+
+    $form['properties'][$type_id][$rank]["remove-$type_id-$rank"] = array(
+      '#type'         => 'image_button',
+      '#value'        => t('Remove'),
+      '#src'          => drupal_get_path('theme', 'tripal') . '/images/minus.png',
+      '#ahah' => array(
+        'path'    => "tripal_contact/properties/minus/$type_id/$rank",
+        'wrapper' => 'tripal-contact-edit-properties-table',
+        'event'   => 'click',
+        'method'  => 'replace',
+    ),
+      '#attributes' => array('onClick' => 'return false;'),
+    );
+  }
+  return $num_properties;
+}
+/*
+ *
+ */
+function tripal_contact_theme_node_form_properties($form) {
+  $rows = array();
+
+  if ($form['properties']) {
+
+    // first add in the properties derived from the contactprop table
+    // the array tree for these properties looks like this:
+    // $form['properties'][$type_id][$rank]["prop_id-$type_id-$rank"]
+    foreach ($form['properties'] as $type_id => $elements) {
+      // there are other fields in the properties array so we only
+      // want the numeric ones those are our type_id
+      if (is_numeric($type_id)) {
+        foreach ($elements as $rank => $element) {
+          if (is_numeric($rank)) {
+            $rows[] = array(
+            drupal_render($element["prop_id-$type_id-$rank"]),
+            drupal_render($element["prop_value-$type_id-$rank"]),
+            drupal_render($element["remove-$type_id-$rank"]),
+            );
+          }
+        }
+      }
+    }
+
+    // second, add in any new properties added by the user through AHAH callbacks
+    // the array tree for these properties looks like this:
+    // $form['properties']['new'][$type_id][$rank]["new_id-$new_id-$rank"]
+    foreach ($form['properties']['new'] as $type_id => $elements) {
+      if (is_numeric($type_id)) {
+        foreach ($elements as $rank => $element) {
+          if (is_numeric($rank)) {
+            $rows[] = array(
+            drupal_render($element["new_id-$type_id-$rank"]),
+            drupal_render($element["new_value-$type_id-$rank"]),
+            drupal_render($element["remove-$type_id-$rank"]),
+            );
+          }
+        }
+      }
+    }
+
+    // finally add in a set of blank field for adding a new property
+    $rows[] = array(
+    drupal_render($form['properties']['new']['new_id']),
+    drupal_render($form['properties']['new']['new_value']),
+    drupal_render($form['properties']['new']['add']),
+    );
+  }
+
+  $headers = array('Property Type','Value', '');
+  return theme('table', $headers, $rows, array('id'=> "tripal-contact-edit-properties-table"));
+}
+
+/*
+ *
+ */
+function tripal_contact_property_add() {
+  $status = TRUE;
+
+  // prepare and render the form
+  $form = tripal_core_ahah_prepare_form();
+
+  // we only want to return the properties as that's all we'll replace with this AHAh callback
+  $data = tripal_contact_theme_node_form_properties($form);
+
+  // bind javascript events to the new objects that will be returned
+  // so that AHAH enabled elements will work.
+  $settings = tripal_core_ahah_bind_events();
+
+  // return the updated JSON
+  drupal_json(
+  array(
+      'status'   => $status, 
+      'data'     => $data,
+      'settings' => $settings,
+  )
+  );
+}
+/*
+ *
+ */
+function tripal_contact_property_delete() {
+  $status = TRUE;
+
+  // prepare and render the form
+  $form = tripal_core_ahah_prepare_form();
+
+  // we only want to return the properties as that's all we'll replace with this AHAh callback
+  $data = tripal_contact_theme_node_form_properties($form);
+
+  // bind javascript events to the new objects that will be returned
+  // so that AHAH enabled elements will work.
+  $settings = tripal_core_ahah_bind_events();
+
+  // return the updated JSON
+  drupal_json(
+  array(
+      'status'   => $status, 
+      'data'     => $data,
+      'settings' => $settings,
+  )
+  );
+}
+/*
+ *
+ */
+function tripal_contact_property_get_description() {
+  $new_id = $_POST['new_id'];
+
+  $values = array('cvterm_id' => $new_id);
+  $cvterm = tripal_core_chado_select('cvterm', array('definition'), $values);
+
+  $description = '&nbsp;';
+  if ($cvterm[0]->definition) {
+    $description = $cvterm[0]->definition;
+  }
+  drupal_json(
+    array(
+      'status' => TRUE,
+      'data'   => '<div id="tripal-contact-new_value-desc">' . $description . '</div>',
+    )
+  );
+}
+/*
+ *
+ */
+function theme_chado_contact_node_form($form) {
+
+  $properties_table = tripal_contact_theme_node_form_properties($form);
+
+  $markup  = drupal_render($form['contact_id']);
+  $markup .= drupal_render($form['title']);
+  $markup .= drupal_render($form['type_id']);
+  $markup .= drupal_render($form['description']);
+  $markup .= "<b>Include Additional Details</b><br>You may add additional properties to this contact by scrolling to the bottom of this table, selecting a property type from the dropdown and adding text.  You may add as many properties as desired by clicking the plus button on the right.  To remove a property, click the minus button";
+  $markup .= $properties_table;
+
+  $form['properties'] = array(
+    '#type' => 'markup',
+    '#value' =>  $markup,
+  );
+  return drupal_render($form);
+}

+ 185 - 123
tripal_contact/tripal_contact.module

@@ -12,6 +12,7 @@
 require('api/tripal_contact.api.inc');
 require('includes/contact_sync.inc');
 require('includes/tripal_contact.admin.inc');
+require('includes/tripal_contact.form.inc');
 
 /**
  * @defgroup tripal_contact Contact Module
@@ -46,7 +47,7 @@ function tripal_contact_views_api() {
  * @ingroup tripal_contact
  */
 function tripal_contact_init() {
-
+  drupal_add_css(drupal_get_path('theme', 'tripal') . '/css/tripal_contact.css');  
 }
 
 /**
@@ -102,6 +103,24 @@ function tripal_contact_menu() {
     'type' => MENU_NORMAL_ITEM,
   );
   
+    // AJAX calls for adding/removing properties to a contact
+  $items['tripal_contact/properties/add'] = array(
+    'page callback' => 'tripal_contact_property_add',
+    'access arguments' => array('edit chado_contact content'),
+    'type ' => MENU_CALLBACK,
+  );
+  $items['tripal_contact/properties/description'] = array(
+    'page callback' => 'tripal_contact_property_get_description',
+    'access arguments' => array('edit chado_contact content'),
+    'type ' => MENU_CALLBACK,
+  );
+  $items['tripal_contact/properties/minus/%/%'] = array(
+    'page callback' => 'tripal_contact_property_delete',
+    'page arguments' => array(3, 4),
+    'access arguments' => array('edit chado_contact content'),
+    'type ' => MENU_CALLBACK,
+  );
+  
   return $items;
 }
   
@@ -130,6 +149,11 @@ function tripal_contact_theme() {
       'arguments' =>  array(NULL),  
       'path' => drupal_get_path('module', 'tripal_contact') . '/theme' 
     ),
+    
+    // Themed Forms
+    'chado_contact_node_form' => array(
+      'arguments' => array('form'),
+    ),
   );
 }
 
@@ -190,103 +214,6 @@ function chado_contact_access($op, $node, $account ) {
   return NULL;
 }
 
-/**
- * Implementation of tripal_contact_form().
- *
- *
- *
- *  @parm &$node
- *    The node that is created when the database is initialized
- *
- *  @parm $form_state
- *    The state of the form, that has the user entered information that is neccessary for, setting
- *    up the database tables for the contact
- *
- *  @return $form
- *    The information that was enterd allong with
- *
- */
-function chado_contact_form(&$node, $form_state) {
-
-  $form = array();
-
-  $contact = $node->contact;
-
-  // get the contact default values.  When this module was first created
-  // the contact description was incorrectly stored in the $node->body field.
-  // It is better to store it in the Chado tables.  However, the 'description'
-  // field of the contact table is only 255 characters.  So, we are going
-  // to follow the same as the contact module and store the description in
-  // the contactprop table and leave the contact.description field blank.
-  // however, for backwards compatibitily, we check to see if the description
-  // is in the $node->body field. If it is we'll use that.  When the node is
-  // edited the text will be moved out of the body and into the contactprop
-  // table where it should belong.
-  if ($node->body) {
-    $contact_description = $node->body;
-  }
-  else {
-    $contact_description = $node->contact_description;
-  }
-  if (!$contact_description) {
-    $contactprop = tripal_contact_get_property($contact->contact_id, 'contact_description');
-    $contact_description = $contactprop->value;
-  }
-
-  $form['contact_id'] = array(
-    '#type' => 'hidden',
-    '#value' => (isset($node->contact_id)) ? $node->contact_id->contact_id : NULL ,
-  );
-  
-  $sql = "
-    SELECT CVTS.cvterm_id, CVTS.name
-    FROM {cvtermpath} CVTP
-      INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id
-      INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id
-      INNER JOIN {cv} CV       ON CVTO.cv_id = CV.cv_id
-    WHERE 
-      CV.name = 'tripal_contact' AND 
-      CVTO.name = 'Contact Type' AND
-      CVTP.pathdistance = 1      
-    ORDER BY CVTS.name ASC 
-  ";
-  $results = chado_query($sql);
-  $contact_types = array();
-  $default_type = '';
-  while ($contact_type = db_fetch_object($results)) {
-    $contact_types[$contact_type->cvterm_id] = $contact_type->name;
-    if (strcmp($contact_type->name,"Person") == 0) {
-      $default_type = $contact_type->cvterm_id;
-    }
-  }
-  $form['type_id'] = array(
-    '#type' => 'select',
-    '#title' => t('Contact Type'),
-    '#options' => $contact_types,
-    '#required' => TRUE,
-    '#default_value' => isset($contact->contact_id->type_id) ? $contact->contact_id->type_id : $default_type,
-  );
-  
-  $form['title']= array(
-    '#type'          => 'textfield',
-    '#title'         => t('Contact Name'),
-    '#description'   => t('Enter the name of this contact'),
-    '#required'      => TRUE,
-    '#default_value' => $contact->name,
-    '#weight'        => 1
-  );
-
-  $form['contact_description']= array(
-    '#type'          => 'textarea',
-    '#title'         => t('Contact Description'),
-    '#description'   => t('A brief description of the contact'),
-    '#required'      => TRUE,
-    '#default_value' => $contact_description,
-    '#weight'        => 5
-  );
-  return $form;
-
-}
 
 
 /**
@@ -308,38 +235,80 @@ function chado_contact_insert($node) {
     $contact['contact_id'] = $node->contact_id;
   }
   else {
-    // check to see if this contact name already exists.    
-    $values =  array('name' => $node->contact_name);
-    $options = array('statement_name' => 'sel_contact_na');
-    $contact = tripal_core_chado_select('contact', array('contact_id'), $values, $options);
-    if (count($contact) > 0) {
-      drupal_set_message(t('A contact with this name already exists.', 'error'));
-      watchdog('tripal_contact','Insert Contact: A contact with this name already exists. %name',
-        array('%name' => $node->contact_name), WATCHDOG_ERROR);
-      return FALSE;  
+    // we don't want to store the description in the description field as it may be longer than
+    // 255 characters, so we'll use a property to store this value.
+    $values =  array(
+      'name' => $node->title,
+      'description' => '',
+      'type_id' => $node->type_id
+    );
+    $options = array('statement_name' => 'ins_contact_nadety');
+    $contact = tripal_core_chado_insert('contact', $values, $options);
+    if (!$contact) {
+      drupal_set_message(t('Could not add the contact'), 'error');
+      watchdog('tripal_contact','Could not add the contact', array(), WATCHDOG_ERROR);
+      return FALSE; 
     }
-    else {
-      $values =  array(
-        'name' => $node->title,
-        'description' => '',
-        'type_id' => $node->type_id
-      );
-      $options = array('statement_name' => 'ins_contact_nadety');
-      $contact = tripal_core_chado_insert('contact', $values, $options);
-      if (!$contact) {
-        drupal_set_message(t('Could not add the contact'), 'error');
-        watchdog('tripal_contact','Could not add the contact',
-          array(), WATCHDOG_ERROR);
-        return FALSE; 
+    
+    // now add the properties
+    $properties = array(); // stores all of the properties we need to add
+  
+    // get the list of properties for easy lookup (without doing lots of database queries
+    $properties_list = array();
+    $sql = "
+      SELECT CVTS.cvterm_id, CVTS.name
+      FROM {cvtermpath} CVTP
+        INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id
+        INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id
+        INNER JOIN {cv} CV       ON CVTO.cv_id = CV.cv_id
+      WHERE 
+        CV.name = 'tripal_contact' AND 
+        NOT CVTO.name = 'Contact Type' 
+      ORDER BY CVTS.name ASC 
+    ";
+    $prop_types = chado_query($sql);
+    while ($prop = db_fetch_object($prop_types)) {
+      $properties_list[$prop->cvterm_id] = $prop->name;
+    }   
+  
+    // get the properties that should be added. Properties are in one of two forms:
+    //  1) prop_value-[type id]-[index]
+    //  2) new_value-[type id]-[index]
+    //  3) new_id, new_value
+    foreach ($node as $name => $value) {
+      if (preg_match('/^new_value-(\d+)-(\d+)/', $name, $matches)) {
+        $type_id = $matches[1];
+        $index = $matches[2];
+        $name = $properties_list[$type_id];
+        $properties[$name][$index] = trim($value);
       }
     }
+    if ($node->new_id and $node->new_value) {
+      $type_id = $node->new_id;
+      $index = count($properties[$name]);
+      $name = $properties_list[$type_id];
+      $properties[$name][$index] = trim($node->new_value);
+    } 
+    // now add in the properties
+    foreach ($properties as $property => $elements) {
+      foreach ($elements as $rank => $value) {
+         
+        $status = tripal_contact_insert_property($contact['contact_id'], $property, $value, FALSE);
+        if (!$status) {
+          drupal_set_message("Error cannot add property: $property", "error");
+          watchdog('t_contact', "Error cannot add property: %prop",
+          array('%property' => $property), WATCHDOG_ERROR);
+        }
+      }
+    } 
   }
 
+  // add the record to the chado_contact table in Drupal
   if ($contact) {   
    
     // add the description property
     tripal_contact_insert_property($contact['contact_id'], 'contact_description',
-      $node->contact_description, TRUE);
+      $node->description, TRUE);
     
     // make sure the entry for this contact doesn't already exist in the chado_contact table
     // if it doesn't exist then we want to add it.
@@ -398,7 +367,74 @@ function chado_contact_update($node) {
     'type_id' => $node->type_id
   );
   $status = tripal_core_chado_update('contact', $match, $values);
-  tripal_contact_update_property($contact_id, 'contact_description', $node->contact_description, 1);
+  if (!$status) {
+    drupal_set_message("Error updating contact", "error");
+    watchdog('t_contact', "Error updating contact", array(), WATCHDOG_ERROR);
+    return;
+  }
+  
+  // now update the properties
+  $properties = array(); // stores all of the properties we need to add
+   
+  // get the list of properties for easy lookup (without doing lots of database queries
+  $properties_list = array();
+  $sql = "
+    SELECT CVTS.cvterm_id, CVTS.name
+    FROM {cvtermpath} CVTP
+      INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id
+      INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id
+      INNER JOIN {cv} CV       ON CVTO.cv_id = CV.cv_id
+    WHERE 
+      CV.name = 'tripal_contact' AND 
+      NOT CVTO.name = 'Contact Type' 
+    ORDER BY CVTS.name ASC 
+  ";
+  $prop_types = chado_query($sql);
+  while ($prop = db_fetch_object($prop_types)) {
+    $properties_list[$prop->cvterm_id] = $prop->name;
+  }
+  
+  // get the properties that should be added. Properties are in one of three forms:
+  //  1) prop_value-[type id]-[index]
+  //  2) new_value-[type id]-[index]
+  //  3) new_id, new_value
+  //  dpm($node);
+  foreach ($node as $key => $value) {
+    if (preg_match('/^prop_value-(\d+)-(\d+)/', $key, $matches)) {
+      $type_id = $matches[1];
+      $index = $matches[2];
+      $name = $properties_list[$type_id];
+      $properties[$name][$index] = trim($value);
+    }
+    if (preg_match('/^new_value-(\d+)-(\d+)/', $key, $matches)) {
+      $type_id = $matches[1];
+      $index = $matches[2];
+      $name = $properties_list[$type_id];
+      $properties[$name][$index] = trim($value);
+    }
+  }
+  if ($node->new_id and $node->new_value) {
+    $type_id = $node->new_id;
+    $name = $properties_list[$type_id];
+    $index = count($properties[$name]);
+    $properties[$name][$index] = trim($node->new_value);
+  }
+  
+  // now add in the properties by first removing any the contact
+  // already has and adding the ones we have
+  tripal_core_chado_delete('contactprop', array('contact_id' => $contact_id));
+  foreach ($properties as $property => $elements) {
+    foreach ($elements as $rank => $value) {
+      $status = tripal_contact_insert_property($contact_id, $property, $value, FALSE);
+      if (!$status) {
+        drupal_set_message("Error cannot add property: '$property'", "error");
+        watchdog('t_contact', "Error cannot add property: '%prop'",
+        array('%prop' => $property), WATCHDOG_ERROR);
+      }
+    }
+  } 
+  
+  tripal_contact_update_property($contact_id, 'contact_description', $node->description, 1);
 }
 
 
@@ -418,7 +454,25 @@ function chado_contact_load($node) {
   $contact_id = chado_get_id_for_node('contact', $node);
 
   $values = array('contact_id' => $contact_id);
-  $contact = tripal_core_generate_chado_var('contact', $values); 
+  $contact = tripal_core_generate_chado_var('contact', $values);
+
+  // get the contact description and replace the contact.description field with this one
+  $values = array(
+    'contact_id' => $contact->contact_id, 
+    'type_id' => array(
+      'name' => 'contact_description',
+    ),
+  );
+  $options = array(
+    'return_array' => 1,
+    'include_fk' => array('type_id' => 1),
+  );
+  $description = tripal_core_generate_chado_var('contactprop', $values, $options);    
+  if (count($description) == 1) {
+    $description = tripal_core_expand_chado_vars($description, 'field', 'contactprop.value');  
+    $contact->description = $description[0]->value;
+  }
+    
 
   $additions = new stdClass();
   $additions->contact = $contact;
@@ -537,3 +591,11 @@ function tripal_contact_preprocess_tripal_contact_relationships(&$variables) {
 
   $contact->all_relationships = $relationships;
 }
+
+/*
+ * 
+ */
+function tripal_contact_form_alter(&$form, &$form_state, $form_id) {
+  if ($form_id == "chado_contact_node_form") {
+  }
+}

+ 2 - 2
tripal_featuremap/tripal_featuremap.install

@@ -130,9 +130,9 @@ function tripal_featuremap_add_cvterms() {
    tripal_cv_add_cvterm(array('name' => 'undefined','def' => 'A catch-all for an undefined unit type'), 
      'featuremap_units', 0, 1, 'tripal');
    
-    tripal_cv_add_cvterm(array('name' => 'start','def' => 'The start coordinate for a map feature.'), 
+   tripal_cv_add_cvterm(array('name' => 'start','def' => 'The start coordinate for a map feature.'), 
      'featurepos_property', 0, 1, 'tripal');
-    tripal_cv_add_cvterm(array('name' => 'stop','def' => 'The end coordinate for a map feature'), 
+   tripal_cv_add_cvterm(array('name' => 'stop','def' => 'The end coordinate for a map feature'), 
      'featurepos_property', 0, 1, 'tripal');
    
    // add cvterms for map properties