Browse Source

Can now update a publication and it's properties manually

spficklin 12 years ago
parent
commit
0f48bf25d5

+ 0 - 1
tripal_core/api/tripal_core_ahah.api.inc

@@ -84,7 +84,6 @@ function tripal_core_ahah_prepare_form() {
   // The new form gets cached and processed again, but because $_POST is
   // destroyed, the submit handlers will not be called again.
   $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
-  
 
   return $form;
 }

+ 9 - 0
tripal_core/tripal_core.module

@@ -109,6 +109,15 @@ function tripal_core_init() {
   
   // create a persistent connection
   $connection = tripal_db_persistent_chado();
+  
+  // If we want AHAH elements on the node forms (e.g. chado_pub form) then we need to include
+  // the node.pages file. Otherwise this error message is given:
+  //
+  // warning: call_user_func_array() expects parameter 1 to be a valid callback, 
+  // function 'node_form' not found or invalid function name 
+  // in /var/www/includes/form.inc on line 382.
+  module_load_include('inc', 'node', 'node.pages');    
+  
 }
 
 /**

+ 89 - 8
tripal_pub/api/tripal_pub.api.inc

@@ -247,7 +247,7 @@ function tripal_pub_add_publications($pubs, $do_contact) {
     }                                      
   
     $num_pubs++;
-    print $num_pubs . ".  " . $pub['Publication Database'] . ' ' . $pub['Pub Accession'] . "\n";                          
+    print $num_pubs . ".  " . $pub['Publication Database'] . ' ' . $pub['Publication Accession'] . "\n";                          
   } // end for loop        
 }
 /*
@@ -258,7 +258,7 @@ function tripal_pub_add_pub_dbxref($pub_id, $pub) {
   // check to see if the pub_dbxref record already exist
   $values = array(
     'dbxref_id' => array(
-      'accession' => $pub['Pub Accession'],
+      'accession' => $pub['Publication Accession'],
       'db_id' => array(
         'name' => $pub['Publication Database'],
       ),
@@ -278,14 +278,14 @@ function tripal_pub_add_pub_dbxref($pub_id, $pub) {
    
   // get the database cross-reference
   $dbxvalues = array(
-    'accession' => $pub['Pub Accession'],
+    'accession' => $pub['Publication Accession'],
     'db_id' => $db->db_id,
   );
   $dbxoptions = array('statement_name' => 'sel_dbxref_acdb');
   $results = tripal_core_chado_select('dbxref', array('dbxref_id'), $dbxvalues, $dbxoptions);
   // if the accession doesn't exist then add it
   if(count($results) == 0){
-    $dbxref = tripal_db_add_dbxref($db->db_id, $pub['Pub Accession']);          
+    $dbxref = tripal_db_add_dbxref($db->db_id, $pub['Publication Accession']);          
   }
   else {
     $dbxref = $results[0];
@@ -296,7 +296,7 @@ function tripal_pub_add_pub_dbxref($pub_id, $pub) {
   $results = tripal_core_chado_insert('pub_dbxref', $values, $options);
   if (!$results) {
     watchdog('tripal_pub', "Cannot add publication dbxref: %db:%accession.",
-      array('%db' => $pub['Publication Database'], '%accession' => $pub['Pub Accession']). WATCHDOG_ERROR);
+      array('%db' => $pub['Publication Database'], '%accession' => $pub['Publication Accession']). WATCHDOG_ERROR);
     return FALSE;
   }
   return $results;
@@ -310,10 +310,10 @@ function tripal_pub_add_publication($pub_details, $do_contact) {
 
   // first try to find the publication using the accession number. It will ahve
   // one if the pub has already been loaded for the publication database
-  if ($pub_details['Pub Accession'] and $pub_details['Publication Database']) {
+  if ($pub_details['Publication Accession'] and $pub_details['Publication Database']) {
     $values = array(
       'dbxref_id' => array (
-        'accession' => $pub_details['Pub Accession'],
+        'accession' => $pub_details['Publication Accession'],
         'db_id' => array(
           'name' => $pub_details['Publication Database']
         ),
@@ -326,7 +326,7 @@ function tripal_pub_add_publication($pub_details, $do_contact) {
     }
     elseif(count($results) > 1) {
       watchdog('tripal_pub', "There are two publications with this accession: %db:%accession. Cannot determine which to update.", 
-        array('%db' => $pub_details['Publication Database'], '%accession' => $pub_details['Pub Accession']), WATCHDOG_ERROR);     
+        array('%db' => $pub_details['Publication Database'], '%accession' => $pub_details['Publication Accession']), WATCHDOG_ERROR);     
       return FALSE;    
     }
   }   
@@ -507,3 +507,84 @@ function tripal_pub_add_authors($pub_id, $authors, $do_contact) {
     $rank++;   
   }
 }
+
+/**
+ * Retrieve properties of a given type for a given pub
+ *
+ * @param $pub_id
+ *    The pub_id of the properties you would like to retrieve
+ * @param $property
+ *    The cvterm name of the properties to retrieve
+ *
+ * @return
+ *    An pub chado variable with the specified properties expanded
+ *
+ * @ingroup tripal_pub_api
+ */
+function tripal_pub_get_property($pub_id, $property) {
+  return tripal_core_get_property('pub', $pub_id, $property, 'tripal');
+}
+
+/**
+ * Insert a given property
+ *
+ * @param $pub_id
+ *   The pub_id of the property to insert
+ * @param $property
+ *   The cvterm name of the property to insert
+ * @param $value
+ *   The value of the property to insert
+ * @param $update_if_present
+ *   A boolean indicated whether to update the record if it's already present
+ *
+ * @return
+ *   True of success, False otherwise
+ *
+ * @ingroup tripal_pub_api
+ */
+function tripal_pub_insert_property($pub_id, $property, $value, $update_if_present = 0) {
+  return tripal_core_insert_property('pub', $pub_id, $property, 'tripal_pub', $value, $update_if_present);
+}
+
+/**
+ * Update a given property
+ *
+ * @param $pub_id
+ *   The pub_id of the property to update
+ * @param $property
+ *   The cvterm name of the property to update
+ * @param $value
+ *   The value of the property to update
+ * @param $insert_if_missing
+ *   A boolean indicated whether to insert the record if it's absent
+ *
+ * Note: The property will be identified using the unique combination of the $pub_id and $property
+ * and then it will be updated with the supplied value
+ *
+ * @return
+ *   True of success, False otherwise
+ *
+ * @ingroup tripal_pub_api
+ */
+function tripal_pub_update_property($pub_id, $property, $value, $insert_if_missing = 0) {
+  return tripal_core_update_property('pub', $pub_id, $property, 'tripal_pub', $value, $insert_if_missing);
+}
+/**
+ * Delete a given property
+ *
+ * @param $pub_id
+ *   The pub_id of the property to delete
+ * @param $property
+ *   The cvterm name of the property to delete
+ *
+ * Note: The property will be identified using the unique combination of the $pub_id and $property
+ * and then it will be deleted
+ *
+ * @return
+ *   True of success, False otherwise
+ *
+ * @ingroup tripal_pub_api
+ */
+function tripal_pub_delete_property($pub_id, $property) {
+  return tripal_core_delete_property('pub', $pub_id, $property, 'tripal');
+}

+ 1 - 0
tripal_pub/includes/agricoloa.inc

@@ -1 +1,2 @@
 <?php
+// http://agricola.nal.usda.gov/help/z3950.html

+ 453 - 224
tripal_pub/includes/pub_form.inc

@@ -4,17 +4,15 @@
  * This is the chado_pub node form callback. The arguments
  * are out of order from a typical form because it's a defined callback 
  */
-function chado_pub_node_form($form_state, $node) {   
+
+function chado_pub_form($node, $form_state) { 
   tripal_core_ahah_init_form();
   $form = array();
-  dpm($form_state);
-
-  $type = node_get_types('type', $node);
-  $pub = $node->pub;
   
+  $pub = $node->pub;  
   $pub_id = $pub->pub_id;
   
-  $d_title        = $form_state['values']['title']        ? $form_state['values']['title']       : $pub->title;
+  $d_title        = $form_state['values']['title']        ? $form_state['values']['title']       : $node->title;
   $d_uniquename   = $form_state['values']['uniquename']   ? $form_state['values']['uniquename']  : $pub->uniquename;
   $d_type_id      = $form_state['values']['type_id']      ? $form_state['values']['type_id']     : $pub->type_id->cvterm_id;
   $d_volume       = $form_state['values']['volume']       ? $form_state['values']['volume']      : $pub->volume;
@@ -27,6 +25,11 @@ function chado_pub_node_form($form_state, $node) {
   $d_publisher    = $form_state['values']['publisher']    ? $form_state['values']['publisher']   : $pub->publisher;
   $d_pubplace     = $form_state['values']['pubplace']     ? $form_state['values']['pubplace']    : $pub->pubplace;
   $d_is_obsolete  = $form_state['values']['is_obsolete']  ? $form_state['values']['is_obsolete'] : $pub->is_obsolete;
+  
+  // if the obsolete value is set by the database then it is in the form of
+  // 't' or 'f', we need to convert to 1 or 0
+  $d_is_obsolete = $d_is_obsolete == 't' ? 1 : $d_is_obsolete;
+  $d_is_obsolete = $d_is_obsolete == 'f' ? 0 : $d_is_obsolete;
 
   // 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
@@ -34,11 +37,12 @@ function chado_pub_node_form($form_state, $node) {
   
   // get the defaults first from the database and then from the form_state
   $default_type = $pub->type_id->cvterm_id;
+  
+  // 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;
 
-  $form['pub_id'] = array(
-    '#type' => 'hidden',
-    '#value' => $pub_id,
-  );
+  // initialze default properties array. This is where we store the property defaults
+  $d_properties = array();      
   
   // get the list of publication types.  In the Tripal publication
   // ontologies these are all grouped under the term 'Publication Type'
@@ -61,6 +65,43 @@ function chado_pub_node_form($form_state, $node) {
       $d_type_id = $pub_type->cvterm_id;
     }
   }
+  
+  // get publication properties list 
+  $properties_select = array();
+  $properties_select[] = 'Select a Property';
+  $properties_list = array();
+  $sql = "
+    SELECT CVTS.cvterm_id, CVTS.name, CVTS.definition
+    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} ON CVTO.cv_id = CV.cv_id
+    WHERE CV.name = 'tripal_pub' and CVTO.name = 'Publication Details'
+    ORDER BY CVTS.name ASC 
+  ";
+  $prop_types = chado_query($sql); 
+  while ($prop = db_fetch_object($prop_types)) {
+    // the 'Citation' term is special because it serves
+    // both as a property and as the uniquename for the publiation table
+    // it is present by default in the initial fields of the form so
+    // we don't want it again in the drop-down list
+    if ($prop->name != 'Citation') {
+      $properties_select[$prop->cvterm_id] = $prop->name;
+    }
+    $properties_list[$prop->cvterm_id] = $prop;
+  }
+  
+  $form['pub_id'] = array(
+    '#type' => 'hidden',
+    '#value' => $pub_id,
+  );
+  
+  $form['title'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Publication Title'),
+    '#default_value' => $d_title,
+    '#required' => TRUE,
+  );
   $form['type_id'] = array(
     '#type' => 'select',
     '#title' => t('Publication Type'),
@@ -68,15 +109,7 @@ function chado_pub_node_form($form_state, $node) {
     '#required' => TRUE,
     '#default_value' => $d_type_id,
   );
-  
-  // Article Title.
-  $form['title'] = array(
-    '#type' => 'textfield',
-    '#title' => check_plain($type->title_label),
-    '#default_value' => $d_title,
-    '#required' => TRUE,
-  );
-  
+    
   $form['series_name'] = array(
     '#type' => 'textfield',
     '#title' => t('Series Name (e.g. Journal Name)'),
@@ -89,6 +122,7 @@ function chado_pub_node_form($form_state, $node) {
     '#title' => t('Publication Year'),
     '#default_value' => $d_pyear,
     '#required' => TRUE,
+    '#size' => 5,
   );
   
   $form['uniquename'] = array(
@@ -105,121 +139,356 @@ function chado_pub_node_form($form_state, $node) {
     '#required' => TRUE,
   );
   
-  // get publication properties list and create the array that will be used for selecting a property type
+  // add in the properties that are actually stored in the pub table fields.
+  $num_properties = chado_pub_node_form_add_pub_table_props($form, $form_state, $properties_list, 
+    $d_properties, $d_removed, $d_volume, $d_volumetitle, $d_issue, $d_pages);
+  
+  // add in the properties from the pubprop table   
+  $num_properties += chado_pub_node_form_add_pubprop_table_props($form, $form_state, $pub_id, $d_properties, $d_removed);
+    
+  // add in any new properties that have been added by the user through an AHAH callback  
+  $num_properties += chado_pub_node_form_add_new_props($form, $form_state, $num_new, $d_properties, $d_removed);
+  
+  // add an empty row of field to allow for addition of a new property
+  chado_pub_node_form_add_new_empty_props($form, $properties_select);
+  
+  
+  $form['removed'] = array(
+    '#type' => 'hidden',
+    '#value' => $d_removed,
+  );
+
+  $form['num_new'] = array(
+    '#type' => 'hidden',
+    '#value' => $num_new,
+  );
+  
+  $form['is_obsolete'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Is Obsolete? (Check for Yes)'),
+    '#required' => TRUE,
+    '#default_value' => $d_is_obsolete,
+  );
+  return $form;
+
+}
+/*
+ * 
+ */
+function chado_pub_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,
+  );
+  $form['properties']['new']["new_value"] = array(
+    '#type'          => 'textarea',
+    '#default_value' => '',
+    '#cols'          => 5,
+    '#rows'          => $rows
+  );
+  $form['properties']['new']["add"] = array(
+    '#type'         => 'image_button',      
+    '#value'        => t('Add'),
+    '#src'          => drupal_get_path('theme', 'tripal') . '/images/add.png',
+    '#ahah' => array(
+      'path'    => "tripal_pub/properties/add",
+      'wrapper' => 'tripal-pub-edit-properties-table',
+      'event'   => 'click',
+      'method'  => 'replace',          
+    ),   
+    '#attributes' => array('onClick' => 'return false;'),
+  );   
+}
+/*
+ * 
+ */
+function chado_pub_node_form_add_new_props(&$form, $form_state, $num_new, &$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
+  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];
+      
+      // 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;
+      }
+      
+      // adjust the term description if needed
+      $description = $cvterm[0]->definition;
+      if ($cvterm[0]->name == 'Author List') {
+        $description .= ' For PubMed style citations list each author with the last name first, followed by initials. Each author should be separated by a comma.';
+        $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'   => $description,
+      );
+      
+      $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_pub/properties/minus/$new_id/$rank",
+          'wrapper' => 'tripal-pub-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;
+    }
+    
+    // adjust the term description if needed
+    $description = $cvterm[0]->definition;
+    if ($cvterm[0]->name == 'Author List') {
+      $description .= ' For PubMed style citations list each author with the last name first, followed by initials. Each author should be separated by a comma.';
+      $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'   => $description,
+    );
+    
+    $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_pub/properties/minus/$new_id/$rank",
+        'wrapper' => 'tripal-pub-edit-properties-table',
+        'event'   => 'click',
+        'method'  => 'replace',
+      ), 
+      '#attributes' => array('onClick' => 'return false;'),
+    );
+    
+  }
+    
+  return $num_properties;
+}
+/*
+ * 
+ */
+function chado_pub_node_form_add_pubprop_table_props(&$form, $form_state, $pub_id, &$d_properties, &$d_removed) {
+  
+  // get the properties for this publication
+  $num_properties = 0;
+    
+  if(!$pub_id) {
+    return $num_properties; 
+  }
+  
   $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} ON CVTO.cv_id = CV.cv_id
-    WHERE CV.name = 'tripal_pub' and CVTO.name = 'Publication Details'
-    ORDER BY CVTS.name ASC 
+    SELECT CVT.cvterm_id, CVT.name, CVT.definition, PP.value, PP.rank
+    FROM {pubprop} PP
+      INNER JOIN {cvterm} CVT on CVT.cvterm_id = PP.type_id
+    WHERE PP.pub_id = %d
+    ORDER BY CVT.name, PP.rank
   ";
-  $prop_types = chado_query($sql);  
+  $pub_props = chado_query($sql, $pub_id);
+  while ($prop = db_fetch_object($pub_props)) {
+    
+    $type_id = $prop->cvterm_id;
+    $rank = count($d_properties[$type_id]);
+    
+    // skip properties that were handled above
+    if($prop->name == "Volume" or $prop->name == "Volume Title" or 
+       $prop->name == "Issue"  or $prop->name == "Pages" or
+       $prop->name == "Citation") {
+         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 . '-0'] = 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++; 
+  
+    // determine how many rows we need in the textarea
+    $rows = 1;
+    if (preg_match('/Abstract/', $prop->name)) {
+      $rows = 10;
+    }
+  
+    // adjust the term description if needed
+    $description = $prop->definition;
+    if ($prop->name == 'Author List') {
+      $description .= ' For PubMed style citations list each author with the last name first, followed by 
+        initials. Each author should be separated by a comma.';
+      $rows = 2;
+    }
+  
+    $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'   => $description,
+    );
+    
+    $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_pub/properties/minus/$type_id/$rank",
+        'wrapper' => 'tripal-pub-edit-properties-table',
+        'event'   => 'click',
+        'method'  => 'replace',
+      ), 
+      '#attributes' => array('onClick' => 'return false;'),
+    );      
+  }
+  return $num_properties;
+}
+/*
+ * 
+ */
+function chado_pub_node_form_add_pub_table_props(&$form, $form_state, $properties_list,
+    &$d_properties, &$d_removed, $d_volume, $d_volumetitle, $d_issue, $d_pages) {
+      
   $num_properties = 0;
-  $d_properties = array();  
-  $properties = array();  
-  $removed = array();
-  $properties[] = 'Select a Property';
-  while ($prop = db_fetch_object($prop_types)) {
-    $properties[$prop->cvterm_id] = $prop->name;
+  $rank = 0;
+  
+  // add properties that are actually part of the pub table  
+  foreach($properties_list as $type_id => $prop) {     
 
     // skip any properties that the user requested to delete through a previous
     // AHAH callback or through the current AHAH callback
-    if($d_removed[$prop->cvterm_id . '-0']) {
+    if($d_removed["$type_id-$rank"]) {
       continue;
     }
-    if($form_state['post']['remove-' . $prop->cvterm_id . '-0']) {
-      $d_removed[$prop->cvterm_id . '-0'] = 1;
+    if($form_state['post']["remove-$type_id-$rank"]) {
+      $d_removed["$type_id-$rank"] = 1;
       continue;
     }
+        
     // if any of the properties match the fields in the pub table then we want to include those 
     // automatically
-    if($prop->name == 'Volume' and $d_volume) {
-      $d_properties[$prop->cvterm_id][0]['name']  =  $prop->name;     
-      $d_properties[$prop->cvterm_id][0]['id']    = $prop->cvterm_id;
-      $d_properties[$prop->cvterm_id][0]['value'] = $d_volume;
-      $num_properties++;
-    }
-    if($prop->name == 'Volume Title' and $d_volumetitle) {
-      $d_properties[$prop->cvterm_id][0]['name']  =  $prop->name;
-      $d_properties[$prop->cvterm_id][0]['id']    = $prop->cvterm_id;
-      $d_properties[$prop->cvterm_id][0]['value'] = $d_volumetitle;
-      $num_properties++;
-    }
-    if($prop->name == 'Issue' and $d_issue) {
-      $d_properties[$prop->cvterm_id][0]['name']  =  $prop->name;
-      $d_properties[$prop->cvterm_id][0]['id']    = $prop->cvterm_id;
-      $d_properties[$prop->cvterm_id][0]['value'] = $d_issue;
-      $num_properties++;
-    }
-    if($prop->name == 'Pages' and $d_pages) {
-      $d_properties[$prop->cvterm_id][0]['name']  =  $prop->name;
-      $d_properties[$prop->cvterm_id][0]['id']    = $prop->cvterm_id;
-      $d_properties[$prop->cvterm_id][0]['value'] = $d_pages;
+    if (($prop->name == 'Volume' and $d_volume) or         
+        ($prop->name == 'Issue' and $d_issue) or 
+        ($prop->name == 'Pages' and $d_pages) or
+        ($prop->name == 'Volume Title' and $d_volumetitle)) {
+          
+      $d_properties[$type_id][$rank]['name']  = $prop->name;           
+      $d_properties[$type_id][$rank]['id']    = $type_id;            
+      $d_properties[$type_id][$rank]['definition']  = $prop->definition;
       $num_properties++;
-    }
-  }
-  
-  // get the properties for this publication
-  if($pub_id) {
-    $sql = "
-      SELECT CVT.cvterm_id, CVT.name, PP.value, PP.rank
-      FROM {pubprop} PP
-        INNER JOIN {cvterm} CVT on CVT.cvterm_id = PP.type_id
-      WHERE PP.pub_id = %d
-      ORDER BY CVT.name, PP.rank
-    ";
-    $pub_props = chado_query($sql, $pub_id);
-    while ($prop = db_fetch_object($pub_props)) {
-      // skip properties that were handled above
-      if($prop->name == "Volume" or $prop->name == "Volume Title" or 
-         $prop->name == "Issue"  or $prop->name == "Pages" or
-         $prop->name == "Citation") {
-           continue;
+      
+      if ($prop->name == 'Volume') {
+        $d_properties[$type_id][$rank]['value'] = $d_volume;
       }
-      // skip any properties that the user requested to delete through a previous
-      // AHAH callback or through the current AHAH callback
-      if($d_removed[$prop->cvterm_id . '-' . $prop->rank]) {
-        continue;
+      if ($prop->name == 'Issue') {
+        $d_properties[$type_id][$rank]['value'] = $d_issue;
       }
-      if($form_state['post']['remove-' . $prop->cvterm_id . '-' . $prop->rank]) {
-        $d_removed[$prop->cvterm_id . '-0'] = 1;
-        continue;
+      if ($prop->name == 'Pages') {
+        $d_properties[$type_id][$rank]['value'] = $d_pages;
       }
-      // add new properties that weren't handled yet
-      if(array_key_exists($prop->cvterm_id, $properties)) {
-        $d_properties[$prop->cvterm_id][$prop->rank]['name']  = $prop->name;
-        $d_properties[$prop->cvterm_id][$prop->rank]['id']    = $prop->cvterm_id;
-        $d_properties[$prop->cvterm_id][$prop->rank]['value'] = $prop->value;
-        $num_properties++; 
+      if ($prop->name == 'Volume Title') {
+        $d_properties[$type_id][$rank]['value'] = $d_volumetitle;
       }
-    }
-  }
-  
-  $form['removed'] = array(
-    '#type' => 'hidden',
-    '#value' => $d_removed,
-  );
-  
-  // build the fields for the properties  
-  $i = 0;
-  foreach ($d_properties as $type_id => $ranks) {
-    foreach ($ranks as $rank => $d_property) {
-      $form['properties'][$type_id][$rank]["prop_id-$type_id-$rank"] = array(
-        '#type'          => 'select',
-        '#options'       => $properties,
-        '#default_value' => $d_property['id']
-      );
-      $rows = 2;
-      if  (preg_match('/Abstract/', $d_property['name'])) {
+      
+      // determine how many rows we need in the textarea
+      $rows = 1;
+      if (preg_match('/Abstract/', $prop->name)) {
         $rows = 10;
       }
+      
+      // adjust the term description if needed
+      $description = $prop->definition;
+      if ($prop->name == 'Author List') {
+        $description .= ' For PubMed style citations list each author with the last name first, followed by initials. Each author should be separated by a comma.';
+        $rows = 2;
+      }
+      
+      // add in the fields
+      $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' => $d_property['value'],
-        '#cols'          => 20,
-        '#rows'          => $rows
+        '#default_value' => $d_properties[$type_id][$rank]['value'],
+        '#cols'          => 50,
+        '#rows'          => $rows,
+        '#description'   => $description,
       );
       
       $form['properties'][$type_id][$rank]["remove-$type_id-$rank"] = array(
@@ -228,138 +497,94 @@ function chado_pub_node_form($form_state, $node) {
         '#src'          => drupal_get_path('theme', 'tripal') . '/images/minus.png',
         '#ahah' => array(
           'path'    => "tripal_pub/properties/minus/$type_id/$rank",
-          'wrapper' => 'chado-pub-details',
+          'wrapper' => 'tripal-pub-edit-properties-table',
           'event'   => 'click',
           'method'  => 'replace',
         ), 
         '#attributes' => array('onClick' => 'return false;'),
-      );      
-      $i++;
+      ); 
     }
   }
-  // add one more blank field
-  $form['properties']['new_id'] = array(
-    '#type'          => 'select',
-    '#options'       => $properties,
-  );
-  $form['properties']['new_value'] = array(
-    '#type'          => 'textarea',
-    '#default_value' => '',
-    '#cols'          => 5,
-    '#rows'          => $rows
-  );
-  $form['properties']["add"] = array(
-    '#type'         => 'image_button',      
-    '#value'        => t('Add'),
-    '#src'          => drupal_get_path('theme', 'tripal') . '/images/add.png',
-    '#ahah' => array(
-      'path'    => "tripal_pub/properties/add",
-      'wrapper' => 'chado-pub-details',
-      'event'   => 'click',
-      'method'  => 'replace',          
-    ),   
-    '#attributes' => array('onClick' => 'return false;'),
-  );    
-  /*
-  $form['volume'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Volume'),
-    '#default_value' => $d_volume
-  );
-  
-  $form['issue'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Issue'),
-    '#default_value' => $d_issue
-  );
-
-  $form['pages'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Pages'),
-    '#description' => t('Page number range[s], e.g. 457--459, viii + 664pp, lv--lvii.'),
-    '#default_value' => $d_pages
-  );
-
-  $form['volumetitle'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Volume Title'),
-    '#description' => t('Title of part if one of a series.'),
-    '#default_value' => $d_volumetitle
-  );
-  $form['miniref'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Mini-Ref'),
-    '#required' => FALSE,
-    '#default_value' => $d_miniref
-  );
-
-  $form['publisher'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Publisher Name'),
-    '#required' => FALSE,
-    '#default_value' => $d_publisher
-  );
+  return $num_properties;
+}
+/*
+ * 
+ */
+function theme_chado_pub_node_form($form) {
 
-  $form['pubplace'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Place of Publication'),
-    '#required' => FALSE,
-    '#default_value' => $d_pubplace
-  );
-  */
+  $properties_table = tripal_pub_theme_node_form_properties($form);
   
-  $form['is_obsolete'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Is Obsolete? (Check for Yes)'),
-    '#required' => TRUE,
-    '#default_value' => $d_isobsolete
+  $markup  = drupal_render($form['pub_id']);
+  $markup .= drupal_render($form['title']);
+  $markup .= drupal_render($form['type_id']);
+  $markup .= drupal_render($form['series_name']);
+  $markup .= drupal_render($form['pyear']);
+  $markup .= drupal_render($form['uniquename']);
+  $markup .= "<b>Include Additional Details</b><br>You may add additional properties to this publication 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;
+  $markup .= drupal_render($form['is_obsolete']);
+  
+  $form['properties'] = array(
+    '#type' => 'markup',
+    '#value' =>  $markup,
   );
-  return $form;
-
+  return drupal_render($form);
 }
+
 /*
  * 
  */
-function theme_chado_pub_node_form($form) {
+function tripal_pub_theme_node_form_properties($form) {
   $rows = array();
+  
   if ($form['properties']) {
-    foreach ($form['properties'] as $i => $ranks) {
-      if (is_numeric($i)) {    
-        foreach ($ranks as $rank => $elements) {
+    
+    // first add in the properties derived from the pub and pubprop tables 
+    // 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(  
-              array('data' => drupal_render($elements["prop_id-$i-$rank"]), 'width' => '20%'),    
-              drupal_render($elements["prop_value-$i-$rank"]),
-              array('data' => drupal_render($elements["remove-$i-$rank"]), 'width' => '5%'),
+              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(
-      array('data' => drupal_render($form['properties']['new_id']), 'width' => '20%'),    
-      drupal_render($form['properties']['new_value']),
-      array('data' => drupal_render($form['properties']['add']), 'width' => '5%'),
+      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', '');
-  
-  $markup = '<div id="chado-pub-details">';
-  $markup .= drupal_render($form['pub_id']);
-  $markup .= drupal_render($form['title']);
-  $markup .= drupal_render($form['type_id']);
-  $markup .= drupal_render($form['series_name']);
-  $markup .= drupal_render($form['pyear']);
-  $markup .= drupal_render($form['uniquename']);
-  $markup .= "<b>Include Additional Details</b>";
-  $markup .= theme('table', $headers, $rows);
-  $markup .= "</div>";
+  }
   
-  $form['properties'] = array(
-    '#type' => 'markup',
-    '#value' =>  $markup,
-  );
-  return drupal_render($form);
+  $headers = array('Property Type','Value', '');      
+  return theme('table', $headers, $rows, array('id'=> "tripal-pub-edit-properties-table"));
 }
 
 /*
@@ -369,9 +594,11 @@ function tripal_pub_property_add() {
   $status = TRUE;
 
   // prepare and render the form
-  $form = tripal_core_ahah_prepare_form();   
-  $data = theme('chado_pub_node_form', $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_pub_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();
@@ -392,8 +619,10 @@ function tripal_pub_property_delete() {
   $status = TRUE;
 
   // prepare and render the form
-  $form = tripal_core_ahah_prepare_form();   
-  $data = theme('chado_pub_node_form', $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_pub_theme_node_form_properties($form);
 
   // bind javascript events to the new objects that will be returned 
   // so that AHAH enabled elements will work.

+ 3 - 3
tripal_pub/includes/pubmed.inc

@@ -241,7 +241,7 @@ function tripal_pub_PMID_parse_pubxml($pub_xml) {
       switch ($element) {
         case 'PMID':
           $xml->read(); // get the value for this element
-          $pub['Pub Accession'] = $xml->value;
+          $pub['Publication Accession'] = $xml->value;
           $pub['Publication Database'] = 'PMID';
           break;        
         case 'Article':
@@ -300,7 +300,7 @@ function tripal_pub_PMID_parse_pubxml($pub_xml) {
     }
   }
   $pub['Citation'] = $pub['Author List'] . 
-    '. <a href="http://www.ncbi.nlm.nih.gov/pubmed/' . $pub['Pub Accession'] . '" target="_blank">' . $pub['Title'] .  '</a> ' .
+    '. <a href="http://www.ncbi.nlm.nih.gov/pubmed/' . $pub['Publication Accession'] . '" target="_blank">' . $pub['Title'] .  '</a> ' .
     $pub['Journal ISO Abbreviation']. '. ' . $pub['Publication Date'];
   if ($pub['Volume'] or $pub['Issue']) {
     $pub['Citation'] .= '; ';  
@@ -314,7 +314,7 @@ function tripal_pub_PMID_parse_pubxml($pub_xml) {
   if ($pub['Pages']) {
     $pub['Citation'] .= ':' . $pub['Pages'];
   }
-  $pub['Citation'] .= '. PubMed PMID: ' . $pub['Pub Accession']; 
+  $pub['Citation'] .= '. PubMed PMID: ' . $pub['Publication Accession']; 
   
   //$pub['xml'] = $pub_xml;
   return $pub;

+ 11 - 1
tripal_pub/tpub.obo

@@ -23,7 +23,7 @@ is_a: TPUB:0000015 ! Publication Type
 
 [Term]
 id: TPUB:0000005
-name: Pub Accession
+name: Publication Accession
 relationship: part_of TPUB:0000001 ! publication_dbxref
 
 [Term]
@@ -1310,6 +1310,16 @@ id: TPUB:0000243
 name: Volume Title
 relationship: part_of TPUB:0000037 ! Publication Details
 
+[Term]
+id: TPUB:0000244
+name: Publisher
+relationship: part_of TPUB:0000037 ! Publication Details
+
+[Term]
+id: TPUB:0000245
+name: Published Location
+relationship: part_of TPUB:0000037 ! Publication Details
+
 [Typedef]
 id: is_a
 name: is a

+ 125 - 16
tripal_pub/tripal_pub.module

@@ -274,6 +274,8 @@ function chado_pub_insert($node) {
       'type_id' => $node->type_id
     );
     $pub = tripal_core_chado_insert('pub', $values);
+    
+
   }
 
   if ($pub) {   
@@ -312,29 +314,127 @@ function chado_pub_update($node) {
     // there is no way to handle revisions in Chado but leave
     // this here just to make not we've addressed it.
   }
-
+  
+  // get the publication ID for this publication
   $pub_id = chado_get_id_for_node('pub', $node) ;
+   
+  // get the list of properties for easy lookup (without doing lots of database queries
+  $properties_list = array();
+  $sql = "
+    SELECT CVTS.cvterm_id, CVTS.name, CVTS.definition
+    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} ON CVTO.cv_id = CV.cv_id
+    WHERE CV.name = 'tripal_pub' and CVTO.name = 'Publication Details'
+    ORDER BY CVTS.name ASC 
+  ";
+  $prop_types = chado_query($sql); 
+  $properties = array();
+  while ($prop = db_fetch_object($prop_types)) {
+    $properties_list[$prop->cvterm_id] = $prop->name;
+    // The 'Citation' term is special because it serves
+    // both as a property and as the uniquename for the
+    // pub and we want it stored in both the pub table and the pubprop table
+    if ($prop->name == 'Citation') {
+      $properties[$prop->name][0] = $node->uniquename;   
+    }
+  }
+  
+  // 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  
+  foreach ($node as $name => $value) {
+    if (preg_match('/^prop_value-(\d+)-(\d+)/', $name, $matches)) {
+      $type_id = $matches[1];
+      $index = $matches[2];  
+      $name = $properties_list[$type_id];  
+      $properties[$name][$index] = $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] = $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] = $node->new_value;    
+  } 
+  
+  // iterate through all of the properties and remove those that really are
+  // part of the pub table fields
+  foreach ($properties as $name => $element) {
+    $value = $element[0];
+    if ($name == "Volume") {
+      $volume = $value;
+      unset($properties[$name]);
+    } 
+    elseif ($name == "Volume Title") {
+      $volumetitle = $value;
+      unset($properties[$name]);
+    }
+    elseif ($name == "Issue") {
+      $issue = $value;
+      unset($properties[$name]);
+    }
+    elseif ($name == "Pages") {
+      $pages = $value;
+      unset($properties[$name]);
+    }
+    elseif ($name == "Publisher") {
+      $publisher = $value;
+      unset($properties[$name]);
+    }
+    elseif ($name == "Journal Country" or $name == "Published Location") {
+      $pubplace = $value;
+      unset($properties[$name]);
+    }
+  }
+  
   // update the pub record
   $match = array(
-     'pub_id' => $pub_id,
+    'pub_id' => $pub_id,
   );
   $values = array(
-    'title' => $node->title,
-    'volumetitle' => $node->volumetitle,
-    'volume' => $node->volume,
+    'title'       => $node->title,
     'series_name' => $node->series_name,
-    'issue' => $node->issue,
-    'pyear' => $node->pyear,
-    'pages' => $node->pages,
-    'miniref' => $node->miniref,
-    'uniquename' => $node->uniquename,
-    'type_id' => $node->type_id,
-    'is_obsolete' => $node->is_obsolete,
-    'publisher' => $node->publisher,
-    'pubplace' => $node->pubplace,
-    'type_id' => $node->type_id
+    'type_id'     => $node->type_id,
+    'pyear'       => $node->pyear,
+    'is_obsolete' => $node->is_obsolete ? 'true' : 'false', 
+    'uniquename'  => $node->uniquename,
+    'volumetitle' => $volumetitle,
+    'volume'      => $volume,    
+    'issue'       => $issue,    
+    'pages'       => $pages,
+    'miniref'     => $miniref,        
+    'publisher'   => $publisher,
+    'pubplace'    => $pubplace,
   );
   $status = tripal_core_chado_update('pub', $match, $values);
+  if (!$status) {
+    drupal_set_message("Error updating publication", "error");
+    watchdog('tripal_pub', "Error updating publication", array(), WATCHDOG_ERROR);
+    return;
+  }
+  
+  // now add in the properties by first removing any the publication
+  // already has and adding the ones we have
+  tripal_core_chado_delete('pubprop', array('pub_id' => $pub_id));
+  foreach ($properties as $property => $elements) {
+    foreach ($elements as $rank => $value) {      
+      $status = tripal_pub_insert_property($pub_id, $property, $value, FALSE);
+      if (!$status) {
+        drupal_set_message("Error cannot add property: $property", "error");
+        watchdog('tripal_pub', "Error cannot add property: %prop", 
+          array('%property' => $property), WATCHDOG_ERROR);
+      }
+    } 
+  }
 }
 
 
@@ -355,6 +455,12 @@ function chado_pub_load($node) {
 
   $values = array('pub_id' => $pub_id);
   $pub = tripal_core_generate_chado_var('pub', $values); 
+  
+  // expand the 'text' fields as those aren't included by default
+  // and they really shouldn't be so large to cause problems
+  $pub = tripal_core_expand_chado_vars($pub, 'field', 'pub.title');
+  $pub = tripal_core_expand_chado_vars($pub, 'field', 'pub.volumetitle');  
+  $pub = tripal_core_expand_chado_vars($pub, 'field', 'pub.uniquename');;
 
   $additions = new stdClass();
   $additions->pub = $pub;
@@ -408,6 +514,7 @@ function chado_pub_delete(&$node) {
  * for the chado_pub node form.  This callback is different from the 
  * default 'chado_pub_form' callback
  */
+/*
 function tripal_pub_forms($form_id, $args) {
   $forms = array();
   if($form_id == 'chado_pub_node_form') {
@@ -417,7 +524,7 @@ function tripal_pub_forms($form_id, $args) {
     );
   }
   return $forms;
-}
+}*/
 
 /*
  * 
@@ -435,6 +542,8 @@ function tripal_pub_form_alter(&$form, &$form_state, $form_id) {
       $form['#action'] = url("admin/tripal/tripal_pub/import/new");
     }
   }
+  if ($form_id == "chado_pub_node_form") {
+  }
 } 
 
 /**