Browse Source

Resolved merge conflict where we both fixed the same bug (in stock & feature check ->op is set before ensuring it's save on validation of node form)

Lacey Sanderson 10 years ago
parent
commit
8bebb35274
33 changed files with 1010 additions and 853 deletions
  1. 0 2
      .gitignore
  2. 11 9
      tripal_contact/includes/tripal_contact.chado_node.inc
  3. 27 26
      tripal_core/api/tripal_core.chado_nodes.api.inc
  4. 23 16
      tripal_core/api/tripal_core.chado_nodes.title_and_path.inc
  5. 2 2
      tripal_core/api/tripal_core.chado_query.api.inc
  6. 51 0
      tripal_core/api/tripal_core.chado_schema.api.inc
  7. 30 24
      tripal_core/api/tripal_core.custom_tables.api.inc
  8. 5 2
      tripal_core/api/tripal_core.jobs.api.inc
  9. 11 11
      tripal_core/api/tripal_core.schema_v1.2.api.inc
  10. 36 13
      tripal_core/includes/tripal_core.chado_install.inc
  11. 65 52
      tripal_core/includes/tripal_core.custom_tables.inc
  12. 15 15
      tripal_example/README.txt
  13. 15 13
      tripal_example/api/tripal_example.api.inc
  14. 13 11
      tripal_example/includes/tripal_example.admin.inc
  15. 276 241
      tripal_example/includes/tripal_example.chado_node.inc
  16. 12 12
      tripal_example/theme/templates/tripal_example_base.tpl.php
  17. 16 15
      tripal_example/theme/templates/tripal_example_properties.tpl.php
  18. 14 13
      tripal_example/theme/templates/tripal_example_references.tpl.php
  19. 43 42
      tripal_example/theme/templates/tripal_example_relationships.tpl.php
  20. 20 19
      tripal_example/theme/tripal_example.theme.inc
  21. 9 9
      tripal_example/tripal_example.info
  22. 67 68
      tripal_example/tripal_example.install
  23. 119 121
      tripal_example/tripal_example.module
  24. 2 2
      tripal_example/tripal_example.views.inc
  25. 9 9
      tripal_example/tripal_example.views_default.inc
  26. 31 29
      tripal_feature/includes/tripal_feature.chado_node.inc
  27. 7 9
      tripal_feature/includes/tripal_feature.gff_loader.inc
  28. 9 7
      tripal_featuremap/includes/tripal_featuremap.chado_node.inc
  29. 11 9
      tripal_library/includes/tripal_library.chado_node.inc
  30. 20 15
      tripal_organism/includes/tripal_organism.chado_node.inc
  31. 9 7
      tripal_project/includes/tripal_project.chado_node.inc
  32. 19 18
      tripal_pub/includes/tripal_pub.chado_node.inc
  33. 13 12
      tripal_stock/includes/tripal_stock.chado_node.inc

+ 0 - 2
.gitignore

@@ -1,2 +0,0 @@
-.project
-.settings

+ 11 - 9
tripal_contact/includes/tripal_contact.chado_node.inc

@@ -250,19 +250,19 @@ function chado_contact_validate($node, $form, &$form_state) {
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
   // without the proper values.
-  if($node->op != 'Save') {
+  if(property_exists($node, "op") and $node->op != 'Save') {
     return;
   }
 
   // we are syncing if we do not have a node ID but we do have a contact_id. We don't
   // need to validate during syncing so just skip it.
-  if (is_null($node->nid) and property_exists($node, 'contact_id') and $node->contact_id != 0) {
+  if (!property_exists($node, 'nid') and property_exists($node, 'contact_id') and $node->contact_id != 0) {
     return;
   }
 
   // remove surrounding white-space on submitted values
-  $node->contactname    = trim($node->contactname);
-  $node->description    = trim($node->description);
+  $node->contactname = property_exists($node, 'contactname') ? trim($node->contactname) : '';
+  $node->description = property_exists($node, 'description') ? trim($node->description) : '';
 
 
   // Validating for an update
@@ -367,15 +367,17 @@ function chado_contact_node_access($node, $op, $account ) {
  * @ingroup tripal_contact
  */
 function chado_contact_insert($node) {
-
-  // remove surrounding white-space on submitted values
-  $node->contactname    = trim($node->contactname);
-  $node->description    = trim($node->description);
+  $contact_id = '';
 
   // if there is a contact_id in the $node object then this must be a sync so
   // we can skip adding the contact as it is already there, although
-  // we do need to proceed with the rest of the insert
+  // we do need to proceed with insertion into the chado/drupal linking table.
   if (!property_exists($node, 'contact_id')) {
+    // remove surrounding white-space on submitted values
+    $node->contactname    = trim($node->contactname);
+    $node->description    = trim($node->description);
+
+
     // insert and then get the newly inserted contact record
     $values = array(
       'name'           => $node->contactname,

+ 27 - 26
tripal_core/api/tripal_core.chado_nodes.api.inc

@@ -115,7 +115,7 @@ function chado_node_get_base_table($content_type, $module = FALSE) {
   }
   else {
     $node_types = module_invoke_all('node_info');
-  
+
     if (isset($node_types[$content_type])) {
       $node_info = $node_types[$content_type];
     }
@@ -123,7 +123,7 @@ function chado_node_get_base_table($content_type, $module = FALSE) {
       return FALSE;
     }
   }
-  
+
   if (isset($node_info['chado_node_api']['base_table'])) {
     return $node_info['chado_node_api']['base_table'];
   }
@@ -456,18 +456,18 @@ function chado_node_sync_form_submit($form, $form_state) {
 
 /**
  * Generic function for syncing records in Chado with Drupal nodes.
- * 
+ *
  * @param $base_table
  *   The name of the Chado table containing the record that should be synced
  * @param $max_sync
- *   Optional: A numeric value to indicate the maximum number of records to sync. 
+ *   Optional: A numeric value to indicate the maximum number of records to sync.
  * @param $organism_id
  *   Optional: Limit the list of records to be synced to only those that
  *   are associated with this organism_id. If the record is not assocaited
  *   with an organism then this field is not needed.
  * @param $types
  *   Optional: Limit the list of records to be synced to only those that
- *   match the types listed in this array. 
+ *   match the types listed in this array.
  * @param $ids
  *   Optional:  Limit the list of records to bye synced to only those whose
  *   primary key value matches the ID provided in this array.
@@ -480,7 +480,7 @@ function chado_node_sync_form_submit($form, $form_state) {
  * @param $job_id
  *   Optional. Used by the Trpial Jobs system when running this function
  *   as a job. It is not needed othewise.
- * 
+ *
  * @ingroup tripal_chado_node_api
  */
 function chado_node_sync_records($base_table, $max_sync = FALSE, $organism_id = FALSE,
@@ -539,9 +539,9 @@ function chado_node_sync_records($base_table, $max_sync = FALSE, $organism_id =
   $hook_query_alter = $linking_table . '_chado_node_sync_select_query';
   if (function_exists($hook_query_alter)) {
     $update = call_user_func($hook_query_alter, array(
-      'select' => $select, 
-      'joins' => $joins, 
-      'where_clauses' => $where_clauses, 
+      'select' => $select,
+      'joins' => $joins,
+      'where_clauses' => $where_clauses,
       'where_args' => $where_args,
     ));
     // Now add in any new changes
@@ -573,7 +573,7 @@ function chado_node_sync_records($base_table, $max_sync = FALSE, $organism_id =
     $where .= ') ';
     $sql_args = array_merge($sql_args, $where_args[$category]);
   }
-  
+
   if ($where) {
     $query .= $where;
   }
@@ -610,6 +610,7 @@ function chado_node_sync_records($base_table, $max_sync = FALSE, $organism_id =
       "If the sync fails or is terminated prematurely then the entire set of \n" .
       "synced items is rolled back and will not be found in the database\n\n";
   try {
+    $percent = 0;
     foreach ($results as $record) {
 
       //print "\nLoading $base_table " . ($i + 1) . " of $count ($base_table_id=" . $record->{$base_table_id} . ")...";
@@ -652,6 +653,7 @@ function chado_node_sync_records($base_table, $max_sync = FALSE, $organism_id =
         $form = array();
         $form_state = array();
         node_validate($new_node, $form, $form_state);
+
         if (!form_get_errors()) {
           $node = node_submit($new_node);
           node_save($node);
@@ -665,14 +667,13 @@ function chado_node_sync_records($base_table, $max_sync = FALSE, $organism_id =
     }
     print "\n\nComplete!\n";
   }
-  
+
   catch (Exception $e) {
     $transaction->rollback();
     print "\n"; // make sure we start errors on new line
     watchdog_exception('trp-fsync', $e);
     print "FAILED: Rolling back database changes...\n";
   }
-
 }
 
 /**
@@ -883,43 +884,43 @@ function hook_chado_node_sync_form_submit ($form, $form_state) {
  * Note: For your own module, replace hook in the function name with the machine-name of
  * your chado node type (ie: chado_feature).
  *
- * @param $query 
- *   An array containing the following: 
+ * @param $query
+ *   An array containing the following:
  *    'select': An array of select clauses
- *    'joins:  An array of joins (ie: a single join could be 
+ *    'joins:  An array of joins (ie: a single join could be
  *      'LEFT JOIN {chadotable} alias ON base.id=alias.id')
- *    'where_clauses: An array of where clauses which will all be AND'ed 
+ *    'where_clauses: An array of where clauses which will all be AND'ed
  *      together. Use :placeholders for values.
- *    'where_args: An associative array of arguments to be subbed in to the 
+ *    'where_args: An associative array of arguments to be subbed in to the
  *      where clause where the
  *
  * @ingroup tripal_chado_node_api
  */
 function hook_chado_node_sync_select_query($query) {
 
-  // You can add fields to be selected. Be sure to prefix each field with the 
+  // You can add fields to be selected. Be sure to prefix each field with the
   // tale name.
   $query['select'][] = 'example.myfavfield';
 
-  // Provide any join you may need to the joins array. Be sure to wrap the 
+  // Provide any join you may need to the joins array. Be sure to wrap the
   // table name in curly brackets.
   $query['joins'][] = 'LEFT JOIN {exampleprop} PROP ON PROP.example_id=EXAMPLE.example_id';
 
-  // The category should be a unique id for a group of items that will be 
+  // The category should be a unique id for a group of items that will be
   // concatenated together via an SQL 'OR'.  By default the $where_clases
-  // variable will come with categories of 'id', 'organism' and 'type'.  
+  // variable will come with categories of 'id', 'organism' and 'type'.
   // you can add your own unique category or alter the contents of the existing
   // categories.  Be sure to make sure the category doesn't already exist
   // in the $query['where_clauses']
-  $category = 'my_category'; 
-  
+  $category = 'my_category';
+
   // Provide any aditionall where clauses and their necessary arguments.
-  // Be sure to prefix the field with the table name.   Be sure that the 
-  // placeholder is unique across all categories (perhaps add a unique 
+  // Be sure to prefix the field with the table name.   Be sure that the
+  // placeholder is unique across all categories (perhaps add a unique
   // prefix/suffix).
   $query['where_clauses'][$category][] = 'example.myfavfield = :favvalue';
   $query['where_args'][$category][':favvalue'] = 'awesome-ness';
-  
+
   // Must return the updated query
   return $query;
 }

+ 23 - 16
tripal_core/api/tripal_core.chado_nodes.title_and_path.inc

@@ -576,7 +576,10 @@ function chado_get_node_url($node) {
  *   error is displayed.
  *
  * @param $node
- *   The node to set the URL for.
+ *   The node to set the URL for.  The node object must have at a
+ *   minimum the 'nid' and 'type' properties, as well as the
+ *   chado object (e.g. 'organism' for chado_organism node type, and
+ *   'feature' for chado_feature node type, etc.).
  *
  * @return
  *   The URL alias that was set.
@@ -663,9 +666,7 @@ function chado_update_existing_node_urls($content_type, $job_id = 0) {
 
   try {
     // Get the number of records we need to set URLs for.
-    $num_nodes = db_query(
-        'SELECT count(*) FROM {' . $content_type . '}'
-      )->fetchField();
+    $num_nodes = db_query('SELECT count(*) FROM {' . $content_type . '}')->fetchField();
 
     // Calculate the interval at which we will print an update on the screen.
     $num_set = 0;
@@ -673,8 +674,8 @@ function chado_update_existing_node_urls($content_type, $job_id = 0) {
 
     if ($num_nodes > 0) {
 
-      print "There are $num_nodes nodes to update URLs for. You will be \n"
-       . "updated on the progress every 100 nodes.\n\n";
+      print "There are $num_nodes nodes to update URLs for. You will be \n" .
+            "updated on the progress every 100 nodes.\n\n";
 
       // Get the list of nodes of this particular content type.
       $query = new EntityFieldQuery();
@@ -687,10 +688,16 @@ function chado_update_existing_node_urls($content_type, $job_id = 0) {
 
         foreach ($nids as $nid) {
 
-          // Load the current node.
-          // We do it this way instead of using noad_load_multiple to load them
-          // all at once to avoid overloading the memory.
-          $node = node_load($nid);
+          // Load the current node. Normally here we would use the node_load()
+          // function that is part of the Drupal API.  However, this seems
+          // to have memory leaks that have not yet been identified, so
+          // we'll create the object by hand:
+          $node = new stdClass();
+          $node->nid = $nid;
+          $node->type = $content_type;
+          $table = preg_replace('/chado_/', '', $content_type);
+          $id = chado_get_id_from_nid($table, $nid);
+          $node->$table = chado_generate_var($table, array($table . "_id" => $id));
 
           // Now set the URL for the current node.
           $alias = chado_set_node_url($node);
@@ -699,14 +706,14 @@ function chado_update_existing_node_urls($content_type, $job_id = 0) {
           if ($num_set % $num_per_interval == 0) {
             $percent = ($num_set / $num_nodes) * 100;
 
+            // Update the user on progress.
+            $percent = sprintf("%.2f", $percent);
+            print "Setting URLs (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
+
             // Update the tripal job.
             if ($job_id) {
               tripal_set_job_progress($job_id, intval($percent));
             }
-
-            // Update the user on progress.
-            $percent = sprintf("%.2f", $percent);
-            print "Setting URLs (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
           }
           $num_set++;
         }
@@ -736,7 +743,7 @@ function chado_update_existing_node_urls($content_type, $job_id = 0) {
 }
 
 /**
- * Generic "Set Node url" sub-form for setting the url of any chado node
+ * Generic "Set Node URL" sub-form for setting the url of any chado node
  *
  * @param $form
  *   The Drupal form array into which the property form elements will be added
@@ -1305,7 +1312,7 @@ function chado_get_token_value($token_info, $node) {
   $token = $token_info['token'];
   $table = $token_info['table'];
   $var = $node;
-  
+
   // Iterate through each portion of the location string. An example string
   // might be:  stock > type_id > name.
   $location = explode('>', $token_info['location']);

+ 2 - 2
tripal_core/api/tripal_core.chado_query.api.inc

@@ -905,7 +905,7 @@ function chado_delete_record($table, $match, $options = NULL) {
  * Additional Options Include:
  *  - has_record
  *     Set this argument to 'TRUE' to have this function return a numeric
- *     value for the number of recrods rather than the array of records.  this
+ *     value for the number of records rather than the array of records.  this
  *     can be useful in 'if' statements to check the presence of particula records.
  *  - return_sql
  *     Set this to 'TRUE' to have this function return an array where the first
@@ -1349,7 +1349,7 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
     }
     $sql = drupal_substr($sql, 0, -2);  // get rid of the trailing ', '
   }
-  
+
   // Limit the records returned
   if (array_key_exists('limit', $options) and is_numeric($options['limit'])) {
     $sql .= " LIMIT " . $options['limit'];

+ 51 - 0
tripal_core/api/tripal_core.chado_schema.api.inc

@@ -56,6 +56,57 @@ function chado_table_exists($table) {
   return TRUE;
 }
 
+/**
+ * A Chado-aware replacement for the db_index_exists() function.
+ *
+ * @param $table
+ *   The table to be altered.
+ * @param $name
+ *   The name of the index.
+ */
+function chado_index_exists($table, $name) {
+  global $databases;
+
+  $indexname = $table . '_' . $name . '_idx';
+
+  $default_db = $databases['default']['default']['database'];
+
+  $sql = "SELECT 1 as exists FROM pg_indexes WHERE indexname = :indexname";
+
+  $result = db_query($sql, array(':indexname' => $indexname));
+  $exists = $result->fetchObject();
+  return $exists->exists;
+}
+
+/**
+ * A Chado-aware wrapper for the db_add_index() function.
+ *
+ * @param $table
+ *   The table to be altered.
+ * @param $name
+ *   The name of the index.
+ * @param $fields
+ *   An array of field names.
+ */
+function chado_add_index($table, $name, $fields) {
+  $indexname = $table . '_' . $name . '_idx';
+
+  $query = 'CREATE INDEX "' . $indexname . '" ON {' . $table . '} ';
+  $query .= '(';
+  $temp = array();
+  foreach ($fields as $field) {
+    if (is_array($field)) {
+      $temp[] = 'substr(' . $field[0] . ', 1, ' . $field[1] . ')';
+    }
+    else {
+      $temp[] = '"' . $field . '"';
+    }
+  }
+  $query .= implode(', ', $temp);
+  $query .= ')';
+  return chado_query($query);
+}
+
 /**
  * Check that any given schema exists
  *

+ 30 - 24
tripal_core/api/tripal_core.custom_tables.api.inc

@@ -38,26 +38,26 @@ function chado_edit_custom_table($table_id, $table_name, $schema, $skip_if_exist
     $record->table_id = $table_id;
     $record->table_name = $table_name;
     $record->schema = serialize($schema);
-  
+
     // get the current custom table record
     $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_id = :table_id";
     $results = db_query($sql, array(':table_id' => $table_id));
     $custom_table = $results->fetchObject();
-  
+
     // if this is a materialized view then don't allow editing with this function
     if ($custom_table->mview_id) {
       tripal_report_error('tripal_core', TRIPAL_ERROR, "Please use the tripal_edit_mview() function to edit this custom table as it is a materialized view.", array());
       drupal_set_message("This custom table is a materialized view. Please use the "  . l('Materialized View', 'admin/tripal/schema/mviews') . " interface to edit it.", 'error');
       return FALSE;
     }
-    
+
     // if the user changed the table name, we want to drop the old one and force
     // creation of the new one.
     if ($custom_table->table_name != $table_name) {
       chado_query("DROP TABLE %s", $custom_table->table_name);
       $skip_if_exists = 0; // we want to create the table
     }
-  
+
     // if skip creation is not set, then drop the table from chado if it exists
     if (!$skip_if_exists) {
       if (db_table_exists($custom_table->table_name)) {
@@ -65,7 +65,7 @@ function chado_edit_custom_table($table_id, $table_name, $schema, $skip_if_exist
         drupal_set_message(t("Custom Table " . $custom_table->table_name . " dropped"));
       }
     }
-  
+
     // update the custom table record and run the create custom table function
     drupal_write_record('tripal_custom_tables', $record, 'table_id');
     $success = chado_create_custom_table ($table_name, $schema, $skip_if_exists);
@@ -90,10 +90,10 @@ function chado_edit_custom_table($table_id, $table_name, $schema, $skip_if_exist
  * table. This way the function cannot be used to accidentally alter existing
  * non custom tables.  If $skip_if_exists is set then the table is simply
  * added to the tripal_custom_tables and no table is created in Chado.
- * 
- * If you are creating a materialized view do not use this function, but rather 
+ *
+ * If you are creating a materialized view do not use this function, but rather
  * use the tripal_add_mview(). A materialized view is also considered a custom table
- * and an entry for it will be added to both the tripal_mviews and 
+ * and an entry for it will be added to both the tripal_mviews and
  * tripal_custom_tables tables, but only if the tripal_add_mview() function is
  * used. The optional $mview_id parameters in this function is intended
  * for use by the tripal_add_mview() function when it calls this function
@@ -129,20 +129,20 @@ function chado_create_custom_table($table, $schema, $skip_if_exists = 1, $mview_
     $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_name = :table_name";
     $results = db_query($sql, array(':table_name' => $table));
     $centry = $results->fetchObject();
-  
+
     // check to see if the table already exists in the chado schema
     $exists = chado_table_exists($table);
-  
+
     // if the table does not exist then create it
     if (!$exists) {
       $ret = db_create_table('chado.' . $table, $schema);
       $created = 1;
     }
-  
+
     // if the table exists in Chado and in our custom table and
     // skip creation is turned off then drop and re-create the table
     if ($exists and is_object($centry) and !$skip_if_exists) {
-  
+
       // drop the table we'll recreate it with the new schema
       chado_query('DROP TABLE {' . $table . '}');
       // remove any 'referring_tables' from the array as the db_create_table doesn't use that
@@ -153,7 +153,7 @@ function chado_create_custom_table($table, $schema, $skip_if_exists = 1, $mview_
       db_create_table('chado.' . $table, $new_schema);
       $recreated = 1;
     }
-  
+
     // add an entry in the tripal_custom_table
     $record = new stdClass();
     $record->table_name = $table;
@@ -161,17 +161,17 @@ function chado_create_custom_table($table, $schema, $skip_if_exists = 1, $mview_
     if ($mview_id) {
       $record->mview_id = $mview_id;
     }
-  
+
     // if an entry already exists then remove it
     if ($centry) {
       $sql = "DELETE FROM {tripal_custom_tables} WHERE table_name = :table_name";
       db_query($sql, array(':table_name' => $table));
     }
-    $success = drupal_write_record('tripal_custom_tables', $record); 
+    $success = drupal_write_record('tripal_custom_tables', $record);
 
     // now add any foreign key constraints
     if (($created or !$skip_if_exists) and array_key_exists('foreign keys', $schema)) {
-  
+
       // iterate through the foreign keys and add each one
       $fkeys = $schema['foreign keys'];
       foreach ($fkeys as $fktable => $fkdetails) {
@@ -192,7 +192,7 @@ function chado_create_custom_table($table, $schema, $skip_if_exists = 1, $mview_
     $transaction->rollback();
     watchdog_exception('tripal_core', $e);
     $error = _drupal_decode_exception($e);
-    drupal_set_message(t("Could not add custom table '%table_name': %message.", 
+    drupal_set_message(t("Could not add custom table '%table_name': %message.",
       array('%table_name' => $table, '%message' => $error['!message'])), 'error');
     return FALSE;
   }
@@ -209,25 +209,31 @@ function chado_create_custom_table($table, $schema, $skip_if_exists = 1, $mview_
 }
 
 /**
- * This function is used to validate a Drupal Schema API array prior to 
+ * This function is used to validate a Drupal Schema API array prior to
  * passing it ot the chado_create_custom_table_schema().  This function
  * can be used in a form validate function or whenver a schema is provided by
  * a user and needs validation.
- * 
+ *
  * @param $schema_array
  *   the Drupal Schema API compatible array
- *   
+ *
  * @return
  *   An empty string for success or a message string for failure
- * 
+ *
  * @ingroup tripal_custom_tables_api
  */
 function chado_validate_custom_table_schema($schema_array) {
 
+
   if (is_array($schema_array) and !array_key_exists('table', $schema_array)) {
     return "The schema array must have key named 'table'";
   }
-  
+
+  if (!ctype_lower($schema_array['table'])) {
+    return "Postgres will automatically change the table name to lower-case. To prevent unwanted side-effects, please rename the table with all lower-case characters.";
+  }
+
+
   // check index length
   if (array_key_exists('indexes', $schema_array)) {
     foreach ($schema_array['indexes'] as $index_name => $details) {
@@ -239,7 +245,7 @@ function chado_validate_custom_table_schema($schema_array) {
       }
     }
   }
-  
+
   // check unique key length
   if (array_key_exists('unique keys', $schema_array)) {
     foreach ($schema_array['unique keys'] as $index_name => $details) {
@@ -251,7 +257,7 @@ function chado_validate_custom_table_schema($schema_array) {
       }
     }
   }
-  
+
 }
 /**
  * Retrieve the custom table id given the name

+ 5 - 2
tripal_core/api/tripal_core.jobs.api.inc

@@ -83,8 +83,11 @@ function tripal_add_job($job_name, $modulename, $callback, $arguments, $uid, $pr
   $record->arguments = $args;
 
   if (drupal_write_record('tripal_jobs', $record)) {
-    $jobs_url = url("admin/tripal/tripal_jobs");
-    drupal_set_message(t("Job '%job_name' submitted.  Check the <a href='!jobs_url'>jobs page</a> for status", array('%job_name' => $job_name, '!jobs_url' => $jobs_url)));
+    drupal_set_message(t("Job '%job_name' submitted.", array('%job_name' => $job_name)));
+    if (user_access('administer tripal')) {
+      $jobs_url = url("admin/tripal/tripal_jobs");
+      drupal_set_message(t("Check the <a href='!jobs_url'>jobs page</a> for status.", array('!jobs_url' => $jobs_url)));
+    }
   }
   else {
     drupal_set_message(t("Failed to add job %job_name.", array('%job_name' => $job_name)), 'error');

+ 11 - 11
tripal_core/api/tripal_core.schema_v1.2.api.inc

@@ -73,7 +73,7 @@ function tripal_core_chado_schema_v1_2_acquisition() {
         'description' => '',
         'type' => 'datetime',
         'not null' => FALSE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
       'name' => array(
         'description' => '',
@@ -384,7 +384,7 @@ function tripal_core_chado_schema_v1_2_analysis() {
         'description' => '',
         'type' => 'datetime',
         'not null' => TRUE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
     ),
     'primary key' => array(
@@ -937,7 +937,7 @@ function tripal_core_chado_schema_v1_2_assay() {
         'description' => '',
         'type' => 'datetime',
         'not null' => FALSE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
       'arrayidentifier' => array(
         'description' => '',
@@ -1738,13 +1738,13 @@ function tripal_core_chado_schema_v1_2_cell_line() {
         'description' => '',
         'type' => 'datetime',
         'not null' => TRUE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
       'timelastmodified' => array(
         'description' => '',
         'type' => 'datetime',
         'not null' => TRUE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
     ),
     'primary key' => array(
@@ -4889,13 +4889,13 @@ function tripal_core_chado_schema_v1_2_feature() {
         'description' => '',
         'type' => 'datetime',
         'not null' => TRUE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
       'timelastmodified' => array(
         'description' => '',
         'type' => 'datetime',
         'not null' => TRUE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
     ),
     'primary key' => array(
@@ -7136,13 +7136,13 @@ function tripal_core_chado_schema_v1_2_library() {
         'description' => '',
         'type' => 'datetime',
         'not null' => TRUE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
       'timelastmodified' => array(
         'description' => '',
         'type' => 'datetime',
         'not null' => TRUE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
     ),
     'primary key' => array(
@@ -11682,7 +11682,7 @@ function tripal_core_chado_schema_v1_2_quantification() {
         'description' => '',
         'type' => 'datetime',
         'not null' => FALSE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
       'name' => array(
         'description' => '',
@@ -13881,7 +13881,7 @@ function tripal_core_chado_schema_v1_2_tableinfo() {
         'description' => '',
         'type' => 'date',
         'not null' => TRUE,
-        'default' => 'ow(',
+        'default' => 'now()',
       ),
     ),
     'primary key' => array(

+ 36 - 13
tripal_core/includes/tripal_core.chado_install.inc

@@ -32,31 +32,54 @@ function tripal_core_chado_load_form() {
         'Upgrade Chado v1.11 to v1.2' => t('Upgrade existing Chado v1.11 to v1.2 (no data is lost)'),
         'Install Chado v1.11' => t('New Install of Chado v1.11 (erases all existing Chado data if Chado already exists)')
      ),
-     '#description' => t('Select an action to perform'),
-     '#required' => TRUE
+     '#description' => t('Select an action to perform. If you want to install Chado all other Tripal modules must not be installed.'),
+     '#required' => TRUE,
   );
 
-  $form['description'] = array(
-    '#type' => 'item',
-    '#value' => t("<font color=\"red\">WARNING:</font> A new install of Chado v1.2 or v1.11 "
-      . "will install Chado within the Drupal database in a \"chado\" schema. If the \"chado\" schema already exists it will "
-      . "be overwritten and all data will be lost.  You may choose to update an existing Chado v1.11 if it was installed with a previous "
-      . "version of Tripal (e.g. v0.3b or v0.3.1). The update will not erase any data. "
-      . "If you are using chado in a database external to the "
-      . "Drupal database with a 'chado' entry in the 'settings.php' \$db_url argument "
-      . "then Chado will be installed but will not be used .  The external "
-      . "database specified in the settings.php file takes precedence."),
+  $form['warning'] = array(
+    '#markup' => "<div><font color=\"red\">WARNING:</font>" . t('A new install of
+      Chado will remove and recreate the Chado database if it already exists.') . '</div>',
   );
 
   $form['button'] = array(
     '#type' => 'submit',
     '#value' => t('Install/Upgrade Chado'),
-    '#weight' => 2,
   );
 
   return $form;
 }
 
+function tripal_core_chado_load_form_validate($form, &$form_state) {
+  // We do not want to allow re-installation of Chado if other
+  // Tripal modules are installed.  This is because the install files
+  // of those modules may add content to Chado and reinstalling Chado
+  // removes that content which may break the modules.
+
+  if ($form_state['values']['action_to_do'] == "Install Chado v1.2" or
+      $form_state['values']['action_to_do'] == "Install Chado v1.11") {
+
+    $modules = system_get_info('module');
+    $list = array();
+    foreach ($modules as $mname => $module) {
+      if (array_key_exists('dependencies', $module) and in_array('tripal_core', $module['dependencies'])) {
+        $list[] = $module['name'] . " ($mname)";
+      }
+    }
+    if (count($list) > 0) {
+      form_set_error("action_to_do", "Chado cannot be installed while other Tripal modules
+          are enabled.  You must fully uninstall the following modules if you
+          would like to install or re-install chado.<br>" .
+          implode("<br>", $list));
+    }
+  }
+  if ($form_state['values']['action_to_do'] == "Upgrade Chado v1.11 to v1.2") {
+    // Make sure we are already not at v1.2
+    $real_version = chado_get_version(TRUE);
+    if ($real_version == "1.2") {
+      form_set_error("action_to_do", "You are already at v1.2.  There is no need to upgrade.");
+    }
+  }
+}
 /**
  * Submit Load Chado Schema Form
  *

+ 65 - 52
tripal_core/includes/tripal_core.custom_tables.inc

@@ -57,7 +57,7 @@ function tripal_custom_table_admin_view() {
  * @ingroup tripal_custom_tables
  */
 function tripal_custom_table_new_page() {
- 
+
   $form = drupal_get_form('tripal_custom_tables_form');
   return drupal_render($form);
 }
@@ -140,7 +140,7 @@ function tripal_custom_tables_form($form, &$form_state = NULL, $table_id = NULL)
     $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_id = :table_id ";
     $results = db_query($sql, array(':table_id' => $table_id));
     $custom_table = $results->fetchObject();
-    
+
     // if this is a materialized view then don't allow editing with this function
     if (property_exists($custom_table, 'mview_id') and $custom_table->mview_id) {
       drupal_set_message("This custom table is a materialized view. Please use the "  . l('Materialized View', 'admin/tripal/schema/mviews') . " interface to edit it.", 'error');
@@ -161,7 +161,7 @@ function tripal_custom_tables_form($form, &$form_state = NULL, $table_id = NULL)
       $default_schema = preg_replace('/=>\s+\n\s+array/', '=> array', $default_schema);
     }
   }
-  
+
   $form['return'] = array(
     '#type' => 'markup',
     '#markup' => "<p>" . l("Return to list of custom tables", "admin/tripal/schema/custom_tables") . "</p>",
@@ -178,49 +178,33 @@ function tripal_custom_tables_form($form, &$form_state = NULL, $table_id = NULL)
     '#value' => $table_id
   );
 
-  $form['instructions']= array(
+  $form['instructions'] = array(
+    '#type' => 'fieldset',
+    '#title' => 'Instructions',
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $form['instructions']['text'] = array(
     '#type'          => 'item',
-    '#description'         => t('At times it is necessary to add a custom table to the Chado schema.
-       These are not offically sanctioned tables but may be necessary for local data requirements.
-       Avoid creating custom tables when possible as other GMOD tools may not recognize these tables
-       nor the data in them.  Linker tables or property tables are often a good candidate for
-       a custom table. For example a table to link stocks and libraries (e.g. library_stock). 
-       Try to model linker or propery tables after existing tables.  If the
-       table already exists it will not be modified.  To force dropping and recreation of the table
-       click the checkbox below.  Tables are defined usign the ' . l('Drupal Schema API', 'https://api.drupal.org/api/drupal/includes!database!schema.inc/group/schemaapi/7', array('attributes' => array('target' => '_blank')))
+    '#description'         => '<p>' . t('At times it is necessary to add a custom table
+       to the Chado schema. These are not offically sanctioned tables but may
+       be necessary for local data requirements. Avoid creating custom tables
+       when possible as other GMOD tools may not recognize these tables nor
+       the data in them.  Linker tables or property tables are often a good
+       candidate for a custom table. For example a table to link stocks and
+       libraries (e.g. library_stock). Try to model linker or propery tables
+       after existing tables.  If the table already exists it will not be
+       modified.  To force dropping and recreation of the table
+       click the checkbox below.  Tables are defined usign the ' .
+       l('Drupal Schema API', 'https://api.drupal.org/api/drupal/includes!database!schema.inc/group/schemaapi/7',
+         array('attributes' => array('target' => '_blank'))) . '</p>' .
+      '<p>Please note that table names should be all lower-case.</p>'
     ),
   );
 
-  $form['force_drop']= array(
-    '#type'          => 'checkbox',
-    '#title'         => t('Re-create table'),
-    '#description'   => t('Check this box if your table already exists and you would like to drop it and recreate it.'),
-    '#default_value' => $default_force_drop,
-  );
-  $form['schema']= array(
-    '#type'          => 'textarea',
-    '#title'         => t('Schema Array'),
-    '#description'   => t('Please enter the ' . l('Drupal Schema API', 'https://api.drupal.org/api/drupal/includes!database!schema.inc/group/schemaapi/7', array('attributes' => array('target' => '_blank'))) . ' compatible array that defines the table.'),
-    '#required'      => FALSE,
-    '#default_value' => $default_schema,
-    '#rows'          => 25,
-  );
-
-  if ($action == 'Edit') {
-    $value = 'Save';
-  }
-  if ($action == 'Add') {
-    $value = 'Add';
-  }
-  $form['submit'] = array(
-    '#type'         => 'submit',
-    '#value'        => t($value),
-    '#executes_submit_callback' => TRUE,
-  );
-
-  $form['example']= array(
-    '#type'          => 'item',
-    '#description'         => "<br>Example library_stock table: <pre>
+  $form['instructions']['example']= array(
+      '#type'          => 'item',
+      '#description'         => "Example library_stock table: <pre>
 array (
   'table' => 'library_stock',
   'fields' => array (
@@ -264,6 +248,35 @@ array (
     </pre>",
   );
 
+  $form['force_drop']= array(
+    '#type'          => 'checkbox',
+    '#title'         => t('Re-create table'),
+    '#description'   => t('Check this box if your table already exists and you would like to drop it and recreate it.'),
+    '#default_value' => $default_force_drop,
+  );
+  $form['schema']= array(
+    '#type'          => 'textarea',
+    '#title'         => t('Schema Array'),
+    '#description'   => t('Please enter the ' . l('Drupal Schema API', 'https://api.drupal.org/api/drupal/includes!database!schema.inc/group/schemaapi/7', array('attributes' => array('target' => '_blank'))) . ' compatible array that defines the table.'),
+    '#required'      => FALSE,
+    '#default_value' => $default_schema,
+    '#rows'          => 25,
+  );
+
+  if ($action == 'Edit') {
+    $value = 'Save';
+  }
+  if ($action == 'Add') {
+    $value = 'Add';
+  }
+  $form['submit'] = array(
+    '#type'         => 'submit',
+    '#value'        => t($value),
+    '#executes_submit_callback' => TRUE,
+  );
+
+
+
 
   return $form;
 }
@@ -301,13 +314,13 @@ function tripal_custom_tables_form_validate($form, &$form_state) {
       if (is_array($schema_array) and !array_key_exists('table', $schema_array)) {
         form_set_error('schema', t("The schema array must have key named 'table'"));
       }
-      
+
       // validate the contents of the array
       $error = chado_validate_custom_table_schema($schema_array);
       if ($error) {
         form_set_error('schema', $error);
       }
-      
+
       if ($action == 'Edit') {
         // see if the table name has changed. If so, then check to make sure
         // it doesn't already exists. We don't want to drop a table we didn't mean to
@@ -359,7 +372,7 @@ function tripal_custom_tables_form_submit($form, &$form_state) {
   else {
     drupal_set_message(t("No action performed."));
   }
-  
+
   drupal_goto("admin/tripal/schema/custom_tables");
 }
 
@@ -369,26 +382,26 @@ function tripal_custom_tables_form_submit($form, &$form_state) {
  * @ingroup tripal_custom_tables
  */
 function tripal_custom_tables_delete_form($form, &$form_state, $table_id) {
-  
+
   // get details about this table entry
   $sql = "SELECT * FROM {tripal_custom_tables} WHERE table_id = :table_id";
   $results = db_query($sql, array(':table_id' => $table_id));
   $entry = $results->fetchObject();
-  
+
   // if this is a materialized view then don't allow editing with this function
   if ($entry->mview_id) {
     drupal_set_message("This custom table is a materialized view. Please use the "  . l('Materialized View', 'admin/tripal/schema/mviews') . " interface to delete it.", 'error');
     drupal_goto("admin/tripal/schema/custom_tables");
     return array();
   }
-  
-  
+
+
   $form = array();
   $form['table_id'] = array(
     '#type' => 'value',
     '#value' => $table_id
   );
-  
+
   $form['sure'] = array(
     '#type' => 'markup',
     '#markup' => '<p>Are you sure you want to delete the "' . $entry->table_name . '" custom table?</p>'
@@ -406,14 +419,14 @@ function tripal_custom_tables_delete_form($form, &$form_state, $table_id) {
 
 /**
  * form submit hook for the tripal_custom_tables_delete_form form.
- * 
+ *
  * @param $form
  * @param $form_state
  */
 function tripal_custom_tables_delete_form_submit($form, &$form_state) {
   $action   = $form_state['clicked_button']['#value'];
   $table_id = $form_state['values']['table_id'];
-    
+
   if (strcmp($action, 'Delete') == 0) {
     chado_delete_custom_table($table_id);
   }

+ 15 - 15
tripal_example/README.txt

@@ -1,7 +1,7 @@
-This module is provided as a template for creating a custom Tripal Extension 
+This module is provided as a template for creating a custom Tripal Extension
 Module for Drupal 7 and Tripal 2.x.
 
-Drupal does provide quite a bit of documentation on its website at 
+Drupal does provide quite a bit of documentation on its website at
 http://www.drupal.org but the easiest way to learn to program a Drupal module
 is to purchase the following book:
 
@@ -12,7 +12,7 @@ But this quick link can help get you started:
   https://drupal.org/developing/modules/7
 
 Briefly, to create a Drupal module you must
- 
+
 1) Create a directory to house all of your module's files
 2) Create a .info inside of the directory which provides information about your
    module to Drupal
@@ -44,11 +44,11 @@ If you want to integrate with Drupal Views 3.x:
 
 Include Files
 -------------
-To limit the size of files, some functionality can be placed inside of 
+To limit the size of files, some functionality can be placed inside of
 "include" files. Include files are placed inside of an 'includes' directory.
 [module dir]/includes
 
-If your module creates a node type that uses data housed in Chado, you should 
+If your module creates a node type that uses data housed in Chado, you should
 place all of the Drupal hooks for nodes inside of an include named:
 [module dir]/includes/[module name].chado_node.inc
 
@@ -60,18 +60,18 @@ All other include files should be named in the following way:
 [module dir]/includes/[module name].[function].inc
 
 where [function] is a brief description of the functionality provided by the
-include file.  Please only use underscores inside of the [function] (no dashes
+include file. Please only use underscores inside of the [function] (no dashes
 or periods).
 
 
 Theme Files
 -------------
-Tripal primarily uses template files for displaying content from Chado. This 
+Tripal primarily uses template files for displaying content from Chado. This
 allows anyone to easily change the way data is displayed without needing to
-delve into the module's source code.  A template typically provides data for
+delve into the module's source code. A template typically provides data for
 a single data type (e.g. feature) or association (e.g. properties associated to
-features, or publications associated with featurmaps, etc.).  These template
-files and any JavaScript, CSS or images needed to suppport them are all
+features, or publications associated with featurmaps, etc.). These template
+files and any JavaScript, CSS or images needed to support them are all
 housed inside of a 'theme' directory with the following structure:
 [module dir]/theme
 [module dir]/theme/css       (for CSS files)
@@ -91,18 +91,18 @@ Template files are named in the following way
 [module dir]/theme/templates/[module name]_[function].tpl.php.
 
 Notice that templates have an underscore separating the [module name] from the
-[function].  Typically a period is used (as with include files) but for
-backwards compatibility the undescores are kept.  
+[function]. Typically a period is used (as with include files) but for
+backwards compatibility the underscores are kept.
 
 API Files
 ---------
-If your module will provide a set of functions that can be used as an 
-Application Programming Intervace (API), then those functions should be placed 
+If your module will provide a set of functions that can be used as an
+Application Programming Interface (API), then those functions should be placed
 in files housed in the 'api' directory:
 [module dir]/api
 
 When creating API functions try to organize them into groups of related function
-and separate them into files by function with the following nameing:
+and separate them into files by function with the following naming:
 [module dir]/api/[module name].[function].api.inc
 
 

+ 15 - 13
tripal_example/api/tripal_example.api.inc

@@ -2,7 +2,8 @@
 
 /**
  * @file
- * Provides an application programming interface (API) for working the example module
+ * Provides an application programming interface (API) for working the example
+ * module
  */
 
 /**
@@ -12,22 +13,23 @@
  * Provides an application programming interface (API) for working with features
  * @}
  */
- 
-// EXPLANATION: This file is used for housing any API function that your
-// module creates.  It is suggested you follow the naming style for Tripal 
-// API functions. Below are naming rules for Tripal API functions:
+
+// EXPLANATION: This file is used for housing any API function that your module
+// creates. It is suggested you follow the naming style for Tripal API
+// functions. Below are naming rules for Tripal API functions:
 //
 // 1) Prefix the function with 'chado_' for all insert, updates, delete or get
-//    function on a table in the chado schema.  Tripal should provide all of these 
-//    functions for tables that come with Chado.  But, you can use this prefix 
-//    for API functions on custom tables that your module may add.
+//    function on a table in the chado schema. Tripal should provide all of
+//    these functions for tables that come with Chado. But, you can use this
+//    prefix for API functions on custom tables that your module may add.
 // 2) For all other functions prefix the function with your module name. So
 //    for this example module the prefix would be 'tripal_example_'
 // 3) A 'verb' should follow the function prefix indicating the action that
 //    the function performs. Commonly used verbs are 'get', 'insert', 'update'
-//    'associate', 'execute', etc.  An exception is for functions that
-//    test state rather than perform an action (e.g. does something exist).  
-//    For functions that test state use 'does' instead of a verb 
-//    (e.g. tripal_example_does_pub_exist) 
-// 4) Follow the verb with a short predicate describing what is being acted upon.
+//    'associate', 'execute', etc. An exception is for functions that
+//    test state rather than perform an action (e.g. does something exist).
+//    For functions that test state use 'does' instead of a verb
+//    (e.g. tripal_example_does_pub_exist)
+// 4) Follow the verb with a short predicate describing what is being acted
+//    upon.
 //

+ 13 - 11
tripal_example/includes/tripal_example.admin.inc

@@ -18,10 +18,9 @@ function tripal_example_admin_examples_listing() {
   drupal_set_breadcrumb($breadcrumb);
 
 
-  // EXPLANATION:  Typically for all Tripal modules the home administrative
-  // page for the module contains a search form to help the adminstrator
-  // locate records.  The following example code adds a default View to
-  // the page
+  // EXPLANATION:  Typically for all Tripal modules the home administrative page
+  // for the module contains a search form to help the adminstrator locate
+  // records. The following example code adds a default View to the page
   /*
   // Add the view
   $view = views_embed_view('tripal_example_admin_examples','default');
@@ -55,19 +54,23 @@ function tripal_example_admin() {
     '#markup' => t('There are currently no settings to configure.')
   );
 
-  // If your module is using the Chado Node: Title & Path API to allow custom titles
-  // for your node type then you need to add the configuration form for this functionality.
+  // If your module is using the Chado Node: Title & Path API to allow custom
+  // titles for your node type then you need to add the configuration form for
+  // this functionality.
   $details = array(
-    'module' => 'tripal_example',       // the name of the MODULE implementing the content type
+      // the name of the MODULE implementing the content type
+    'module' => 'tripal_example',
       // An array of options to use under "Page Titles"
-      // the key should be the token and the value should be the human-readable option
+      // the key should be the token and the value should be the human-readable
+      // option
     'options' => array(
       '[example.name]' => 'Germplasm Name Only',
       '[example.uniquename]' => 'Germplasm Unique Name Only',
         // there should always be one options matching the unique constraint.
-        // If you have a more human-readable constraint, then that is preferrable.
+        // If you have a more human-readable constraint, then that is
+        // preferable.
         // See the tripal feature module for a good example of this.
-      '[example.example_id]' => 'Unique Contraint: The Chado ID for Examples'
+      '[example.example_id]' => 'Unique Constraint: The Chado ID for Examples'
     ),
     // the token indicating the unique constraint in the options array
     'unique_option' => '[example.example_id]'
@@ -88,4 +91,3 @@ function tripal_example_admin() {
 function tripal_example_admin_validate($form, &$form_state) {
 
 }
-

+ 276 - 241
tripal_example/includes/tripal_example.chado_node.inc

@@ -9,7 +9,7 @@
 /**
  *  Implementation of hook_node_info().
  *
- *  This hook provides information to drupal about any node types that are being
+ *  This hook provides information to Drupal about any node types that are being
  *  created by this module. If your module does not create any node types then
  *  this function is not required.
  *
@@ -30,22 +30,26 @@ function tripal_example_node_info() {
     'description' => t('A record from the fake chado example table'),
     'has_title'   => TRUE,
     'locked'      => TRUE,
-    // EXPLANATION: This section of the node type array specifies how Tripal will sync the node
-    // types with data in Chado. When Drupal creates a node it has no way of
-    // coordinating which node belongs to which record in Chado. Therefore,
-    // Tripal maintains tables in the Drupal schema that maps Drupal nodes
-    // to recrords in Chado.  Syncing is the process of creating Drupal nodes
-    // and linking them to the appropriate record.
+    // EXPLANATION: This section of the node type array specifies how Tripal
+    // will sync the node types with data in Chado. When Drupal creates a node
+    // it has no way of coordinating which node belongs to which record in
+    // Chado. Therefore, Tripal maintains tables in the Drupal schema that maps
+    // Drupal nodes to records in Chado. Syncing is the process of creating
+    // Drupal nodes and linking them to the appropriate record.
     'chado_node_api' => array(
-      'base_table' => 'example',       // the base table name (e.g. example, example, contact)
-      'hook_prefix' => 'chado_example',// the node type hook prefix
+      // the base table name (e.g. example, example, contact)
+      'base_table' => 'example',
+      // the node type hook prefix
+      'hook_prefix' => 'chado_example',
       'record_type_title' => array(
-        'singular' => t('Example'),    // how to refer to the record
-        'plural' => t('Examples')      // how to refer to the record in plurals
+        // how to refer to the record
+        'singular' => t('Example'),
+        // how to refer to the record in plurals
+        'plural' => t('Examples')
       ),
       'sync_filters' => array(
-        'type_id' => TRUE,             // if the record has a type_id set to TRUE
-        'organism_id' => TRUE          // if the record has an organism_id set to TRUE
+        'type_id' => TRUE,     // if the record has a type_id set to TRUE
+        'organism_id' => TRUE  // if the record has an organism_id set to TRUE
       ),
     )
   );
@@ -54,28 +58,26 @@ function tripal_example_node_info() {
 }
 
 /**
- * Implement hook_access().  This hook provides instructions to
- * drupal for which users can access the custom content types
- * created in the function above.  The available permissions
- * are set in the chado_example_permissions() hook in the
- * tripal_example.module file.  This hook is not needed
- * if no node types were defined in the hook_node_info() hook.
+ * Implement hook_access(). This hook provides instructions to Drupal for which
+ * users can access the custom content types created in the function above. The
+ * available permissions are set in the chado_example_permissions() hook in the
+ * tripal_example.module file. This hook is not needed if no node types were
+ * defined in the hook_node_info() hook.
  *
  * @return
- * This function should return null if it does not specificially
- * deny access. This allows for other mechanisms to to deny
- * or reject access. If the return value is TRUE then access
- * is granted regardless of any other rules that might be implemented
- * by other modules.
+ * This function should return null if it does not specifically deny access.
+ * This allows for other mechanisms to to deny or reject access. If the return
+ * value is TRUE then access is granted regardless of any other rules that might
+ * be implemented by other modules.
  */
 function chado_example_node_access($node, $op, $account) {
   $node_type = $node;
   if (is_object($node)) {
     $node_type = $node->type;
   }
-  // EXPLANATION:  in the tripal_example_permissions() function we
-  // created the permission types that are used here to check for
-  // access permissions to the 'chado_exmaple' node type.
+  // EXPLANATION:  in the tripal_example_permissions() function we created the
+  // permission types that are used here to check for access permissions to the
+  // 'chado_exmaple' node type.
   if($node_type == 'chado_example') {
     if ($op == 'create') {
       if (!user_access('create chado_example content', $account)) {
@@ -111,37 +113,38 @@ function chado_example_node_access($node, $op, $account) {
  */
 function chado_example_form($node, &$form_state) {
 
-  // EXPLANATION: This function should construct a form array that is used
-  // by Drupal to contruct a form for inserting or editing our new node type.
+  // EXPLANATION: This function should construct a form array that is used by
+  // Drupal to construct a form for inserting or editing our new node type.
   // See this page for information about the Form API:
   // https://api.drupal.org/api/drupal/includes!form.inc/group/form_api/7
   //
   // The code below is laid out in the following order
   // 1) Set default values
   // 2) Add form elements used by this node type
-  // 3) Use the Tripal API to add form elemetns for properties,
+  // 3) Use the Tripal API to add form elements for properties,
   //    dbxref's and relationships
   //
-  // For the example code below we assume that the fake 'example' table
-  // only has a uniquename, organism_id, type_id and example_id.
+  // For the example code below we assume that the fake 'example' table only has
+  // a uniquename, organism_id, type_id and example_id.
 
   $form = array();
 
   // Default values can come in the following ways:
   //
-  // 1) as elements of the $node object.  This occurs when editing an existing example
-  // 2) in the $form_state['values'] array which occurs on a failed validation or
-  //    ajax callbacks from non submit form elements
-  // 3) in the $form_state['input'[ array which occurs on ajax callbacks from submit
-  //    form elements and the form is being rebuilt
+  // 1) as elements of the $node object. This occurs when editing an existing
+  //    example
+  // 2) in the $form_state['values'] array which occurs on a failed validation
+  //    or ajax callbacks from non submit form elements
+  // 3) in the $form_state['input'[ array which occurs on ajax callbacks from
+  //    submit form elements and the form is being rebuilt
   //
   // set form field defaults
 
 
   // SET FORM DEFAULTS
   //---------------------------------------------
-  $example      = null;   // holds the example object record
-  $example_id   = null;   // when editing an example record we'll have an example_id
+  $example      = null; // holds the example object record
+  $example_id   = null; // when editing an example record we'll have an example_id
 
   // initialize the defaults for the form fields
   $uniquename   = '';
@@ -164,8 +167,8 @@ function chado_example_form($node, &$form_state) {
       '#value' => $example_id,
     );
   }
-  // if we are re constructing the form from a failed validation or ajax callback
-  // then use the $form_state['values'] values
+  // if we are re constructing the form from a failed validation or ajax
+  // callback then use the $form_state['values'] values
   if (array_key_exists('values', $form_state)) {
      $uniquename   = $form_state['values']['uniquename'];
      $example_type = $form_state['values']['example_type'];
@@ -188,12 +191,12 @@ function chado_example_form($node, &$form_state) {
     '#title' => t('Unique Name'),
     '#required' => TRUE,
     '#default_value' => $uniquename,
-    '#description' => t('Enter a unique name for this example.  This name must be unique.'),
+    '#description' => t('Enter a unique name for this example. This name must be unique.'),
     '#maxlength' => 255
   );
 
-  // for the type_id we want to use the default vocabulary so that this
-  // field can have autocomplete functionality
+  // for the type_id we want to use the default vocabulary so that this field
+  // can have auto-complete functionality
   $type_cv = tripal_get_default_cv('example', 'type_id');
   $cv_id = $type_cv->cv_id;
   $form['example_type'] = array(
@@ -226,43 +229,58 @@ function chado_example_form($node, &$form_state) {
 
   // PROPERTIES FORM
   //---------------------------------------------
-  // If there is a exampleprop table and you want to allow users to add/remove entries
-  // from it through your node form then add this section to your own node form
+  // If there is a exampleprop table and you want to allow users to add/remove
+  // entries from it through your node form then add this section to your own
+  // node form
   $prop_cv = tripal_get_default_cv('exampleprop', 'type_id');
   $cv_id = $prop_cv ? $prop_cv->cv_id : NULL;
   $details = array(
-    'property_table' => 'exampleprop',      // the name of the prop table
-    'chado_id' => $example_id,              // the value of example_id for this record
-    'cv_id' => $cv_id                       // the cv.cv_id of the cv governing exampleprop.type_id
+    // the name of the prop table
+    'property_table' => 'exampleprop',
+    // the value of example_id for this record
+    'chado_id' => $example_id,
+    // the cv.cv_id of the cv governing exampleprop.type_id
+    'cv_id' => $cv_id
   );
   // Adds the form elements to your current form
   chado_add_node_form_properties($form, $form_state, $details);
 
   // ADDITIONAL DBXREFS FORM
   //---------------------------------------------
-  // If there is a example_dbxref table and you want to allow users to add/remove entries
-  // from it through your node form then add this section to your own node form
+  // If there is a example_dbxref table and you want to allow users to
+  // add/remove entries from it through your node form then add this section to
+  // your own node form
   $details = array(
-    'linking_table' => 'example_dbxref',  // the name of the _dbxref table
-    'base_foreign_key' => 'example_id',   // the name of the key in your base chado table
-    'base_key_value' => $example_id       // the value of example_id for this record
+    // the name of the _dbxref table
+    'linking_table' => 'example_dbxref',
+    // the name of the key in your base chado table
+    'base_foreign_key' => 'example_id',
+    // the value of example_id for this record
+    'base_key_value' => $example_id
   );
   // Adds the form elements to your current form
   chado_add_node_form_dbxrefs($form, $form_state, $details);
 
   // RELATIONSHIPS FORM
   //---------------------------------------------
-  // If there is a example_relationship table and you want to allow users to add/remove entries
-  // from it through your node form then add this section to your own node form
+  // If there is a example_relationship table and you want to allow users to
+  // add/remove entries from it through your node form then add this section to
+  // your own node form
   $rels_cv = tripal_get_default_cv('example_relationship', 'type_id');
   $cv_id = $rels_cv ? $rels_cv->cv_id : NULL;
   $details = array(
-    'relationship_table' => 'example_relationship', // the name of the _relationship table
-    'base_table' => 'example',                      // the name of your chado base table
-    'base_foreign_key' => 'example_id',             // the name of the key in your base chado table
-    'base_key_value' => $example_id,                // the value of example_id for this record
-    'nodetype' => 'example',                        // the human-readable name of your node type
-    'cv_id' => $cv_id                               // the cv.cv_id of the cv governing example_relationship.type_id
+    // the name of the _relationship table
+    'relationship_table' => 'example_relationship',
+    // the name of your chado base table
+    'base_table' => 'example',
+    // the name of the key in your base chado table
+    'base_foreign_key' => 'example_id',
+    // the value of example_id for this record
+    'base_key_value' => $example_id,
+    // the human-readable name of your node type
+    'nodetype' => 'example',
+    // the cv.cv_id of the cv governing example_relationship.type_id
+    'cv_id' => $cv_id
   );
   // Adds the form elements to your current form
   chado_add_node_form_relationships($form, $form_state, $details);
@@ -274,14 +292,14 @@ function chado_example_form($node, &$form_state) {
 /**
  * Implementation of hook_validate
  *
- * This function validates a form prior to insert or update. If an error
- * is detected, it sets the error using form_set_error() which takes the
- * user back to the form to make corrections.
+ * This function validates a form prior to insert or update. If an error is
+ * detected, it sets the error using form_set_error() which takes the user back
+ * to the form to make corrections.
  *
  * This validation is being used for three activities:
- *   CASE A: Update a node that exists in both drupal and chado
- *   CASE B: Synchronizing a node from chado to drupal
- *   CASE C: Inserting a new node that exists in niether drupal nor chado
+ *   CASE A: Update a node that exists in both Drupal and Chado
+ *   CASE B: Synchronizing a node from Chado to Drupal
+ *   CASE C: Inserting a new node that exists in neither Drupal nor Chado
  *
  * @param $node
  *
@@ -294,19 +312,19 @@ function chado_example_validate($node, $form, &$form_state) {
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
   // without the proper values.
-  if($node->op != 'Save') {
+  if(property_exists($node, "op") and $node->op != 'Save') {
     return;
   }
 
-  // we are syncing if we do not have a node ID but we do have a example_id. We don't
-  // need to validate during syncing so just skip it.
-  if (is_null($node->nid) and property_exists($node, 'example_id') and $node->example_id != 0) {
+  // we are syncing if we do not have a node ID but we do have a example_id. We
+  // don't need to validate during syncing so just skip it.
+  if (!property_exists($node, 'nid') and property_exists($node, 'example_id') and $node->example_id != 0) {
     return;
   }
 
   // be sure to always trim text fields
-  $node->uniquename   = trim($node->uniquename);
-  $node->description  = trim($node->description);
+  $node->uniquename   = property_exists($node, 'uniquename') ? trim($node->uniquename) : '';
+  $node->description  = property_exists($node, 'description') ? trim($node->description) : '';
 
   // Validating for an update. If the 'nid' property is present in the node then
   // this is an update and validation can be different for updates
@@ -322,8 +340,8 @@ function chado_example_validate($node, $form, &$form_state) {
       form_set_error('feature_type', t("The feature type is not a valid name from the Sequence Ontology."));
     }
 
-    // TODO: also we should check that the unique constraint is not invalidated by
-    // changing either the type_id, organism_id or uniquename.
+    // TODO: also we should check that the unique constraint is not invalidated
+    // by changing either the type_id, organism_id or uniquename.
   }
   // Validating for an insert
   else {
@@ -342,14 +360,14 @@ function chado_example_validate($node, $form, &$form_state) {
 }
 
 /**
- *  Implementation of hook_insert(). This function is called after the
- *  node is inserted into the database. We need it so that we can insert
- *  appropriate fields as provided by the user into the database. And so that
- *  we can link the new Drupal node to the data in Chado via the chado_example
- *  linking table. We can get to this function also during "syncing".
- *  With syncing, however, the data already exists in Chado and we do not want
- *  to try to re-add it. But we do need to add an entry to the chado_example table
- *  to link the Drupal node with the data in the 'example' table of Chado.
+ *  Implementation of hook_insert(). This function is called after the node is
+ * inserted into the database. We need it so that we can insert appropriate
+ * fields as provided by the user into the database. And so that we can link the
+ * new Drupal node to the data in Chado via the chado_example linking table. We
+ * can get to this function also during "syncing".
+ * With syncing, however, the data already exists in Chado and we do not want
+ * to try to re-add it. But we do need to add an entry to the chado_example
+ * table to link the Drupal node with the data in the 'example' table of Chado.
  *
  *  This function is not required if the hook_node_info() does not define
  *  any custom node types.
@@ -357,22 +375,25 @@ function chado_example_validate($node, $form, &$form_state) {
  * @ingroup tripal_example
  */
 function chado_example_insert($node) {
-  // be sure to always trim text fields
-  $node->uniquename   = trim($node->uniquename);
-  $node->description  = trim($node->description);
 
-  // get the example type record
-  $type_cv = tripal_get_default_cv('example', 'type_id');
-  $type = tripal_get_cvterm(array(
-    'name' => $node->example_type,
-    'cv_id' => $type_cv->cv_id,
-  ));
+  $example_id = '';
 
   // if there is an example_id in the $node object then this must be a sync so
-  // we can skip adding the example as it is already there, although
-  // we do need to proceed with the rest of the insert
+  // we can skip adding the example as it is already there, although we do need
+  // to proceed with insertion into the chado/drupal linking table.
   if (!property_exists($node, 'example_id')) {
 
+    // be sure to always trim text fields
+    $node->uniquename   = trim($node->uniquename);
+    $node->description  = trim($node->description);
+
+    // get the example type record
+    $type_cv = tripal_get_default_cv('example', 'type_id');
+    $type = tripal_get_cvterm(array(
+        'name' => $node->example_type,
+        'cv_id' => $type_cv->cv_id,
+    ));
+
     // perform the insert using the chado_insert_record function();
     $values = array(
       'uniquename' => $node->uniquename,
@@ -391,39 +412,51 @@ function chado_example_insert($node) {
     // get the example_id for linking Drupal node with Chado data
     $example_id = $example['example_id'];
 
-    // Only add to other chado tables if the base record was inserted properly
+    // Only add to other Chado tables if the base record was inserted properly
     if ($example_id > 0) {
 
-      // If you implemented the properties form in chado_example_form then you need to
-      // handle inserting these properties into your chado prop table.
+      // If you implemented the properties form in chado_example_form then you
+      // need to handle inserting these properties into your Chado prop table.
       $details = array(
-        'property_table'   => 'exampleprop',   // the name of the prop table
-        'base_table'       => 'example',       // the name of your chado base table
-        'foreignkey_name'  => 'example_id',    // the name of the key in your base table
-        'foreignkey_value' => $example_id      // the value of the example_id key
+        // the name of the prop table
+        'property_table'   => 'exampleprop',
+        // the name of your Chado base table
+        'base_table'       => 'example',
+        // the name of the key in your base table
+        'foreignkey_name'  => 'example_id',
+        // the value of the example_id key
+        'foreignkey_value' => $example_id
       );
       chado_update_node_form_properties($node, $details);
 
-      // If you implemented the dbxrefs form in chado_example_form then you need to
-      // handle inserting these database references into your chado _dbxref table.
+      // If you implemented the dbxrefs form in chado_example_form then you need
+      // to handle inserting these database references into your Chado _dbxref
+      // table.
       $details = array(
-        'linking_table'    => 'example_dbxref', // the name of your _dbxref table
-        'foreignkey_name'  => 'example_id',     // the name of the key in your base table
-        'foreignkey_value' => $example_id       // the value of the example_id key
+        // the name of your _dbxref table
+        'linking_table'    => 'example_dbxref',
+        // the name of the key in your base table
+        'foreignkey_name'  => 'example_id',
+        // the value of the example_id key
+        'foreignkey_value' => $example_id
       );
       chado_update_node_form_dbxrefs($node, $details);
 
-      // If you implemented the relationships form in chado_example_form then you need to
-      // handle inserting these relationships into your chado _relationship table.
+      // If you implemented the relationships form in chado_example_form then
+      // you need to handle inserting these relationships into your Chado
+      // _relationship table.
       $details = array(
-        'relationship_table' => 'example_relationship',  // name of the _relationship table
-        'foreignkey_value' => $example_id                // value of the example_id key
+        // name of the _relationship table
+        'relationship_table' => 'example_relationship',
+        // value of the example_id key
+        'foreignkey_value' => $example_id
       );
       chado_update_node_form_relationships($node, $details);
     }
   }
   else {
-    // the node has an example_id so get it for linking Drupal node with Chado data
+    // the node has an example_id so get it for linking Drupal node with Chado
+    // data
     $example_id = $node->example_id;
   }
 
@@ -440,12 +473,11 @@ function chado_example_insert($node) {
 }
 
 /**
- * Implementation of hook_update().  This function runs after the
- * node has been inserted into the Drupal schema and allows us to
- * update the record in Chado.
+ * Implementation of hook_update(). This function runs after the node has been
+ * inserted into the Drupal schema and allows us to update the record in Chado.
  *
- *  This function is not required if the hook_node_info() does not define
- *  any custom node types.
+ * This function is not required if the hook_node_info() does not define any
+ * custom node types.
  *
  * @ingroup tripal_example
  */
@@ -470,41 +502,44 @@ function chado_example_update($node) {
       array('%values' => print_r($values, TRUE)));
   }
 
-  // If you implemented the properties form in chado_example_form then you need to
-  // handle updating these properties into your chado prop table.
+  // If you implemented the properties form in chado_example_form then you need
+  // to handle updating these properties into your Chado prop table.
   $details = array(
-    'property_table' => 'exampleprop',   // the name of the prop table
-    'base_table' => 'example',           // the name of your chado base table
-    'foreignkey_name' => 'example_id',   // the name of the key in your base table
-    'foreignkey_value' => $example_id    // the value of the example_id key
+    'property_table' => 'exampleprop', // the name of the prop table
+    'base_table' => 'example',         // the name of your Chado base table
+    'foreignkey_name' => 'example_id', // the name of the key in your base table
+    'foreignkey_value' => $example_id  // the value of the example_id key
   );
   chado_update_node_form_properties($node, $details);
 
   // If you implemented the dbxrefs form in chado_example_form then you need to
-  // handle updating these database references into your chado _dbxref table.
+  // handle updating these database references into your Chado _dbxref table.
   $details = array(
-    'linking_table' => 'example_dbxref',   // the name of your _dbxref table
-    'foreignkey_name' => 'example_id',     // the name of the key in your base table
-    'foreignkey_value' => $example_id      // the value of the example_id key
+    'linking_table' => 'example_dbxref', // the name of your _dbxref table
+    'foreignkey_name' => 'example_id',   // the name of the key in your base table
+    'foreignkey_value' => $example_id    // the value of the example_id key
   );
   chado_update_node_form_dbxrefs($node, $details);
 
-  // If you implemented the relationships form in chado_example_form then you need to
-  // handle updating these relationships into your chado _relationship table.
+  // If you implemented the relationships form in chado_example_form then you
+  // need to handle updating these relationships into your Chado _relationship
+  // table.
   $details = array(
-    'relationship_table' => 'example_relationship',  // name of the _relationship table
-    'foreignkey_value' => $example_id                // value of the example_id key
+    // name of the _relationship table
+    'relationship_table' => 'example_relationship',
+    // value of the example_id key
+    'foreignkey_value' => $example_id
   );
   chado_update_node_form_relationships($node, $details);
 
 }
 /**
- * Implementation of hook_delete().  This function runs after the
- * node has been deleted from the Drupal schema and allows us to
- * delete the corresponding recrod in Chado.
+ * Implementation of hook_delete(). This function runs after the node has been
+ * deleted from the Drupal schema and allows us to delete the corresponding
+ * record in Chado.
  *
- * This function is not required if the hook_node_info() does not define
- * any custom node types.
+ * This function is not required if the hook_node_info() does not define any
+ * custom node types.
  *
  * @ingroup tripal_example
  */
@@ -513,18 +548,18 @@ function chado_example_delete($node) {
   // get the example id from the node
   $example_id  = chado_get_id_from_nid('example', $node->nid);
 
-  // if we don't have a example id for this node then this isn't a node of
-  // type chado_example or the entry in the chado_example table was lost.
+  // if we don't have a example id for this node then this isn't a node of type
+  // chado_example or the entry in the chado_example table was lost.
   if (!$example_id) {
     return;
   }
 
   // remove the entry in the chado_exapmle table linking the deleted
-  // Drupal node with the data in chado
+  // Drupal node with the data in Chado
   $sql_del = "DELETE FROM {chado_example} WHERE nid = :nid AND vid = :vid";
   db_query($sql_del, array(':nid' => $node->nid, ':vid' => $node->vid));
 
-  // Remove data from example tables of chado database.  This will
+  // Remove data from example tables of Chado database. This will
   // cause a cascade delete and remove all data in referencing tables
   // for this example
   chado_query("DELETE FROM {example} WHERE example_id = :example_id", array(':example_id' => $example_id));
@@ -535,25 +570,25 @@ function chado_example_delete($node) {
 }
 
 /**
- * Implementation of hook_load().  This function is necessary to load
- * into the $node object the fields of the table form Chado. For example
- * for the example table, the chado_example_load() function adds in
- * a example object which contains all of the fields and sub objects
- * for data in tables with foreign key relationships.
+ * Implementation of hook_load(). This function is necessary to load into the
+ * $node object the fields of the table form Chado. For example for the example
+ * table, the chado_example_load() function adds in a example object which
+ * contains all of the fields and sub objects for data in tables with foreign
+ * key relationships.
  *
- * This function is not required if the hook_node_info() does not define
- * any custom node types.
+ * This function is not required if the hook_node_info() does not define any
+ * custom node types.
  *
  * @ingroup tripal_example
  */
 function chado_example_load($nodes) {
 
   // EXPLANATION: when displaying or node or accessing the node in a template
-  // we need the data from Chado.  This fucntion finds the record in Chado that
+  // we need the data from Chado. This function finds the record in Chado that
   // this node belongs to and adds the record.
 
-  // there may be multiple nodes that get passed in so we have to iterate through
-  // them all
+  // there may be multiple nodes that get passed in so we have to iterate
+  // through them all
   foreach ($nodes as $nid => $node) {
     // find the example and add in the details
     $example_id = chado_get_id_from_nid('example', $nid);
@@ -568,20 +603,21 @@ function chado_example_load($nodes) {
     $values = array('example_id' => $example_id);
     $example = chado_generate_var('example', $values);
 
-    // for fields in the table that are of type 'text' you may want to include those
-    // by default, the chado_generate_var does not include text fields as
-    // they may be very large and including a large text field can slow the page load.
+    // for fields in the table that are of type 'text' you may want to include
+    // those by default, the chado_generate_var does not include text fields as
+    // they may be very large and including a large text field can slow the page
+    // load.
     // If you know a text field will never be large and it is important for the
     // other functions that will see the node to have access to a field you can
-    // include it here using the chado_expand_var() function.  In most
-    // cases it is probably best to let the end-user decide if text fields should
-    // be included by using this function in the templates.
+    // include it here using the chado_expand_var() function. In most
+    // cases it is probably best to let the end-user decide if text fields
+    // should be included by using this function in the templates.
     $example = chado_expand_var($example, 'field', 'example.description');
 
 
-    // If your module is using the Chado Node: Title & Path API to allow custom titles
-    // for your node type. Every time you want the title of the node, you need to use the
-    // following API function:
+    // If your module is using the Chado Node: Title & Path API to allow custom
+    // titles for your node type. Every time you want the title of the node, you
+    // need to use the following API function:
     $node->title = chado_get_node_title($node);
 
     // add the new example object to this node.
@@ -598,24 +634,24 @@ function chado_example_load($nodes) {
  */
 function tripal_example_node_presave($node) {
 
-  // EXPLANATION: This node is useful for
-  // making changes to the node prior to it being saved to the database.
+  // EXPLANATION: This node is useful for making changes to the node prior to it
+  // being saved to the database.
   // One useful case for this is to set the title of a node using values
   // supplied by the user.
   //
-  // This function is not required. You probably won't need it if you
-  //  don't define a custom node type in the hook_node_info() function. But
-  // it is node type agnostic, so you can use this function to change the
-  // contents of any node regardless of it's type.
+  // This function is not required. You probably won't need it if you don't
+  // define a custom node type in the hook_node_info() function. But it is node
+  // type agnostic, so you can use this function to change the contents of any
+  // node regardless of it's type.
 
   // set the node title
   switch ($node->type) {
-    // This step is for setting the title for the Drupal node.  This title
-    // is permanent and thus is created to be unique.  Title changes provided
-    // by tokens are generated on the fly dynamically, but the node title
-    // seen in the content listing needs to be set here. Do not call
-    // the chado_get_node_title() function here to set the title as the node
-    // object isn't properly filled out and the function will fail.
+    // This step is for setting the title for the Drupal node. This title is
+    // permanent and thus is created to be unique. Title changes provided by
+    // tokens are generated on the fly dynamically, but the node title seen in
+    // the content listing needs to be set here. Do not call the
+    // chado_get_node_title() function here to set the title as the node object
+    // isn't properly filled out and the function will fail.
     case 'chado_example':
       // for a form submission the 'uniquename' field will be set,
       // for a sync, we must pull from the example object
@@ -639,24 +675,23 @@ function tripal_example_node_presave($node) {
  */
 function tripal_example_node_insert($node) {
 
-  // EXPLANATION: This function is used
-  // after any a node is inserted into the database.  It is different
-  // from the hook_insert() function above in that it is called after
-  // any node is saved, regardlesss of it's type. This function is useful
-  // for making changes to the database after a node is inserted.
-  // An example comes from the tripal_feature module where the URL alias
-  // of a node cannot be set in the hook_insert() function. Therefore
-  // the tripal_feature module uses this function to set the url path
-  // of a newly inserted example node.
+  // EXPLANATION: This function is used after any a node is inserted into the
+  // database. It is different from the hook_insert() function above in that it
+  // is called after any node is saved, regardless of it's type. This function
+  // is useful for making changes to the database after a node is inserted.
+  // An example comes from the tripal_feature module where the URL alias of a
+  // node cannot be set in the hook_insert() function. Therefore the
+  // tripal_feature module uses this function to set the URL path of a newly
+  // inserted example node.
   //
-  // This function is not required. You probably won't need it if you
-  // don't define a custom node type in the hook_node_info() function. But
-  // it is node type agnostic, so you can use this function to do any
-  // activity after insert of any node.
-
-  // the Example code below will set the URL path after inserting.  We do it
-  // here because we do not know the example_id in the presave and cannot do
-  // it in the hook_insert()
+  // This function is not required. You probably won't need it if you don't
+  // define a custom node type in the hook_node_info() function. But it is node
+  // type agnostic, so you can use this function to do any activity after insert
+  // of any node.
+
+  // the Example code below will set the URL path after inserting. We do it here
+  // because we do not know the example_id in the pre-save and cannot do it in
+  // the hook_insert()
   switch ($node->type) {
     case 'chado_example':
 
@@ -668,17 +703,17 @@ function tripal_example_node_insert($node) {
       $example = chado_generate_var('example', $values);
       $node->example = $example;
 
-      // If your module is using the 'Chado Node: Title & Path API' to allow custom titles
-      // for your node type. Every time you want the title of the node, you need to use the
-      // following API function:
+      // If your module is using the 'Chado Node: Title & Path API' to allow
+      // custom titles for your node type. Every time you want the title of the
+      // node, you need to use the following API function:
       $example->title = chado_get_node_title($node);
 
       // set the URL for this example page
-      // see the code in the tripal_feature/includes/tripal_feature.chado_node.inc file
-      // in the function tripal_feature_node_insert for an example of how that
-      // module sets the URL.  It uses a configuration file to allow the user
-      // to dynmically build a URL schema and then uses that schema to generate
-      // a URL string.
+      // see the code in the tripal_feature/includes/tripal_feature.chado_node.inc
+      // file in the function tripal_feature_node_insert for an example of how
+      // that module sets the URL. It uses a configuration file to allow the
+      // user to dynamically build a URL schema and then uses that schema to
+      // generate a URL string.
       break;
   }
 }
@@ -691,35 +726,34 @@ function tripal_example_node_insert($node) {
  */
 function tripal_example_node_update($node) {
 
-  // EXPLANATION: This function is used
-  // after any a node is updated in the database.  It is different
-  // from the hook_update() function above in that it is called after
-  // any node is updated, regardlesss of it's type.
-  // An example comes from the tripal_feature module where the URL alias
-  // of a node cannot be set in the hook_update() function. Therefore
-  // the tripal_feature module uses this function to reset the url path
-  // of an updated feature node.
+  // EXPLANATION: This function is used after any a node is updated in the
+  // database. It is different from the hook_update() function above in that it
+  // is called after any node is updated, regardless of it's type.
+  // An example comes from the tripal_feature module where the URL alias of a
+  // node cannot be set in the hook_update() function. Therefore the
+  // tripal_feature module uses this function to reset the URL path of an
+  // updated feature node.
   //
-  // This function is not required. You probably won't need it if you
-  // don't define a custom node type in the hook_node_info() function. But
-  // it is node type agnostic, so you can use this function to do any
-  // activity after insert of a node.
+  // This function is not required. You probably won't need it if you don't
+  // define a custom node type in the hook_node_info() function. But it is node
+  // type agnostic, so you can use this function to do any activity after insert
+  // of a node.
 
   // add items to other nodes, build index and search results
   switch ($node->type) {
     case 'chado_example':
 
-      // If your module is using the Chado Node: Title & Path API to allow custom titles
-      // for your node type. Every time you want the title of the node, you need to use the
-      // following API function:
+      // If your module is using the Chado Node: Title & Path API to allow
+      // custom titles for your node type. Every time you want the title of the
+      // node, you need to use the following API function:
       $example->title = chado_get_node_title($node);
 
       // set the URL for this example page
-      // see the code in the tripal_feature/includes/tripal_feature.chado_node.inc file
-      // in the function tripal_feature_node_insert for an example of how that
-      // module sets the URL.  It uses a configuration file to allow the user
-      // to dynmically build a URL schema and then uses that schema to generate
-      // a URL string.
+      // see the code in the tripal_feature/includes/tripal_feature.chado_node.inc
+      // file in the function tripal_feature_node_insert for an example of how
+      // that module sets the URL. It uses a configuration file to allow the
+      // user to dynamically build a URL schema and then uses that schema to
+      // generate a URL string.
       break;
   }
 }
@@ -730,11 +764,11 @@ function tripal_example_node_update($node) {
  */
 function tripal_example_node_view($node, $view_mode, $langcode) {
 
-  // EXPLANATION: This function defines the content "blocks" that appear
-  // when thhe node is displayed. It is node type agnostic so we can add
-  // content to any node type.  So, we use this function to add the content
-  // from all of our theme templates onto our new node type. We will also
-  // use this function to add content to other node types.
+  // EXPLANATION: This function defines the content "blocks" that appear when
+  // the node is displayed. It is node type agnostic so we can add content to
+  // any node type. So, we use this function to add the content from all of our
+  // theme templates onto our new node type. We will also use this function to
+  // add content to other node types.
 
   switch ($node->type) {
     case 'chado_example':
@@ -742,24 +776,25 @@ function tripal_example_node_view($node, $view_mode, $langcode) {
       // supports full page view and teaser view.
       if ($view_mode == 'full') {
 
-        // If you want to use the default Tripal node template then you need to tell
-        // tripal to generate the Table of Contents. This is done by setting the following
-        // to TRUE. If your content type follows the chado_<base table> convention
-        // then this is the default. In this case if you don't want to use the default
-        // template then you need to set the following to FALSE.
+        // If you want to use the default Tripal node template then you need to
+        // tell Tripal to generate the Table of Contents. This is done by
+        // setting the following to TRUE. If your content type follows the
+        // chado_<base table> convention then this is the default. In this case
+        // if you don't want to use the default template then you need to set
+        // the following to FALSE.
         $node->content['#tripal_generic_node_template'] = TRUE;
 
-        // There is always a base template.  This is the template that
-        // is first shown when the example node type is first displayed.
-        // if you are using the default Tripal node template, then you should
+        // There is always a base template. This is the template that is first
+        // shown when the example node type is first displayed.
+        // If you are using the default Tripal node template, then you should
         // also set two additional items in each array:  tripal_toc_id and
-        // tripal_toc_title.  The tripal_tock_id should be a single unqiue
+        // tripal_toc_title. The tripal_tock_id should be a single unique
         // world that is used to reference the template. This ID is used for
-        // constructing URLs for the content.  The tripal_toc_title contains
+        // constructing URLs for the content. The tripal_toc_title contains
         // the title that should appear in the table of contents for this
-        // content.  You should only set the '#weight' element for the
-        // base template (or Overview) to ensure that it appears at the top of
-        // the list. Otherwise items are sorted alphabetically.
+        // content. You should only set the '#weight' element for the base
+        // template (or Overview) to ensure that it appears at the top of the
+        // list. Otherwise items are sorted alphabetically.
         $node->content['tripal_example_base'] = array(
           '#theme' => 'tripal_example_base',
           '#node' => $node,
@@ -788,11 +823,11 @@ function tripal_example_node_view($node, $view_mode, $langcode) {
           '#tripal_toc_title' => 'Relationships',
         );
 
-        // Note: if you create a template that you do not want a user to
-        // know where it is (discourage editing of it), you can add the following
-        // key:  '#tripal_template_show' => FALSE. If this key/value is set
-        // the the administrator message that Tripal provides indicating
-        // where the template is housed will not be shown.
+        // Note: if you create a template that you do not want a user to know
+        // where it is (discourage editing of it), you can add the following
+        // key:  '#tripal_template_show' => FALSE. If this key/value is set the
+        // administrator message that Tripal provides indicating where the
+        // template is housed will not be shown.
       }
       // set the content for the teaser view
       if ($view_mode == 'teaser') {
@@ -803,8 +838,8 @@ function tripal_example_node_view($node, $view_mode, $langcode) {
         );
       }
       break;
-    // you can add custom content to any node type by adding
-    // content to the node in the same way as above.
+    // you can add custom content to any node type by adding content to the node
+    // in the same way as above.
     case 'chado_organism':
       if ($view_mode == 'full') {
         $node->content['tripal_organism_examples'] = array(

+ 12 - 12
tripal_example/theme/templates/tripal_example_base.tpl.php

@@ -2,18 +2,18 @@
 $example  = $variables['node']->example;  ?>
 
 <div class="tripal_example-data-block-desc tripal-data-block-desc"></div> <?php
- 
-// the $headers array is an array of fields to use as the colum headers. 
-// additional documentation can be found here 
+
+// the $headers array is an array of fields to use as the column headers.
+// additional documentation can be found here
 // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
 // This table for the analysis has a vertical header (down the first column)
 // so we do not provide headers here, but specify them in the $rows array below.
 $headers = array();
 
 // the $rows array contains an array of rows where each row is an array
-// of values for each column of the table in that row.  Additional documentation
+// of values for each column of the table in that row. Additional documentation
 // can be found here:
-// https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7 
+// https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
 $rows = array();
 
 // Unique Name row
@@ -36,7 +36,7 @@ $rows[] = array(
 $organism = $example->organism_id->genus ." " . $example->organism_id->species ." (" . $example->organism_id->common_name .")";
 if (property_exists($example->organism_id, 'nid')) {
   $organism = l("<i>" . $example->organism_id->genus . " " . $example->organism_id->species . "</i> (" . $example->organism_id->common_name .")", "node/".$example->organism_id->nid, array('html' => TRUE));
-} 
+}
 $rows[] = array(
   array(
     'data' => 'Organism',
@@ -46,7 +46,7 @@ $rows[] = array(
 );
 
 // allow site admins to see the example ID
-if (user_access('view ids')) { 
+if (user_access('view ids')) {
   // Feature ID
   $rows[] = array(
     array(
@@ -62,9 +62,9 @@ if (user_access('view ids')) {
 }
 
 
-// the $table array contains the headers and rows array as well as other
-// options for controlling the display of the table.  Additional
-// documentation can be found here:
+// the $table array contains the headers and rows array as well as other options
+// for controlling the display of the table. Additional documentation can be
+// found here:
 // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
 $table = array(
   'header' => $headers,
@@ -79,7 +79,7 @@ $table = array(
   'empty' => '',
 );
 
-// once we have our table array structure defined, we call Drupal's theme_table()
-// function to generate the table.
+// once we have our table array structure defined, we call Drupal's
+// theme_table() function to generate the table.
 print theme_table($table); ?>
 <div style="text-align: justify"><?php print $example->description ?></div>

+ 16 - 15
tripal_example/theme/templates/tripal_example_properties.tpl.php

@@ -11,24 +11,25 @@ $exampleprops = $example->exampleprop;
 $properties = array();
 
 if (count($properties)) { ?>
-  <div class="tripal_example-data-block-desc tripal-data-block-desc">Additional details for this example include:</div> <?php 
+  <div class="tripal_example-data-block-desc tripal-data-block-desc">Additional details for this example include:</div> <?php
 
-  // the $headers array is an array of fields to use as the colum headers.
+  // the $headers array is an array of fields to use as the column headers.
   // additional documentation can be found here
   // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
   $headers = array('Property Name', 'Value');
-  
+
   // the $rows array contains an array of rows where each row is an array
-  // of values for each column of the table in that row.  Additional documentation
-  // can be found here:
+  // of values for each column of the table in that row. Additional
+  // documentation can be found here:
   // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
   $rows = array();
-  
+
   $keywords = array();
   foreach ($properties as $property) {
-    // each keyword is stored as a seperate properties. We want to show them
-    // only in a single field not as a bunc of individual properties, so when we see one, 
-    // save it in an array for later and down't add it yet to the table yet.
+    // each keyword is stored as a separate properties. We want to show them
+    // only in a single field not as a bunch of individual properties, so when
+    // we see one, save it in an array for later and don't add it yet to the
+    // table yet.
     if ($property->type_id->name == 'Keywords') {
       $keywords[] = $property->value;
       continue;
@@ -44,11 +45,11 @@ if (count($properties)) { ?>
       'Keywords',
       implode(', ', $keywords),
     );
-  } 
+  }
 
   // the $table array contains the headers and rows array as well as other
-  // options for controlling the display of the table.  Additional
-  // documentation can be found here:
+  // options for controlling the display of the table. Additional documentation
+  // can be found here:
   // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
   $table = array(
     'header' => $headers,
@@ -62,8 +63,8 @@ if (count($properties)) { ?>
     'colgroups' => array(),
     'empty' => '',
   );
-  
-  // once we have our table array structure defined, we call Drupal's theme_table()
-  // function to generate the table.
+
+  // once we have our table array structure defined, we call Drupal's
+  // theme_table() function to generate the table.
   print theme_table($table);
 }

+ 14 - 13
tripal_example/theme/templates/tripal_example_references.tpl.php

@@ -1,36 +1,37 @@
 <?php
 $example = $variables['node']->example;
 
-// expand the example object to include the records from the example_dbxref table
+// expand the example object to include the records from the example_dbxref
+// table
 $options = array('return_array' => 1);
 $example = chado_expand_var($example, 'table', 'example_dbxref', $options);
 $example_dbxrefs = $example->example_dbxref;
 
 $references = array();
 if (count($example_dbxrefs) > 0 ) {
-  foreach ($example_dbxrefs as $example_dbxref) {    
+  foreach ($example_dbxrefs as $example_dbxref) {
     $references[] = $example_dbxref->dbxref_id;
   }
 }
 
 if(count($references) > 0){ ?>
-  <div class="tripal_example-data-block-desc tripal-data-block-desc">This example is also available in the following databases:</div><?php 
-  
+  <div class="tripal_example-data-block-desc tripal-data-block-desc">This example is also available in the following databases:</div><?php
+
   // the $headers array is an array of fields to use as the colum headers.
   // additional documentation can be found here
   // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
   $headers = array('Database', 'Accession');
-  
+
   // the $rows array contains an array of rows where each row is an array
-  // of values for each column of the table in that row.  Additional documentation
-  // can be found here:
+  // of values for each column of the table in that row. Additional
+  // documentation can be found here:
   // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
   $rows = array();
-  
+
   foreach ($references as $dbxref){
     $database = $dbxref->db_id->name . ': ' . $dbxref->db_id->description;
     if ($dbxref->db_id->url) {
-      $database = l($dbxref->db_id->name, $dbxref->db_id->url, array('attributes' => array('target' => '_blank'))) . ': ' . $dbxref->db_id->description; 
+      $database = l($dbxref->db_id->name, $dbxref->db_id->url, array('attributes' => array('target' => '_blank'))) . ': ' . $dbxref->db_id->description;
     }
     $accession = $dbxref->db_id->name . ':' . $dbxref->accession;
     if ($dbxref->db_id->urlprefix) {
@@ -39,15 +40,15 @@ if(count($references) > 0){ ?>
     if (property_exists($dbxref, 'is_primary')) {
       $accession .= " <i>(primary cross-reference)</i>";
     }
-    
+
     $rows[] = array(
       $database,
       $accession
     );
   }
   // the $table array contains the headers and rows array as well as other
-  // options for controlling the display of the table.  Additional
-  // documentation can be found here:
+  // options for controlling the display of the table. Additional documentation
+  // can be found here:
   // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
   $table = array(
     'header' => $headers,
@@ -61,7 +62,7 @@ if(count($references) > 0){ ?>
     'colgroups' => array(),
     'empty' => '',
   );
-  
+
   // once we have our table array structure defined, we call Drupal's theme_table()
   // function to generate the table.
   print theme_table($table);

+ 43 - 42
tripal_example/theme/templates/tripal_example_relationships.tpl.php

@@ -1,20 +1,21 @@
 <?php
 /* Typically in a Tripal template, the data needed is retrieved using a call to
- * chado_expand_var function.  For example, to retrieve all 
- * of the example relationships for this node, the following function call would be made:
- * 
+ * chado_expand_var function. For example, to retrieve all of the example
+ * relationships for this node, the following function call would be made:
+ *
  *   $example = chado_expand_var($example,'table','example_relationship');
- * 
- * However, this function call can be extremely slow when there are numerous relationships.
- * This is because the chado_expand_var function is recursive and expands 
- * all data following the foreign key relationships tree.  Therefore, to speed retrieval
- * of data, a special variable is provided to this template:
- * 
+ *
+ * However, this function call can be extremely slow when there are numerous
+ * relationships. This is because the chado_expand_var function is recursive and
+ * expands all data following the foreign key relationships tree. Therefore, to
+ * speed retrieval of data, a special variable is provided to this template:
+ *
  *   $example->all_relationships;
- *   
- * This variable is an array with two sub arrays with the keys 'object' and 'subject'.  The array with
- * key 'object' contains relationships where the example is the object, and the array with
- * the key 'subject' contains relationships where the example is the subject
+ *
+ * This variable is an array with two sub arrays with the keys 'object' and
+ * 'subject'. The array with key 'object' contains relationships where the
+ * example is the object, and the array with the key 'subject' contains
+ * relationships where the example is the subject.
  */
 $example = $variables['node']->example;
 
@@ -24,30 +25,30 @@ $subject_rels = $all_relationships['subject'];
 
 if (count($object_rels) > 0 or count($subject_rels) > 0) { ?>
   <div class="tripal_example-data-block-desc tripal-data-block-desc"></div> <?php
-  
-  // first add in the subject relationships.  
+
+  // first add in the subject relationships.
   foreach ($subject_rels as $rel_type => $rels){
     foreach ($rels as $obj_type => $objects){ ?>
       <p>This <?php print $example->type_id->name;?> is <?php print $rel_type ?> the following <b><?php print $obj_type ?></b> example(s): <?php
-       
+
       // the $headers array is an array of fields to use as the colum headers.
       // additional documentation can be found here
       // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
       $headers = array('Publication');
-      
+
       // the $rows array contains an array of rows where each row is an array
-      // of values for each column of the table in that row.  Additional documentation
-      // can be found here:
+      // of values for each column of the table in that row. Additional
+      // documentation can be found here:
       // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
       $rows = array();
-      
+
       foreach ($objects as $object){
         // link the example to it's node
         $title = $object->record->object_id->title;
         if (property_exists($object->record, 'nid')) {
           $title = l($title, "node/" . $object->record->nid, array('attributes' => array('target' => "_blank")));
         }
-        
+
         // get the citation
         $values = array(
           'example_id' => $object->record->object_id->example_id,
@@ -57,13 +58,13 @@ if (count($object_rels) > 0 or count($subject_rels) > 0) { ?>
         );
         $citation = chado_generate_var('exampleprop', $values);
         $citation = chado_expand_var($citation, 'field', 'exampleprop.value');
-        
+
         $rows[] = array(
           $title . '<br>' . htmlspecialchars($citation->value),
-        ); 
-       } 
+        );
+       }
        // the $table array contains the headers and rows array as well as other
-       // options for controlling the display of the table.  Additional
+       // options for controlling the display of the table. Additional
        // documentation can be found here:
        // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
        $table = array(
@@ -78,37 +79,37 @@ if (count($object_rels) > 0 or count($subject_rels) > 0) { ?>
          'colgroups' => array(),
          'empty' => '',
        );
-       
-       // once we have our table array structure defined, we call Drupal's theme_table()
-       // function to generate the table.
+
+       // once we have our table array structure defined, we call Drupal's
+       // theme_table() function to generate the table.
        print theme_table($table); ?>
        </p>
        <br><?php
      }
   }
-  
-  // second add in the object relationships.  
+
+  // second add in the object relationships.
   foreach ($object_rels as $rel_type => $rels){
     foreach ($rels as $subject_type => $subjects){?>
-      <p>The following <b><?php print $subjects[0]->record->subject_id->type_id->name ?></b> example(s) are <?php print $rel_type ?> this <?php print $example->type_id->name;?>: <?php 
+      <p>The following <b><?php print $subjects[0]->record->subject_id->type_id->name ?></b> example(s) are <?php print $rel_type ?> this <?php print $example->type_id->name;?>: <?php
       // the $headers array is an array of fields to use as the colum headers.
       // additional documentation can be found here
       // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
       $headers = array('Publication');
-      
+
       // the $rows array contains an array of rows where each row is an array
-      // of values for each column of the table in that row.  Additional documentation
-      // can be found here:
+      // of values for each column of the table in that row. Additional
+      // documentation can be found here:
       // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
       $rows = array();
-      
+
       foreach ($subjects as $subject){
         // link the example to it's node
         $title = $subject->record->subject_id->title;
         if (property_exists($subject->record, 'nid')) {
           $title = l($title, "node/" . $subject->record->nid, array('attributes' => array('target' => "_blank")));
         }
-        
+
         // get the citation
         $values = array(
           'example_id' => $subject->record->subject_id->example_id,
@@ -118,13 +119,13 @@ if (count($object_rels) > 0 or count($subject_rels) > 0) { ?>
         );
         $citation = chado_generate_var('exampleprop', $values);
         $citation = chado_expand_var($citation, 'field', 'exampleprop.value');
-        
+
         $rows[] = array(
           $title . '<br>' . htmlspecialchars($citation->value),
         );
-       } 
+       }
        // the $table array contains the headers and rows array as well as other
-       // options for controlling the display of the table.  Additional
+       // options for controlling the display of the table. Additional
        // documentation can be found here:
        // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
        $table = array(
@@ -139,9 +140,9 @@ if (count($object_rels) > 0 or count($subject_rels) > 0) { ?>
          'colgroups' => array(),
          'empty' => '',
        );
-       
-       // once we have our table array structure defined, we call Drupal's theme_table()
-       // function to generate the table.
+
+       // once we have our table array structure defined, we call Drupal's
+       // theme_table() function to generate the table.
        print theme_table($table); ?>
        </p>
        <br><?php

+ 20 - 19
tripal_example/theme/tripal_example.theme.inc

@@ -2,40 +2,41 @@
 
 /**
  * @file
- * 
- * This file should contain all Drupal hooks for theming content.  For templates 
+ *
+ * This file should contain all Drupal hooks for theming content. For templates
  * that need specific the hook_preprocess functions should be included here
  *
  */
 
 /**
  * implementation of hook_preprocess_HOOK()
- * 
- * Used to alter or add to theme variables.  The variables are passed into
- * templates when prossing.  This function organizes the relationships
+ *
+ * Used to alter or add to theme variables. The variables are passed into
+ * templates when processing. This function organizes the relationships
  * into more simple structures for parsing in the template file.
  *
  * @ingroup tripal_example
  */
 function tripal_example_preprocess_tripal_example_relationships(&$variables) {
-  // EXPLANATION:  If you have implmented a new chado node type and the record
+  // EXPLANATION:  If you have implemented a new Chado node type and the record
   // that belongs to the node has a corresponding xxxx_relationship table
   // this this function can be used to provide relationships to the template
-  // in a format that is easier to parse.  This is one example where specific SQL
-  // statements can improve performance over Tripal API calls.  SQL is not 
+  // in a format that is easier to parse. This is one example where specific SQL
+  // statements can improve performance over Tripal API calls. SQL is not
   // recommended inside of template files, but rather the Tripal API calls only.
   // Therefore, this function queries the relationships and then organizes them
-  // into arrays that are easier and faster to parse.  You should be able to
-  // copy the content of this function 
-  // and adjust as necessary to change table names if your record has relationships.
+  // into arrays that are easier and faster to parse. You should be able to
+  // copy the content of this function and adjust as necessary to change table
+  // names if your record has relationships.
 
   $example = $variables['node']->example;
-  
+
    // expand the example object to include the example relationships.
   $options = array(
     'return_array' => 1,
-    // we don't want to fully recurse we only need information about the
-    // relationship type and the object and subject examples (including example type)
+    // we don't want to fully recurs we only need information about the
+    // relationship type and the object and subject examples (including example
+    // type)
     'include_fk' => array(
       'type_id' => 1,
       'object_id' => array(
@@ -52,7 +53,7 @@ function tripal_example_preprocess_tripal_example_relationships(&$variables) {
   $srelationships = $example->example_relationship->subject_id;
   $orelationships = $example->example_relationship->object_id;
 
-  // combine both object and subject relationshisp into a single array
+  // combine both object and subject relationships into a single array
   $relationships = array();
   $relationships['object'] = array();
   $relationships['subject'] = array();
@@ -62,11 +63,11 @@ function tripal_example_preprocess_tripal_example_relationships(&$variables) {
     foreach ($orelationships as $relationship) {
       $rel = new stdClass();
       $rel->record = $relationship;
-       
+
       // get the relationship and child types
       $rel_type = t(preg_replace('/_/', " ", $relationship->type_id->name));
       $child_type = $relationship->subject_id->type_id->name;
-       
+
       // get the node id of the subject
       $sql = "SELECT nid FROM {chado_example} WHERE example_id = :example_id";
       $n = db_query($sql, array(':example_id' => $relationship->subject_id->example_id))->fetchObject();
@@ -91,14 +92,14 @@ function tripal_example_preprocess_tripal_example_relationships(&$variables) {
       $rel->record = $relationship;
       $rel_type = t(preg_replace('/_/', " ", $relationship->type_id->name));
       $parent_type = $relationship->object_id->type_id->name;
-       
+
       // get the node id of the subject
       $sql = "SELECT nid FROM {chado_example} WHERE example_id = :example_id";
       $n = db_query($sql, array(':example_id' => $relationship->object_id->example_id))->fetchObject();
       if ($n) {
         $rel->record->nid = $n->nid;
       }
-       
+
       if (!array_key_exists($rel_type, $relationships['subject'])) {
         $relationships['subject'][$rel_type] = array();
       }

+ 9 - 9
tripal_example/tripal_example.info

@@ -1,6 +1,6 @@
 ;
 ; Provide details about your module in this file. Instruction for setup of this
-; file can be found here:  https:;drupal.org/node/542202
+; file can be found here: https://drupal.org/node/542202
 ;
 name = Tripal Example
 description = An example module that can be used as a template for anyone wanting to create a custom extension module for Tripal.
@@ -17,30 +17,30 @@ project = tripal_example
 
 ;
 ; In order for this module to appear in the 'Tripal Extensions' section when
-; viewing the module administrative page, the package must be set to 
+; viewing the module administrative page, the package must be set to
 ; 'Tripal Extensions'
-; 
+;
 package = Tripal Extensions
 
 ;
 ; Follow these instructions when specifying the version:
-; https:;drupal.org/node/1015226
-; 
+; https://drupal.org/node/1015226
+;
 version = 7.x-2.0-rc1
 
 ;
-; Stylesheets containing CSS that should always be available for the
-; module should be specified here.  
+; Style-sheets containing CSS that should always be available for the
+; module should be specified here.
 ;
 stylesheets[all][] = theme/css/tripal_example.css
 
 ;
 ; Javascript files that should always be available for the
-; module should be specified here.  
+; module should be specified here.
 ;
 scripts[]          = theme/js/tripal_example.js
 
-; 
+;
 ; Add additional dependencies for other modules using the module project name.
 ; These modules must be enabled before this module can be enabled
 ;

+ 67 - 68
tripal_example/tripal_example.install

@@ -13,12 +13,12 @@
  */
 function tripal_example_disable() {
 
-  // EXPLANATION: If you are using Drupal Views you want to ensure
-  // that any default views that your module provides are disabled
-  // when the module is disabled.  Default views are specified in the
-  // [module name].views.default.inc file.  The following code will disable
-  // these views.  If your module does not create any default views you
-  // can remove the following code.
+  // EXPLANATION: If you are using Drupal Views you want to ensure that any
+  // default views that your module provides are disabled when the module is
+  // disabled. Default views are specified in the
+  // [module name].views.default.inc file. The following code will disable these
+  // views. If your module does not create any default views you can remove the
+  // following code.
 
   // Disable all default views provided by this module
   require_once("tripal_example.views_default.inc");
@@ -33,8 +33,8 @@ function tripal_example_disable() {
  * Implements hook_requirements().
  *
  * Performs check to see if all required dependencies are met. Drupal will
- * automatically check for module dependencies but here you can check for
- * other requirements.
+ * automatically check for module dependencies but here you can check for other
+ * requirements.
  *
  * @ingroup tripal_example
  */
@@ -44,9 +44,9 @@ function tripal_example_requirements($phase) {
   $requirements = array();
   if ($phase == 'install') {
     // EXPLANATION: It is essential that Chado be installed for almost all
-    // Tripal modules. Therefore, the following code checks to ensure Chado
-    // is installed and available.  If your module does not require that
-    // Chado be installed, you can remove the following check.
+    // Tripal modules. Therefore, the following code checks to ensure Chado is
+    // installed and available. If your module does not require that Chado be
+    // installed, you can remove the following check.
 
     // make sure chado is installed
     if (!$GLOBALS["chado_is_installed"]) {
@@ -71,17 +71,16 @@ function tripal_example_install() {
 
   // EXPLANATION: If your module will making data publicly available for
   // download or use by the site you can create the directory using the
-  // tripal_create_files_dir() function.  This will create a directory
-  // in the public access directory which will typcially be in
+  // tripal_create_files_dir() function. This will create a directory in the
+  // public access directory which will typically be in
   // sites/default/files/tripal/[module name]/
 
   // create the module's data directory
   tripal_create_files_dir('tripal_example');
 
-  // EXPLANATION: Here is a good place to add any materialized views,
-  // controlled vocabularies CV, databases or CV terms needed by your module.
-  // To keep this module code short, create functions to do each of those
-  // tasks
+  // EXPLANATION: Here is a good place to add any materialized views, controlled
+  // vocabularies CV, databases or CV terms needed by your module.
+  // To keep this module code short, create functions to do each of those tasks
 
   // add any materialized view
   tripal_example_add_mviews();
@@ -91,11 +90,11 @@ function tripal_example_install() {
 
   // add any controlled vocabularies used by the example module. You may need
   // to add a vocabulary if you to set it as default (see next lines of code).
-  // For example, the Sequence Ontology (SO) is used by the feature module as the
-  // default vocabulary for the feature type_id field.  But, that vocabulary
-  // does not yet exist in Chado until after the SO is loaded using the
-  // Tripal OBO loader.  But, we can add it here as a placeholder so that we can
-  // then set it as a default vocabulary (see below).
+  // For example, the Sequence Ontology (SO) is used by the feature module as
+  // the default vocabulary for the feature type_id field. But, that vocabulary
+  // does not yet exist in Chado until after the SO is loaded using the Tripal
+  // OBO loader. But, we can add it here as a place-holder so that we can then
+  // set it as a default vocabulary (see below).
   tripal_example_add_cvs();
 
 
@@ -103,12 +102,12 @@ function tripal_example_install() {
   tripal_example_add_cvterms();
 
   // EXPLANATION: Many tables in Chado have a 'type_id' column which allows for
-  // association of controlled vocabulries to describe the record.   Chado
-  // places no restrictions on which vocabularies can be used, but Tripal can
-  // be instructed to provide a default vocabulary for any given field. For
-  // example, the feature.type_id column will typically use the Sequence Ontology
-  // In that case, we can use the tripal_set_default_cv() function to specify
-  // the Sequence Ontology (sequence) as the default vocabulary.
+  // association of controlled vocabularies to describe the record. Chado places
+  // no restrictions on which vocabularies can be used, but Tripal can be
+  // instructed to provide a default vocabulary for any given field. For
+  // example, the feature.type_id column will typically use the Sequence
+  // Ontology. In that case, we can use the tripal_set_default_cv() function to
+  // specify the Sequence Ontology (sequence) as the default vocabulary.
   tripal_set_default_cv('example', 'type_id', 'example_type');
   tripal_set_default_cv('exampleprop', 'type_id', 'example_property');
   tripal_set_default_cv('example_relationship', 'type_id', 'example_relationship');
@@ -133,9 +132,9 @@ function tripal_example_uninstall() {
 /**
  * Implementation of hook_schema().
  *
- * Provides a list of tables to be created inside of the Drupal schema
- * (the 'public' schema by default). It uses the Drupal Schema API
- * array structure to define the table, its indexes and constraints.
+ * Provides a list of tables to be created inside of the Drupal schema (the
+ * 'public' schema by default). It uses the Drupal Schema API array structure to
+ * define the table, its indexes and constraints.
  *
  * Schema API documentation is here:
  * https://api.drupal.org/api/drupal/includes%21database%21schema.inc/group/schemaapi/7
@@ -145,12 +144,11 @@ function tripal_example_uninstall() {
 function tripal_example_schema() {
 
   // EXPLANATION: If your module creates a node type for data in the Chado
-  // database then you probably need to link Drupal nodes with a respective
-  // ID in the Chado table.  The following is an example array for a table
-  // that will link the 'chado_example' node type (created by this example
-  // module) with a record in the fake Chado example table.  This table
-  // will link the 'nid' of the node with the 'example_id' of the eample
-  // record.
+  // database then you probably need to link Drupal nodes with a respective ID
+  // in the Chado table. The following is an example array for a table that will
+  // link the 'chado_example' node type (created by this example module) with a
+  // record in the fake Chado example table. This table will link the 'nid' of
+  // the node with the 'example_id' of the example record.
   $schema['chado_example'] = array(
     'fields' => array(
       'vid' => array(
@@ -190,16 +188,17 @@ function tripal_example_schema() {
 };
 
 /**
- * Creates a materialized view that stores the type & number of examples per organism
+ * Creates a materialized view that stores the type & number of examples per
+ * organism.
  *
  * @ingroup tripal_example
  */
 function tripal_example_add_mviews() {
 
-  // EXPLANATION: use the tripal_add_mview() function to add a materialized
-  // view needed by your module.  If you have more than one materialized view
-  // it is best to create a single function for each one and call each
-  // function here. Otherwise this function can become quite long.
+  // EXPLANATION: use the tripal_add_mview() function to add a materialized view
+  // needed by your module. If you have more than one materialized view it is
+  // best to create a single function for each one and call each function here.
+  // Otherwise this function can become quite long.
 
 }
 /**
@@ -208,9 +207,9 @@ function tripal_example_add_mviews() {
  * @ingroup tripal_example
  */
 function tripal_example_add_dbs() {
-  // EXPLANATION: use the tripal_insert_db() function to add any
-  // external databases needed by your module.  If the database already
-  // exists then the function will gracefully return.
+  // EXPLANATION: use the tripal_insert_db() function to add any external
+  // databases needed by your module. If the database already exists then the
+  // function will gracefully return.
 
   tripal_insert_db(array(
     'name' => 'example_db',
@@ -224,10 +223,10 @@ function tripal_example_add_dbs() {
  */
 function tripal_example_add_cvs() {
 
-  // EXPLANATION: use the tripal_insert_cv() function to add any
-  // controlled vocabularies needed by your module.  If the vocabulary already
-  // exists then the function will gracefully return.  Chado convensions
-  // use a singluar name for CV names (not plural)/
+  // EXPLANATION: use the tripal_insert_cv() function to add any controlled
+  // vocabularies needed by your module. If the vocabulary already exists then
+  // the function will gracefully return. Chado conventions use a singular name
+  // for CV names (not plural).
 
   tripal_insert_cv(
     'example_property',
@@ -253,15 +252,15 @@ function tripal_example_add_cvs() {
  */
 function tripal_example_add_cvterms() {
 
-  // EXPLANATION:  for our test module to work we need to add some terms to our example_type
-  // controlled vocabulary.  Ideally we should have a full OBO file for loading
-  // but sometimes we just have a small list that won't really change so
-  // we can add those terms here.
+  // EXPLANATION: for our test module to work we need to add some terms to our
+  // example_type controlled vocabulary. Ideally we should have a full OBO file
+  // for loading but sometimes we just have a small list that won't really
+  // change so we can add those terms here.
   tripal_insert_cvterm(array(
     'id'         => 'test',         // the term accession
     'name'       => 'Test type',    // the human readable term name
     'cv_name'    => 'example_type', // the CV name this term belongs to.
-    'definition' => 'A test type for the example modlue.',
+    'definition' => 'A test type for the example module.',
     'db_name'    => 'example_db',   // the database in which the term is found.
   ));
 }
@@ -281,7 +280,7 @@ function tripal_example_add_custom_tables() {
   //   3) example_relationship (for storing relationships about examples)
   //   4) example_dbxref (for storing cross-references about an example)
   //
-  // To make the code easier to read, each table is created by a separte
+  // To make the code easier to read, each table is created by a separate
   // function called here:
 
   tripal_example_add_example_table();
@@ -289,6 +288,7 @@ function tripal_example_add_custom_tables() {
   tripal_example_add_example_relationship_table();
   tripal_example_add_example_dbxref_table();
 }
+
 /**
  * Adds the 'example' custom table to Chado.
  *
@@ -353,10 +353,9 @@ function tripal_example_add_example_table() {
         ),
       ),
     ),
-    // EXPLANATION: the 'referring_tables' array is the list of tables
-    // that have a foreign key relationships with this table. This
-    // information is required for the Tripal API to be able to expand
-    // tables in templates.
+    // EXPLANATION: the 'referring_tables' array is the list of tables that have
+    // a foreign key relationships with this table. This information is required
+    // for the Tripal API to be able to expand tables in templates.
     'referring_tables' => array(
       0 => 'example_relationship',
       1 => 'exampleprop',
@@ -584,8 +583,8 @@ function tripal_example_update_7200() {
   // https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_update_N/7
   //
   // It is best not to use Tripal API calls inside of this function because an
-  // upgarde from Drupal 6 to Drupal 7 requires that all modules be disabled
-  // which means the Tripal API is not available.  This is an unfortunate
+  // upgrade from Drupal 6 to Drupal 7 requires that all modules be disabled
+  // which means the Tripal API is not available. This is an unfortunate
   // requirement, but will prevent errors during a major upgrade.
 
   // it is good to wrap any database changes inside of a try catch block:
@@ -599,17 +598,17 @@ function tripal_example_update_7200() {
 }
 
 /**
- * Implementation of hook_update_dependencies().  It specifies a list of
- * other modules whose updates must be run prior to this one.
+ * Implementation of hook_update_dependencies(). It specifies a list of other
+ * modules whose updates must be run prior to this one.
  */
 function tripal_example_update_dependencies() {
   $dependencies = array();
 
-  // EXPLANATION: here we can specify which modules must be updated prior
-  // to applying the updates in this module.  This is useful because it
-  // prevents updates from being executed out of order.  The following
-  // example code shows that the 'tripal_example' module update number 7200
-  // must be executed after the 'tripal_cv' module's 7200 update.
+  // EXPLANATION: here we can specify which modules must be updated prior to
+  // applying the updates in this module. This is useful because it prevents
+  // updates from being executed out of order. The following example code shows
+  // that the 'tripal_example' module update number 7200 must be executed after
+  // the 'tripal_cv' module's 7200 update.
   $dependencies['tripal_example'][7200] = array(
     'tripal_cv' => 7200
   );

+ 119 - 121
tripal_example/tripal_example.module

@@ -2,14 +2,14 @@
 
 /**
  * @file
- * This file contains all Drupal hooks for the module other than any
- * node hooks and block hooks. Those go in the [module name].chado_node.inc file
- * and [module_name].blocks.inc respectively
+ * This file contains all Drupal hooks for the module other than any node hooks
+ * and block hooks. Those go in the [module name].chado_node.inc file and
+ * [module_name].blocks.inc respectively
  *
  */
 
-// EXPLANATION: include any files needed for this module.  That includes any 
-// API file, the theme file, or include files.
+// EXPLANATION: include any files needed for this module. That includes any API
+// file, the theme file, or include files.
 require('api/tripal_example.api.inc');
 require('theme/tripal_example.theme.inc');
 require('includes/tripal_example.admin.inc');
@@ -18,21 +18,20 @@ require('includes/tripal_example.chado_node.inc');
 
 /**
  * Implementation of hook_permissions()
- * 
+ *
  * Set the permission types that this module uses.
- * 
+ *
  * @ingroup tripal_example
  */
 function tripal_example_permission() {
-  
-  // EXPLANATION:  here we want to setup any of the permission types
-  // that this module needs.  Our exmample module creates a new
-  // chado node type called 'chado_example'.  Therefore, we need 
-  // permissions to view, edit, delete, create our new node type.  Additionally,
-  // we want to add a permission that allows for administration of this 
-  // module.  These permissions will appear in the 'People' -> 'Permissions'
-  // configuration page and allow the site admin to specify which user roles
-  // are allowed to perform specific actions.
+
+  // EXPLANATION:  here we want to setup any of the permission types that this
+  // module needs. Our example module creates a new chado node type called
+  // 'chado_example'. Therefore, we need permissions to view, edit, delete,
+  // create our new node type. Additionally, we want to add a permission that
+  // allows for administration of this module. These permissions will appear in
+  // the 'People' -> 'Permissions' configuration page and allow the site admin
+  // to specify which user roles are allowed to perform specific actions.
   return array(
     'access chado_example content' => array(
       'title' => t('View Examples'),
@@ -59,32 +58,32 @@ function tripal_example_permission() {
 
 /**
  * Implements hook_menu()
- * 
+ *
  * Specifies menu items and URLs used by this module.
  *
  * @ingroup tripal_example
  */
 function tripal_example_menu() {
   $items = array();
-  
-  // EXPLANATION:  the $items array should be popluated to contain a list of 
-  // menu items or URL callbacks that our module needs.  
-  // all Tripal Extension modules shoudl provide at least these menu items:
+
+  // EXPLANATION:  the $items array should be populated to contain a list of
+  // menu items or URL callbacks that our module needs.
+  // all Tripal Extension modules should provide at least these menu items:
   //  * A menu item for an administrative home page
   //  * A menu item for 'Help' documentation
   //  * A menu item for a module configuration page
   //
   // Additionally, if your module defines a custom node type that is linked
   // to a record in Chado:
-  //  * A menu item for syncing drupal nodes with Chado records.   
-  //    
-  
+  //  * A menu item for syncing drupal nodes with Chado records.
+  //
+
   // EXPLANATION:  all extension modules should have an administrative menu item
-  // with the path set to 'admin/tripal/extension/[module name]'.  This will
-  // place the menu item in the 'Tripal' -> 'Extesion Modules' page.  Because this
-  // is an administrative menu item we must be sure to set the 'access arguments'
-  // to be 'administer tripal example' which is a permission type we created
-  // in the tripal_example_permissions() function above.
+  // with the path set to 'admin/tripal/extension/[module name]'. This will
+  // place the menu item in the 'Tripal' -> 'Extension Modules' page. Because
+  // this is an administrative menu item we must be sure to set the
+  // 'access arguments' to be 'administer tripal example' which is a permission
+  // type we created in the tripal_example_permissions() function above.
   $items['admin/tripal/extension/tripal_example'] = array(
     'title' => 'Examples',
     'description' => 'Example module for help with development of new extension modules.',
@@ -93,14 +92,14 @@ function tripal_example_menu() {
     'type' => MENU_NORMAL_ITEM,
   );
 
-  // EXPLANATION: all extension modules should provide help documentation to 
+  // EXPLANATION: all extension modules should provide help documentation to
   // describe the functionality of the module and any installation or setup
-  // tasks that may be required.  The menu 'type' is MENU_LOCAL_TASK so that
-  // the link appears in a tab on the extension module's administrative page.
-  // here the 'page callback' specifies that we are using Drupal's theme 
+  // tasks that may be required. The menu 'type' is MENU_LOCAL_TASK so that the
+  // link appears in a tab on the extension module's administrative page.
+  // Here the 'page callback' specifies that we are using Drupal's theme
   // function and the 'page_arguments' indicate the name of the template file
-  // Thus, all help documentation should be provided in the 
-  // [module name]/theme/tripal_example_help.tpl.php file. 
+  // Thus, all help documentation should be provided in the
+  // [module name]/theme/tripal_example_help.tpl.php file.
   $items['admin/tripal/extension/tripal_example/help'] = array(
     'title' => 'Help',
     'description' => 'Basic Description of Tripal Library Module Functionality',
@@ -111,14 +110,14 @@ function tripal_example_menu() {
     'weight' => 10
   );
 
-  // EXPLANATION: all extension modules should provide a configuration page. 
+  // EXPLANATION: all extension modules should provide a configuration page.
   // Even if your module does not need configuration the menu item and page
   // should be created. This helps users recognize that the module is installed
-  // and working.  The configuration page can simply state that no 
-  // configuration settings are available.  Typically a form is provided for the 
-  // module's configuration settings. Therefore the 'page callback' uses the
+  // and working. The configuration page can simply state that no configuration
+  // settings are available. Typically a form is provided for the module's
+  // configuration settings. Therefore the 'page callback' uses the
   // drupal_get_form() function and the 'page argument' indicates the form
-  // to call is named 'tripal_eample_admin'.  The function that describes
+  // to call is named 'tripal_eample_admin'. The function that describes
   // to form is in the includes/tripal_example.admin.inc file.
   $items['admin/tripal/extension/tripal_example/configuration'] = array(
     'title' => 'Settings',
@@ -129,10 +128,10 @@ function tripal_example_menu() {
     'type' => MENU_LOCAL_TASK,
     'weight' => 5
   );
-  
+
   // EXPLANATION: If your module defines a new chado node type and that node
   // type directly links to a record in Chado, then you can use the Tripal API
-  // to quickly provide syncing functionality.  See the API documentation here
+  // to quickly provide syncing functionality. See the API documentation here
   // for more information on how that is setup:
   // http://api.tripal.info/api/tripal/tripal_core%21api%21tripal_core.chado_nodes.api.inc/function/chado_node_sync_form/2.x
   $items['admin/tripal/extension/tripal_example/sync'] = array(
@@ -144,15 +143,15 @@ function tripal_example_menu() {
     'type' => MENU_LOCAL_TASK,
     'weight' => 2
   );
-  
+
   // EXPLANATION: If your module defines a new node type that uses the default
-  // table of contents (left-side bar of content panes on a page). Then a 
-  // 'TOC' link will automatically appear on the node page to allow for 
-  // customization of the TOC.  However those customizations are only node
-  // specific.  To provide a tab in the module's administrative pages add the
-  // following menu item. This menu will provide a form similar to the one
-  // found on the node that allows the user to set global TOC settings for the
-  // content type.  Be sure to always use a menu path of the form:
+  // table of contents (left-side bar of content panes on a page). Then a 'TOC'
+  // link will automatically appear on the node page to allow for customization
+  // of the TOC. However those customizations are only node specific. To provide
+  // a tab in the module's administrative pages add the following menu item.
+  // This menu will provide a form similar to the one found on the node that
+  // allows the user to set global TOC settings for the content type. Be sure to
+  // always use a menu path of the form:
   //   admin/tripal/chado/[module name]/[content type name]_toc
   // this allows for a module to support TOC management when there are multiple
   // content types provided by the module, as the content type is specified
@@ -168,16 +167,16 @@ function tripal_example_menu() {
     'file path' => drupal_get_path('module', 'tripal_core'),
     'weight' => 3
   );
-  
+
   return $items;
 }
 
 /**
  * Implements hook_views_api()
- * 
- * This hook tells drupal that there is views support for
- * for this module which then automatically includes the tripal_db.views.inc 
- * where all the views integration code is found.
+ *
+ * This hook tells Drupal that there is views support for this module which then
+ * automatically includes the tripal_db.views.inc where all the views
+ * integration code is found.
  *
  * @ingroup tripal_example
  */
@@ -189,35 +188,34 @@ function tripal_example_views_api() {
 
 
 /**
- *  We need to let drupal know about our theme functions and their arguments.
- *  We create theme functions to allow users of the module to customize the
- *  look and feel of the output generated in this module
+ * We need to let Drupal know about our theme functions and their arguments.
+ * We create theme functions to allow users of the module to customize the look
+ * and feel of the output generated in this module.
  *
  * @ingroup tripal_example
  */
 function tripal_example_theme($existing, $type, $theme, $path) {
   $core_path = drupal_get_path('module', 'tripal_core');
 
-  // EXPLANATION: this function defines all of the functions and templates
-  // that this module needs to provide content.  These details are provided
-  // in the form of an array the indicates which functions or templates
-  // provide content.  Please see the Drupal theming guide for an in-depth
-  // description for how theming works in Drupal:
+  // EXPLANATION: this function defines all of the functions and templates that
+  // this module needs to provide content. These details are provided in the
+  // form of an array the indicates which functions or templates provide
+  // content. Please see the Drupal theming guide for an in-depth description
+  // for how theming works in Drupal:
   // https://drupal.org/documentation/theme
-  
+
   $items = array(
-    
-    // EXPLANATION:  If this module defines a new node type that displays
-    // Chado data then we should use Tripal's default node template.  This
-    // template ensures that all content provided by Tripal and Tripal 
-    // extension modules has the same look and feel.  It is designed to be
-    // generic such that it won't intefer with the look-and-feel of the default
-    // theme.  This generic template will organize the node into a table
-    // of contents found on the left-side of the page and place the content
-    // in the center of the page.  User's will cycle through content on the 
-    // page by clicking the links in the table of contents. If you do not want
-    // to use the default Tripal template you can change this array to your
-    // liking.
+
+    // EXPLANATION:  If this module defines a new node type that displays Chado
+    // data then we should use Tripal's default node template. This template
+    // ensures that all content provided by Tripal and Tripal extension modules
+    // has the same look and feel. It is designed to be generic such that it
+    // won't interfere with the look-and-feel of the default theme. This generic
+    // template will organize the node into a table of contents found on the
+    // left-side of the page and place the content in the center of the page.
+    // User's will cycle through content on the page by clicking the links in
+    // the table of contents. If you do not want to use the default Tripal
+    // template you can change this array to your liking.
     'node__chado_example' => array(
       'template' => 'node--chado-generic',
       'render element' => 'node',
@@ -230,12 +228,12 @@ function tripal_example_theme($existing, $type, $theme, $path) {
     // correspond directly to a file with the extension '.tpl.php'. For example
     // the 'tripal_example_base' template will have a corresponding
     // tripal_example_base.tpl.php file where the display code is housed.
-    // The only required templates are the 'base',  'help' and 'teaseer' templates.
-    // The base template provides the basic information about the record in 
-    // in Chado.  The 'help' template provides the adminstrative help documenation,
-    // and the teaser provides a brief summary of the record that can be used
-    // as short description of the record in aggregated lists.
-    
+    // The only required templates are the 'base',  'help' and 'teaser'
+    // templates. The base template provides the basic information about the
+    // record in Chado. The 'help' template provides the administrative help
+    // documentation, and the teaser provides a brief summary of the record that
+    // can be used as short description of the record in aggregated lists.
+
     // the base template
     'tripal_example_base' => array(
       'variables' => array('node' => NULL),
@@ -254,13 +252,14 @@ function tripal_example_theme($existing, $type, $theme, $path) {
       'template' => 'tripal_example_teaser',
       'path' => "$path/theme/templates",
     ),
-    
-    
-    // EXPLANATION: Typically, a different template is created for each subset of data.
-    // for example, most Chado tables have a 'XXXXprop', 'XXXX_cvterm',
+
+
+    // EXPLANATION: Typically, a different template is created for each subset
+    // of data.
+    // For example, most Chado tables have a 'XXXXprop', 'XXXX_cvterm',
     // 'XXXX_dbxref', 'XXXX_synonyms', 'XXXX_relationships' tables. Therefore,
     // a template is created to display data from each of these tables.
-    
+
     'tripal_example_properties' => array(
       'variables' => array('node' => NULL),
       'template' => 'tripal_example_properties',
@@ -279,11 +278,11 @@ function tripal_example_theme($existing, $type, $theme, $path) {
 
     // EXPLANATION: sometimes a module may want to add content to another
     // modules' node types. For example, the feature module does this by
-    // adding a 'feature summary' data to an organism.  To add data to another
-    // module's node, the templates belong to this module and are 
-    // specified in the same way as above.  However, the naming of the 
-    // template is changed to include the name of the module that supplies
-    // the node type followed by our record name: 
+    // adding a 'feature summary' data to an organism. To add data to another
+    // module's node, the templates belong to this module and are specified in
+    // the same way as above. However, the naming of the template is changed to
+    // include the name of the module that supplies the node type followed by
+    // our record name:
 
     // tripal_organism templates
     'tripal_organism_examples' => array(
@@ -292,25 +291,24 @@ function tripal_example_theme($existing, $type, $theme, $path) {
       'path' => "$path/theme/templates",
     ),
   );
-  
+
   return $items;
 }
 
 /**
  * Implements hook_help()
- * 
+ *
  * Adds a help page to the module list
  */
 function tripal_example_help ($path, $arg) {
-  
-  // EXPLANATION: in the tripal_example_menu() function above we created 
-  // a menu item for the help documentation.  The menu item specified 
-  // a function that should be called when the menu item is clicked.  This 
-  // is that function.  But, rather than place HTML code in this function
-  // we want to have our help documentation in a template file.  We 
-  // specified in the tripal_example_theme() function that we have a template
-  // file so now we want to use get the contents of that template file and
-  // return it.
+
+  // EXPLANATION: in the tripal_example_menu() function above we created a menu
+  // item for the help documentation. The menu item specified a function that
+  // should be called when the menu item is clicked. This is that function. But,
+  // rather than place HTML code in this function we want to have our help
+  // documentation in a template file. We specified in the
+  // tripal_example_theme() function that we have a template file so now we want
+  // to use get the contents of that template file and return it.
   if ($path == 'admin/help#tripal_example') {
     return theme('tripal_example_help', array());
   }
@@ -324,38 +322,38 @@ function tripal_example_help ($path, $arg) {
  */
 function tripal_example_cron() {
 
-  // EXPLANATION: here we can add any code that needs to be executed when
-  // the Drupal cron is run.
+  // EXPLANATION: here we can add any code that needs to be executed when the
+  // Drupal cron is run.
 }
 
 
 /**
  * Implementation of hook_form_alter()
- * 
+ *
  * Allows a module to alter any form prior to it being rendered. For more
  * details about Drupal's Form API see this page:
- * 
+ *
  * https://api.drupal.org/api/drupal/includes!form.inc/group/form_api/7
  *
  */
 function tripal_example_form_alter(&$form, &$form_state, $form_id) {
-  
+
   if ($form_id == "chado_example_node_form") {
-    
-    // EXPLANATION:  The hook_form_alter() Drupal hook is used to alter
-    // a form before it is displayed.  This allows any module to provide new
-    // form elements or change the form that another module creates.  We do
-    // not need to alter a form created by another module, but we do want to
-    // alter the form for our new node type.  For example, all node types
-    // will automatically have a 'Preview' button.  For inserting or updating
-    // data for Chado we don't really need a Preview button and it complicates
-    // the form.  So, we use the following code to disable the Preview button.
-    // if you want to keep the preview button then remove this code.
-    // turn of preview button for insert/updates
+
+    // EXPLANATION:  The hook_form_alter() Drupal hook is used to alter a form
+    // before it is displayed. This allows any module to provide new form
+    // elements or change the form that another module creates. We do not need
+    // to alter a form created by another module, but we do want to alter the
+    // form for our new node type. For example, all node types will
+    // automatically have a 'Preview' button. For inserting or updating data
+    // for Chado we don't really need a Preview button and it complicates the
+    // form. So, we use the following code to disable the Preview button. If
+    // you want to keep the preview button then remove this code. turn of
+    // preview button for insert/updates
     $form['actions']['preview']['#access'] = FALSE;
-    
+
     // EXPLANATION: Drupal always adds a 'body' field to all node types.
-    // Our node type doens't use the 'body' field so we remove it from the form.
+    // Our node type doesn't use the 'body' field so we remove it from the form.
     unset($form['body']);
   }
 }

+ 2 - 2
tripal_example/tripal_example.views.inc

@@ -1,8 +1,8 @@
 <?php
 /**
  *  @file
- *  This file contains the basic functions for views integration of
- *  chado/tripal example tables
+ *  This file contains the basic functions for views integration of chado/tripal
+ *  example tables
  */
 
 // EXPLANATION: see another tripal module (e.g. tripal_feature) for example

+ 9 - 9
tripal_example/tripal_example.views_default.inc

@@ -11,15 +11,15 @@
 */
 function tripal_example_views_default_views() {
   $views = array();
-  
-  // EXPLANATION:  use this function to programmatically define any default
-  // Drupal views that your module will provide automatically.  Typically
-  // there are two default views: 1) one for the administrator to quickly
-  // find data managed by your module, or 2) one for users to be able to
-  // search for public data.  
+
+  // EXPLANATION: use this function to programmatically define any default
+  // Drupal views that your module will provide automatically. Typically there
+  // are two default views: 1) one for the administrator to quickly find data
+  // managed by your module, or 2) one for users to be able to search for public
+  // data.
   //
-  // See another Tripal module such as tripal_feature for an example 
-  // of how to setup a default views.
-  
+  // See another Tripal module such as tripal_feature for an example of how to
+  // setup a default views.
+
   return $views;
 }

+ 31 - 29
tripal_feature/includes/tripal_feature.chado_node.inc

@@ -260,25 +260,26 @@ function chado_feature_form($node, &$form_state) {
  */
 function chado_feature_validate($node, $form, &$form_state) {
 
+
   // We only want to validate when the node is saved.
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
   // without the proper values.
-  if(!isset($node->op) OR $node->op != 'Save') {
+  if(property_exists($node, "op") and $node->op != 'Save') {
     return;
   }
 
   // we are syncing if we do not have a node ID but we do have a feature_id. We don't
   // need to validate during syncing so just skip it.
-  if (is_null($node->nid) and property_exists($node, 'feature_id') and $node->feature_id != 0) {
+  if (!property_exists($node, 'nid') and property_exists($node, 'feature_id') and $node->feature_id != 0) {
     return;
   }
 
   // remove surrounding white-space on submitted values
-  $node->uniquename   = trim($node->uniquename);
-  $node->fname        = trim($node->fname);
-  $node->feature_type = trim($node->feature_type);
-  $node->residues     = trim($node->residues);
+  $node->uniquename   = property_exists($node, 'uniquename') ? trim($node->uniquename) : '';
+  $node->fname        = property_exists($node, 'fname') ? trim($node->fname) : '';
+  $node->feature_type = property_exists($node, 'feature_type') ? trim($node->feature_type) : '';
+  $node->residues     = property_exists($node, 'residues') ? trim($node->residues) : '';
 
   // Validating for an update
   if (property_exists($node, 'nid')) {
@@ -338,6 +339,7 @@ function chado_feature_validate($node, $form, &$form_state) {
         CVT.name      = :cvtname
     ";
     $args = array(':name' => $node->uniquename, ':organism_id' => $node->organism_id, ':cvtname' => $node->feature_type);
+
     $result = chado_query($sql, $args)->fetchObject();
     if ($result) {
       form_set_error('uniquename', t("Feature insert cannot proceed. The feature name '$node->uniquename' already exists for this organism. Please provide a unique name for this feature."));
@@ -412,33 +414,33 @@ function chado_feature_node_access($node, $op, $account) {
  */
 function chado_feature_insert($node) {
 
-  $node->uniquename   = trim($node->uniquename);
-  $node->fname        = trim($node->fname);
-  $node->feature_type = trim($node->feature_type);
-  $node->residues     = trim($node->residues);
-
-  // remove spaces, newlines from residues
-  $residues = preg_replace("/[\n\r\s]/", "", $node->residues);
-  $obsolete = 'FALSE';
-  if ($node->is_obsolete) {
-    $obsolete = 'TRUE';
-  }
-
-  // get the feature type id
-  $values = array(
-    'cv_id' => array(
-      'name' => 'sequence'
-    ),
-    'name' => $node->feature_type
-  );
-  $type = chado_select_record('cvterm', array('cvterm_id'), $values);
-
   $feature_id = '';
 
   // if there is a feature_id in the $node object then this must be a sync so
   // we can skip adding the feature as it is already there, although
-  // we do need to proceed with the rest of the insert
+  // we do need to proceed with insertion into the chado/drupal linking table.
   if (!property_exists($node, 'feature_id')) {
+    $node->uniquename   = trim($node->uniquename);
+    $node->fname        = trim($node->fname);
+    $node->feature_type = trim($node->feature_type);
+    $node->residues     = trim($node->residues);
+
+    // remove spaces, newlines from residues
+    $residues = preg_replace("/[\n\r\s]/", "", $node->residues);
+    $obsolete = 'FALSE';
+    if ($node->is_obsolete) {
+      $obsolete = 'TRUE';
+    }
+
+    // get the feature type id
+    $values = array(
+        'cv_id' => array(
+            'name' => 'sequence'
+        ),
+        'name' => $node->feature_type
+    );
+    $type = chado_select_record('cvterm', array('cvterm_id'), $values);
+
     $values = array(
       'organism_id' => $node->organism_id,
       'name' => $node->fname,
@@ -959,4 +961,4 @@ function chado_feature_chado_node_default_title_format() {
  */
 function chado_feature_chado_node_default_url_format() {
   return '/feature/[feature.organism_id>organism.genus]/[feature.organism_id>organism.species]/[feature.type_id>cvterm.name]/[feature.uniquename]';
-}
+}

+ 7 - 9
tripal_feature/includes/tripal_feature.gff_loader.inc

@@ -477,6 +477,7 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
       // check to see if we have FASTA section, if so then set the variable
       // to start parsing
       if (preg_match('/^##FASTA/i', $line)) {
+        print "Parsing FASTA portion...\n";
         if ($remove) {
           // we're done because this is a delete operation so break out of the loop.
           break;
@@ -498,7 +499,7 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
           $result = chado_query($sel_cvterm_sql, $query);
           $cvterm = $result->fetchObject();
           if (!$cvterm) {
-            tripal_report_error('tripal_feature', TRIPAL_ERROR, 
+            tripal_report_error('tripal_feature', TRIPAL_ERROR,
              'cannot find feature type \'%landmark_type\' on line %line_num of the GFF file',
               array('%landmark_type' => $landmark_type, '%line_num' => $line_num));
             return '';
@@ -672,11 +673,6 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
           }
         }
       }
-
-      if ($skip_line) {
-        continue;
-      }
-
       // if neither name nor uniquename are provided then generate one
       if (!$attr_uniquename and !$attr_name) {
         // check if an alternate ID field is suggested, if so, then use
@@ -703,14 +699,16 @@ function tripal_feature_load_gff3($gff_file, $organism_id, $analysis_id,
       }
 
       // if a name is not specified then use the unique name as the name
-      if (strcmp($attr_name, '')==0) {
+      if (strcmp($attr_name, '') == 0) {
         $attr_name = $attr_uniquename;
       }
 
-      // if an ID attribute is not specified then use the attribute name plus the date
+      // if an ID attribute is not specified then we must generate a
+      // unique ID. Do this by combining the attribute name with the date
+      // and line number.
       if (!$attr_uniquename) {
         $date = getdate();
-        $attr_uniquename = $attr_name . '-' . $date[0];
+        $attr_uniquename = $attr_name . '-' . $date[0] . '-' . $line_num;
       }
 
       // make sure the landmark sequence exists in the database.  If the user

+ 9 - 7
tripal_featuremap/includes/tripal_featuremap.chado_node.inc

@@ -159,19 +159,19 @@ function chado_featuremap_validate($node, $form, &$form_state) {
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
   // without the proper values.
-  if($node->op != 'Save') {
+  if(property_exists($node, "op") and $node->op != 'Save') {
     return;
   }
 
   // we are syncing if we do not have a node ID but we do have a featuremap_id. We don't
   // need to validate during syncing so just skip it.
-  if (is_null($node->nid) and property_exists($node, 'featuremap_id') and $node->featuremap_id != 0) {
+  if (!property_exists($node, 'nid') and property_exists($node, 'featuremap_id') and $node->featuremap_id != 0) {
     return;
   }
 
   // trim white space from text fields
-  $node->fmapname       = trim($node->fmapname);
-  $node->description    = trim($node->description);
+  $node->fmapname = property_exists($node, 'fmapname') ? trim($node->fmapname) : '';
+  $node->description = property_exists($node, 'description') ? trim($node->description) : '';
 
   $featuremap = 0;
   // check to make sure the unique name on the map is unique
@@ -261,14 +261,16 @@ function chado_featuremap_node_access($node, $op, $account) {
  */
 function chado_featuremap_insert($node) {
 
-  $node->fmapname       = trim($node->fmapname);
-  $node->description    = trim($node->description);
+  $featuremap_id = '';
 
   // if there is an featuremap_id in the $node object then this must be a sync so
   // we can skip adding the featuremap as it is already there, although
-  // we do need to proceed with the rest of the insert
+  // we do need to proceed with insertion into the chado/drupal linking table.
   if (!property_exists($node, 'featuremap_id')) {
 
+    $node->fmapname       = trim($node->fmapname);
+    $node->description    = trim($node->description);
+
     $values = array(
       'name'        => $node->fmapname,
       'description' => $node->description,

+ 11 - 9
tripal_library/includes/tripal_library.chado_node.inc

@@ -222,20 +222,20 @@ function chado_library_validate($node, $form, &$form_state) {
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
   // without the proper values.
-  if($node->op != 'Save') {
+  if(property_exists($node, "op") and $node->op != 'Save') {
     return;
   }
 
   // we are syncing if we do not have a node ID but we do have a featuremap_id. We don't
   // need to validate during syncing so just skip it.
-  if (is_null($node->nid) and property_exists($node, 'library_id') and $node->library_id != 0) {
+  if (!property_exists($node, 'nid') and property_exists($node, 'library_id') and $node->library_id != 0) {
     return;
   }
 
   // trim white space from text fields
-  $node->libraryname = trim($node->libraryname);
-  $node->uniquename  = trim($node->uniquename);
-  $node->description = trim($node->description);
+  $node->libraryname = property_exists($node, 'libraryname') ? trim($node->libraryname) : '';
+  $node->uniquename  = property_exists($node, 'uniquename') ? trim($node->uniquename) : '';
+  $node->description = property_exists($node, 'description') ? trim($node->description) : '';
 
   $lib = 0;
   // check to make sure the unique name on the library is unique
@@ -268,14 +268,16 @@ function chado_library_validate($node, $form, &$form_state) {
  */
 function chado_library_insert($node) {
 
-  $node->libraryname = trim($node->libraryname);
-  $node->uniquename  = trim($node->uniquename);
-  $node->description = trim($node->description);
+  $library_id = '';
 
   // if there is an library_id in the $node object then this must be a sync so
   // we can skip adding the library as it is already there, although
-  // we do need to proceed with the rest of the insert
+  // we do need to proceed with insertion into the chado/drupal linking table.
   if (!property_exists($node, 'library_id')) {
+    $node->libraryname = trim($node->libraryname);
+    $node->uniquename  = trim($node->uniquename);
+    $node->description = trim($node->description);
+
     $values = array(
       'name' => $node->libraryname,
       'uniquename' => $node->uniquename,

+ 20 - 15
tripal_organism/includes/tripal_organism.chado_node.inc

@@ -220,22 +220,22 @@ function chado_organism_validate($node, $form, &$form_state) {
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
   // without the proper values.
-  if($node->op != 'Save') {
+  if(property_exists($node, "op") and $node->op != 'Save') {
     return;
   }
 
   // we are syncing if we do not have a node ID but we do have a organism_id. We don't
   // need to validate during syncing so just skip it.
-  if (is_null($node->nid) and property_exists($node, 'organism_id') and $node->organism_id != 0) {
+  if (!property_exists($node, 'nid') and property_exists($node, 'organism_id') and $node->organism_id != 0) {
     return;
   }
 
   // remove any white space around values
-  $node->genus        = trim($node->genus);
-  $node->species      = trim($node->species);
-  $node->abbreviation = trim($node->abbreviation);
-  $node->common_name  = trim($node->common_name);
-  $node->description  = trim($node->description);
+  $node->genus        = property_exists($node, 'genus') ? trim($node->genus) : '';
+  $node->species      = property_exists($node, 'species') ? trim($node->species) : '';
+  $node->abbreviation = property_exists($node, 'abbreviation') ? trim($node->abbreviation) : '';
+  $node->common_name  = property_exists($node, 'common_name') ? trim($node->common_name) : '';
+  $node->description  = property_exists($node, 'description') ? trim($node->description) : '';
 
   // Validating for an update
   if (property_exists($node, 'organism_id')) {
@@ -284,17 +284,20 @@ function chado_organism_validate($node, $form, &$form_state) {
  * @ingroup tripal_organism
  */
 function chado_organism_insert($node) {
-  // remove any white space around values
-  $node->genus        = trim($node->genus);
-  $node->species      = trim($node->species);
-  $node->abbreviation = trim($node->abbreviation);
-  $node->common_name  = trim($node->common_name);
-  $node->description  = trim($node->description);
+
+  $organism_id = '';
 
   // if there is an organism_id in the $node object then this must be a sync so
   // we can skip adding the organism as it is already there, although
-  // we do need to proceed with the rest of the insert
+  // we do need to proceed with insertion into the chado/drupal linking table.
   if (!property_exists($node, 'organism_id')) {
+    // remove any white space around values
+    $node->genus        = trim($node->genus);
+    $node->species      = trim($node->species);
+    $node->abbreviation = trim($node->abbreviation);
+    $node->common_name  = trim($node->common_name);
+    $node->description  = trim($node->description);
+
     $values = array(
       'genus'        => $node->genus,
       'species'      => $node->species,
@@ -383,7 +386,9 @@ function chado_organism_update($node) {
     'comment' => $node->description
   );
   $org_status = chado_update_record('organism', $match, $values);
-  chado_organism_add_image($node);
+  if ( $node->organism_image != '' ) {
+    chado_organism_add_image($node);
+  }
 
   // * Properties Form *
   $details = array(

+ 9 - 7
tripal_project/includes/tripal_project.chado_node.inc

@@ -200,19 +200,19 @@ function chado_project_validate($node, $form, &$form_state) {
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
   // without the proper values.
-  if($node->op != 'Save') {
+  if(property_exists($node, "op") and $node->op != 'Save') {
     return;
   }
 
   // we are syncing if we do not have a node ID but we do have a project_id. We don't
   // need to validate during syncing so just skip it.
-  if (is_null($node->nid) and property_exists($node, 'project_id') and $node->project_id != 0) {
+  if (!property_exists($node, 'nid') and property_exists($node, 'project_id') and $node->project_id != 0) {
     return;
   }
 
   // trim white space from text fields
-  $node->title = trim($node->title);
-  $node->description = trim($node->description);
+  $node->title = property_exists($node, 'title') ? trim($node->title) : '';
+  $node->description = property_exists($node, 'description') ? trim($node->description) : '';
 
   $project = 0;
   // check to make sure the name on the project is unique
@@ -240,13 +240,15 @@ function chado_project_validate($node, $form, &$form_state) {
  */
 function chado_project_insert($node) {
 
-  $node->title = trim($node->title);
-  $node->description = trim($node->description);
+  $project_id = '';
 
   // if there is an project_id in the $node object then this must be a sync so
   // we can skip adding the project as it is already there, although
-  // we do need to proceed with the rest of the insert
+  // we do need to proceed with insertion into the chado/drupal linking table.
   if (!property_exists($node, 'project_id')) {
+    $node->title = trim($node->title);
+    $node->description = trim($node->description);
+
     $values = array(
       'name' => $node->title,
       'description' => '',

+ 19 - 18
tripal_pub/includes/tripal_pub.chado_node.inc

@@ -337,22 +337,22 @@ function chado_pub_validate($node, $form, &$form_state) {
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
   // without the proper values.
-  if($node->op != 'Save') {
+  if(property_exists($node, "op") and $node->op != 'Save') {
     return;
   }
 
   // we are syncing if we do not have a node ID but we do have a pub_id. We don't
   // need to validate during syncing so just skip it.
-  if (is_null($node->nid) and property_exists($node, 'pub_id') and $node->pub_id != 0) {
+  if (!property_exists($node, 'nid') and property_exists($node, 'pub_id') and $node->pub_id != 0) {
     return;
   }
 
   // get the submitted values
-  $title        = trim($node->pubtitle);
-  $pyear        = trim($node->pyear);
-  $uniquename   = trim($node->uniquename);
-  $is_obsolete  = $node->is_obsolete;
-  $type_id      = $node->type_id;
+  $title        = property_exists($node, 'pubtitle') ? trim($node->pubtitle) : '';
+  $pyear        = property_exists($node, 'pyear') ? trim($node->pyear) : '';
+  $uniquename   = property_exists($node, 'uniquename') ? trim($node->uniquename) : '';
+  $is_obsolete  = property_exists($node, 'is_obsolete') ? trim($node->is_obsolete) : 0;
+  $type_id      = property_exists($node, 'type_id') ? trim($node->type_id) : '';
 
   $pub = array();
 
@@ -573,21 +573,23 @@ function chado_pub_node_access($node, $op, $account) {
  */
 function chado_pub_insert($node) {
 
-  $node->pubtitle     = trim($node->pubtitle);
-  $node->pyear        = trim($node->pyear);
-  $node->uniquename   = trim($node->uniquename);
-  $is_obsolete  = $node->is_obsolete;
-  $type_id      = $node->type_id;
-
-  // we need an array suitable for the tripal_pub_create_citation() function
-  // to automatically generate a citation if a uniquename doesn't already exist
-  $pub_arr = array();
+  $pub_id = '';
 
   // if there is an pub_id in the $node object then this must be a sync so
   // we can skip adding the pub as it is already there, although
-  // we do need to proceed with the rest of the insert
+  // we do need to proceed with insertion into the chado/drupal linking table.
   if (!property_exists($node, 'pub_id')) {
 
+    $node->pubtitle     = trim($node->pubtitle);
+    $node->pyear        = trim($node->pyear);
+    $node->uniquename   = trim($node->uniquename);
+    $is_obsolete  = $node->is_obsolete;
+    $type_id      = $node->type_id;
+
+    // we need an array suitable for the tripal_pub_create_citation() function
+    // to automatically generate a citation if a uniquename doesn't already exist
+    $pub_arr = array();
+
     $properties = array(); // stores all of the properties we need to add
     $cross_refs = array(); // stores any cross references for this publication
 
@@ -1164,7 +1166,6 @@ function tripal_pub_node_insert($node) {
  * @ingroup tripal_pub
  */
 function tripal_pub_node_load($nodes, $types) {
-
   if (count(array_intersect(array('chado_pub'), $types))) {
     foreach ($nodes as $nid => $node) {
       if ($node->type == 'chado_pub' and !property_exists($node, 'path')) {

+ 13 - 12
tripal_stock/includes/tripal_stock.chado_node.inc

@@ -323,22 +323,22 @@ function chado_stock_validate(&$node, $form, &$form_state) {
   // Since this validate can be called on AJAX and Deletion of the node
   // we need to make this check to ensure queries are not executed
   // without the proper values.
-  if(!isset($node->op) OR $node->op != 'Save') {
+  if(property_exists($node, "op") and $node->op != 'Save') {
     return;
   }
 
   // we are syncing if we do not have a node ID but we do have a stock_id. We don't
   // need to validate during syncing so just skip it.
-  if (is_null($node->nid) and property_exists($node, 'stock_id') and $node->stock_id != 0) {
+  if (!property_exists($node, 'nid') and property_exists($node, 'stock_id') and $node->stock_id != 0) {
     return;
   }
 
   // remove surrounding whitespace
-  $node->uniquename = trim($node->uniquename);
-  $node->sname = trim($node->sname);
-  $node->stock_description = trim($node->stock_description);
-  $node->accession = trim($node->accession);
-  $node->db_description = trim($node->db_description);
+  $node->uniquename = property_exists($node, 'uniquename') ? trim($node->uniquename) : '';
+  $node->sname = property_exists($node, 'sname') ? trim($node->sname) : '';
+  $node->stock_description = property_exists($node, 'stock_description') ? trim($node->stock_description) : '';
+  $node->accession = property_exists($node, 'accession') ? trim($node->accession) : '';
+  $node->db_description = property_exists($node, 'db_description') ? trim($node->db_description) : '';
 
   $int_in_chado_sql = "SELECT count(*) as count FROM {:table} WHERE :column = :value";
   $string_in_chado_sql = "SELECT count(*) as count FROM {:table} WHERE :column = :value";
@@ -441,17 +441,18 @@ function chado_stock_validate(&$node, $form, &$form_state) {
  */
 function chado_stock_insert($node) {
 
-  $node->uniquename   = trim($node->uniquename);
-  $node->sname        = trim($node->sname);
-  $node->accession    = trim($node->accession);
 
   $stock_id = '';
 
   // if there is an stock_id in the $node object then this must be a sync so
   // we can skip adding the stock to chado as it is already there, although
-  // we do need to proceed with the rest of the insert
+  // we do need to proceed with insertion into the chado/drupal linking table.
   if (!property_exists($node, 'stock_id')) {
 
+    $node->uniquename   = trim($node->uniquename);
+    $node->sname        = trim($node->sname);
+    $node->accession    = trim($node->accession);
+
     // before we can add the stock, we must add the dbxref if one has been
     // provided by the user.
     $dbxref = NULL;
@@ -913,4 +914,4 @@ function chado_stock_chado_node_default_title_format() {
  */
 function chado_stock_chado_node_default_url_format() {
   return '/stock/[stock.organism_id>organism.genus]/[stock.organism_id>organism.species]/[stock.type_id>cvterm.name]/[stock.uniquename]';
-}
+}