Browse Source

Merge branch '7.x-3.x' into 7.x-3.x-dashboard

Stephen Ficklin 8 years ago
parent
commit
76b173868f
30 changed files with 720 additions and 209 deletions
  1. 4 1
      README.md
  2. 1 1
      legacy/tripal_analysis/includes/tripal_analysis.chado_node.inc
  3. 6 6
      tripal/api/tripal.entities.api.inc
  4. 66 7
      tripal/api/tripal.jobs.api.inc
  5. 2 2
      tripal/includes/tripal_admin_usage_page.inc
  6. BIN
      tripal/theme/images/TripalLogo-sm.png
  7. BIN
      tripal/theme/images/powered_by_tripal.png
  8. BIN
      tripal/theme/images/powered_by_tripal_bw.png
  9. BIN
      tripal/theme/images/powered_by_tripal_bw_small.png
  10. BIN
      tripal/theme/images/powered_by_tripal_small.png
  11. BIN
      tripal/theme/images/tripal_logo.png
  12. 21 7
      tripal/tripal.drush.inc
  13. 76 0
      tripal/tripal.module
  14. 42 42
      tripal_chado/api/tripal_chado.api.inc
  15. 1 1
      tripal_chado/api/tripal_chado.mviews.api.inc
  16. 1 2
      tripal_chado/includes/TripalFields/chado_linker__contact/chado_linker__contact_widget.inc
  17. 6 1
      tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship.inc
  18. 0 1
      tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship_widget.inc
  19. 2 2
      tripal_chado/includes/TripalFields/schema__alternate_name/schema__alternate_name_widget.inc
  20. 0 1
      tripal_chado/includes/TripalFields/schema__publication/schema__publication.inc
  21. 6 1
      tripal_chado/includes/TripalFields/schema__publication/schema__publication_formatter.inc
  22. 2 2
      tripal_chado/includes/TripalFields/schema__publication/schema__publication_widget.inc
  23. 1 1
      tripal_chado/includes/loaders/tripal_chado.pub_importer_PMID.inc
  24. 1 1
      tripal_chado/includes/tripal_chado.entity.inc
  25. 1 1
      tripal_chado/includes/tripal_chado.field_storage.inc
  26. 15 15
      tripal_chado/includes/tripal_chado.fields.inc
  27. 355 70
      tripal_chado/includes/tripal_chado.migrate.inc
  28. 20 3
      tripal_chado/includes/tripal_chado.semweb.inc
  29. 1 0
      tripal_chado/tripal_chado.info
  30. 90 41
      tripal_chado/tripal_chado.install

+ 4 - 1
README.md

@@ -1,10 +1,13 @@
-# About
+![alt tag](https://raw.githubusercontent.com/tripal/tripal/7.x-3.x/tripal/theme/images/tripal_logo.png)
+
 Tripal is a toolkit for construction of online biological (genetics, genomics,
 breeding, etc), community database, and is a member of the 
 [GMOD](http://www.gmod.org) family of tools. Tripal v3 provides by default
 integration with the [GMOD Chado database](http://gmod.org/wiki/Chado_-_Getting_Started).
 Tripal's primary goals are: 
 
+Genomics, genetics, breeding and other biological data are increasingly complicated and time consuming to publish online for other researchers to search, browse and make discoveries.   Tripal provides a framework to reduce the complexity of creating such a site, and provides access to a community of similar groups that share community-standards, and interact to address questions and learn best practices for sharing, storing and visualizing complex biological data.
+
 1. Provide a framework for those with genomic, genetic and breeding data that
 can facility creation of an online site for display, search and visualization.
 2. To use community-derived standards and ontologies to facility continuity

+ 1 - 1
legacy/tripal_analysis/includes/tripal_analysis.chado_node.inc

@@ -215,7 +215,7 @@ function chado_analysis_form($node, &$form_state) {
   $day = preg_replace("/^\d+-\d+-0?(\d+) .*/", "$1", $default_time);
   // If the time is not set, use current time
   if (!$default_time) {
-    $default_time = REQUEST_TIME;
+    $default_time = time();
     $year  = format_date($default_time, 'custom', 'Y');
     $month = format_date($default_time, 'custom', 'n');
     $day   = format_date($default_time, 'custom', 'j');

+ 6 - 6
tripal/api/tripal.entities.api.inc

@@ -333,7 +333,7 @@ function tripal_create_bundle($args, &$error = '') {
     // Allow modules to add fields to the new bundle.
     $modules = module_implements('bundle_create_fields');
     foreach ($modules as $module) {
-      $function = $module . '_bundle_create_fields';
+      $function = $module . '_bundle_fields_info';
       $info = $function('TripalEntity', $bundle);
       foreach ($info as $field_name => $details) {
         $field_type = $details['type'];
@@ -359,7 +359,7 @@ function tripal_create_bundle($args, &$error = '') {
     // Allow modules to add instances to the new bundle.
     $modules = module_implements('bundle_create_instances');
     foreach ($modules as $module) {
-      $function = $module . '_bundle_create_instances';
+      $function = $module . '_bundle_instances_info';
       $info = $function('TripalEntity', $bundle);
       foreach ($info as $field_name => $details) {
         // If the field is already attached to this bundle then skip it.
@@ -485,7 +485,7 @@ function tripal_tripal_cron_notification() {
     // Allow modules to add fields to the new bundle.
     $modules = module_implements('bundle_create_fields');
     foreach ($modules as $module) {
-      $function = $module . '_bundle_create_fields';
+      $function = $module . '_bundle_fields_info';
       $info = $function('TripalEntity', $bundle);
       foreach ($info as $field_name => $details) {
 
@@ -510,7 +510,7 @@ function tripal_tripal_cron_notification() {
     // Allow modules to add instances to the new bundle.
     $modules = module_implements('bundle_create_instances');
     foreach ($modules as $module) {
-      $function = $module . '_bundle_create_instances';
+      $function = $module . '_bundle_instances_info';
       $info = $function('TripalEntity', $bundle);
       foreach ($info as $field_name => $details) {
 
@@ -576,7 +576,7 @@ function tripal_refresh_bundle_fields($bundle_name) {
   // Allow modules to add fields to the new bundle.
   $modules = module_implements('bundle_create_fields');
   foreach ($modules as $module) {
-    $function = $module . '_bundle_create_fields';
+    $function = $module . '_bundle_fields_info';
     $info = $function('TripalEntity', $bundle);
     foreach ($info as $field_name => $details) {
       $field_type = $details['type'];
@@ -599,7 +599,7 @@ function tripal_refresh_bundle_fields($bundle_name) {
   // Allow modules to add instances to the new bundle.
   $modules = module_implements('bundle_create_instances');
   foreach ($modules as $module) {
-    $function = $module . '_bundle_create_instances';
+    $function = $module . '_bundle_instances_info';
     $info = $function('TripalEntity', $bundle);
     foreach ($info as $field_name => $details) {
       // If the field is already attached to this bundle then skip it.

+ 66 - 7
tripal/api/tripal.jobs.api.inc

@@ -126,7 +126,7 @@ function tripal_add_job($job_name, $modulename, $callback, $arguments, $uid,
     'modulename' => $modulename,
     'callback' => $callback,
     'status' => 'Waiting',
-    'submit_date' => REQUEST_TIME,
+    'submit_date' => time(),
     'uid' => $uid,
     # The lower the number the higher the priority.
     'priority' => $priority,
@@ -212,7 +212,7 @@ function tripal_is_job_running() {
       // the job is not running so terminate it
       $record = new stdClass();
       $record->job_id = $job->job_id;
-      $record->end_time = REQUEST_TIME;
+      $record->end_time = time();
       $record->status = 'Error';
       $record->error_msg = 'Job has terminated unexpectedly.';
       drupal_write_record('tripal_jobs', $record, 'job_id');
@@ -223,6 +223,47 @@ function tripal_is_job_running() {
   return FALSE;
 }
 
+/**
+ * Check for too many concurrent jobs.
+ *
+ * @param $max_jobs
+ *   The maximum number of concurrent jobs to allow; -1 = no limit
+ *
+ * @ingroup tripal_jobs_api
+ */
+function tripal_max_jobs_exceeded($max_jobs) {
+  if ($max_jobs < 0) {
+    // No limit on concurrent jobs
+    return FALSE;
+  }
+
+  $num_jobs_running = 0;
+
+  // Iterate through each job that has not ended and see if it is still running.
+  // If it is not running but does not have an end_time then set the end time
+  // and set the status to 'Error'
+  $sql =  "SELECT * FROM {tripal_jobs} TJ " .
+          "WHERE TJ.end_time IS NULL and NOT TJ.start_time IS NULL ";
+  $jobs = db_query($sql);
+  foreach ($jobs as $job) {
+    $status = shell_exec('ps -p ' . escapeshellarg($job->pid) . ' -o pid=');
+    if ($job->pid && $status) {
+      // the job is still running
+      $num_jobs_running++;
+    }
+    else {
+      // the job is not running so terminate it
+      $record = new stdClass();
+      $record->job_id = $job->job_id;
+      $record->end_time = REQUEST_TIME;
+      $record->status = 'Error';
+      $record->error_msg = 'Job has terminated unexpectedly.';
+      drupal_write_record('tripal_jobs', $record, 'job_id');
+    }
+  }
+
+  return ($num_jobs_running >= $max_jobs);
+}
 
 /**
  * Set a job to be re-ran (ie: add it back into the job queue)
@@ -286,7 +327,7 @@ function tripal_cancel_job($job_id, $redirect = TRUE) {
   if ($job->start_time == 0) {
     $record = new stdClass();
     $record->job_id = $job->job_id;
-    $record->end_time = REQUEST_TIME;
+    $record->end_time = time();
     $record->status = 'Cancelled';
     $record->progress = '0';
     drupal_write_record('tripal_jobs', $record, 'job_id');
@@ -314,16 +355,25 @@ function tripal_cancel_job($job_id, $redirect = TRUE) {
  *   based on order and priority.  However there are times when a specific
  *   job needs to be launched and this argument will allow it.  Only jobs
  *   which have not been run previously will run.
+ * @param $max_jobs
+ *   The maximum number of jobs that should be run concurrently. If -1 then unlimited.
+ * @param $single
+ *   Ensures only a single job is run rather then the entire queue.
  *
  * @ingroup tripal_jobs_api
  */
-function tripal_launch_job($do_parallel = 0, $job_id = NULL) {
+function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $single = 0) {
 
   // first check if any jobs are currently running
   // if they are, don't continue, we don't want to have
   // more than one job script running at a time
   if (!$do_parallel and tripal_is_job_running()) {
-    print "Jobs are still running. Use the --parallel=1 option with the Drush command to run jobs in parallel.";
+    print "Jobs are still running. Use the --parallel=1 option with the Drush command to run jobs in parallel.\n";
+    return;
+  }
+
+  if ($do_parallel && tripal_max_jobs_exceeded($max_jobs)) {
+    print "At least $max_jobs jobs are still running. At least one of these jobs much complete before a new job can start.\n";
     return;
   }
 
@@ -341,6 +391,7 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL) {
             "ORDER BY priority ASC,job_id ASC";
     $job_res = db_query($sql);
   }
+  print "There are " . $job_res->rowCount() . " jobs queued.\n";
   foreach ($job_res as $job) {
 
     // Include the necessary files
@@ -352,7 +403,7 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL) {
     // set the start time for this job
     $record = new stdClass();
     $record->job_id = $job->job_id;
-    $record->start_time = REQUEST_TIME;
+    $record->start_time = time();
     $record->status = 'Running';
     $record->pid = getmypid();
     drupal_write_record('tripal_jobs', $record, 'job_id');
@@ -391,11 +442,19 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL) {
     print "Calling: $callback(" . implode(", ", $string_args) . ")\n";
     call_user_func_array($callback, $args);
     // set the end time for this job
-    $record->end_time = REQUEST_TIME;
+    $record->end_time = time();
     $record->status = 'Completed';
     $record->progress = '100';
     drupal_write_record('tripal_jobs', $record, 'job_id');
 
+    if ($single) {
+      // Don't start any more jobs
+      break;
+    }
+    if (tripal_max_jobs_exceeded($max_jobs)) {
+      break;
+    }
+
     // send an email to the user advising that the job has finished
   }
 }

+ 2 - 2
tripal/includes/tripal_admin_usage_page.inc

@@ -41,7 +41,7 @@ function tripal_admin_notification_import_field($field_name_note, $bundle_id, $m
   }
 
   if($field_or_instance == 'field'){
-    $function = $module . '_bundle_create_fields';
+    $function = $module . '_bundle_fields_info';
     $info = $function('TripalEntity', $bundle);
     foreach ($info as $field_name => $details) {
       if($details['field_name'] == $field_name_note) {
@@ -57,7 +57,7 @@ function tripal_admin_notification_import_field($field_name_note, $bundle_id, $m
     }
   }
   else if($field_or_instance == 'instance'){
-    $function = $module . '_bundle_create_instances';
+    $function = $module . '_bundle_instances_info';
     $info = $function('TripalEntity', $bundle);
     foreach ($info as $field_name => $details) {
       if($details['field_name'] == $field_name_note) {

BIN
tripal/theme/images/TripalLogo-sm.png


BIN
tripal/theme/images/powered_by_tripal.png


BIN
tripal/theme/images/powered_by_tripal_bw.png


BIN
tripal/theme/images/powered_by_tripal_bw_small.png


BIN
tripal/theme/images/powered_by_tripal_small.png


BIN
tripal/theme/images/tripal_logo.png


+ 21 - 7
tripal/tripal.drush.inc

@@ -67,7 +67,8 @@ function tripal_drush_command() {
     'description' => dt('Launches jobs waiting in the queue. Only one job can execute at a time unless the --parllel=1 option is provided.'),
     'examples' => array(
       'Single Job' => 'drush trp-run-jobs --username=administrator',
-      'Parallel Job' => 'drush trp-run-jobs --username=administrator --parallel=1'
+      'Parallel Job' => 'drush trp-run-jobs --username=administrator --parallel=1',
+      'Max-jobs Job' => 'drush trp-run-jobs --username=administrator --parallel=1 --max_jobs=10',
     ),
     'arguments' => array(),
     'options' => array(
@@ -79,13 +80,16 @@ function tripal_drush_command() {
       ),
       'parallel' => dt('Normally jobs are executed one at a time. But if you are certain no conflicts will occur with other currently running jobs you may set this argument to a value of 1 to make the job run in parallel with other running jobs.'),
       'job_id' => dt('Provide a job_id to run a specific job. Only jobs that have not been run already can be used'),
+      'max_jobs' => dt('Indicate the maximum number of concurrent jobs. Default is -1 (unlimited). Ignore if not running parallel jobs'),
+      'single' => dt('Execute only one queued job'),
     ),
   );
   $items['trp-rerun-job'] = array(
     'description' => dt('Re-run a specific job from the queue.'),
     'examples' => array(
       'Single Job' => 'drush trp-rerun-job --username=administrator --job_id=2',
-      'Parallel Job' => 'drush trp-rerun-job --username=administrator  --job_id=2 --parallel=1'
+      'Parallel Job' => 'drush trp-rerun-job --username=administrator  --job_id=2 --parallel=1',
+      'Max-jobs Job' => 'drush trp-run-jobs --username=administrator --parallel=1 --max_jobs=10',
     ),
     'arguments' => array(),
     'options' => array(
@@ -100,6 +104,8 @@ function tripal_drush_command() {
         'required' => TRUE,
       ),
       'parallel' => dt('Normally jobs are executed one at a time. But if you are certain no conflicts will occur with other currently running jobs you may set this argument to a value of 1 to make the job run in parallel with other running jobs.'),
+      'max_jobs' => dt('Indicate the maximum number of concurrent jobs. Default is -1 (unlimited). Ignore if not running parallel jobs'),
+      'single' => dt('Execute only one queued job'),
     ),
   );
 
@@ -140,6 +146,8 @@ function drush_tripal_set_user($username) {
 function drush_tripal_trp_run_jobs() {
   $parallel = drush_get_option('parallel');
   $job_id   = drush_get_option('job_id');
+  $max_jobs = drush_get_option('max_jobs', -1);
+  $single   = drush_get_option('single', 0);
 
   // Unfortunately later versions of Drush use the '--user' argument which
   // makes it incompatible with how Tripal was using it.  For backwards
@@ -160,17 +168,19 @@ function drush_tripal_trp_run_jobs() {
 
   drush_tripal_set_user($username);
 
+  drush_print("\n" . date('Y-m-d H:i:s'));
   if ($parallel) {
     drush_print("Tripal Job Launcher (in parallel)");
+    if ($max_jobs !== -1) drush_print("Maximum number of jobs is " . $max_jobs);
     drush_print("Running as user '$username'");
     drush_print("-------------------");
-    tripal_launch_job($parallel, $job_id);
+    tripal_launch_job($parallel, $job_id, $max_jobs, $single);
   }
   else {
     drush_print("Tripal Job Launcher");
     drush_print("Running as user '$username'");
     drush_print("-------------------");
-    tripal_launch_job(0, $job_id);
+    tripal_launch_job(0, $job_id, $max_jobs, $single);
   }
 }
 
@@ -202,21 +212,24 @@ function drush_tripal_trp_rerun_job() {
 
   $parallel = drush_get_option('parallel');
   $job_id   = drush_get_option('job_id');
+  $max_jobs = drush_get_option('max_jobs', -1);
+  $single   = drush_get_option('single', 0);
 
   drush_tripal_set_user($username);
   $new_job_id = tripal_rerun_job($job_id, FALSE);
 
+  drush_print("\n" . date('Y-m-d H:i:s'));
   if ($parallel) {
     drush_print("Tripal Job Launcher (in parallel)");
     drush_print("Running as user '$username'");
     drush_print("-------------------");
-    tripal_launch_job($parallel, $new_job_id);
+    tripal_launch_job($parallel, $new_job_id, $max_jobs, $single);
   }
   else {
     drush_print("Tripal Job Launcher");
     drush_print("Running as user '$username'");
     drush_print("-------------------");
-    tripal_launch_job(0, $new_job_id);
+    tripal_launch_job(0, $new_job_id, $max_jobs, $single);
   }
 
 }
@@ -244,7 +257,8 @@ function drush_tripal_trp_get_currjob() {
         "Module: " . $job->modulename . "\n" .
         "Callback: " . $job->callback . "\n" .
         "Process ID: " . $job->pid . "\n" .
-        "Progress: " . $job->progress . "%\n";
+        "Progress: " . $job->progress . "%\n".
+        "Current Date: " . date('Y-m-d H:i:s') . "\n";
     drush_print($output);
   }
   if (!$job_pid) {

+ 76 - 0
tripal/tripal.module

@@ -654,6 +654,11 @@ function tripal_block_info() {
       'administrative' => TRUE,
     ),
   );
+
+  $blocks['powered_by_tripal'] = array(
+    'info' => t('Powered by Tripal'),
+    'cache' => DRUPAL_NO_CACHE,
+  );
   return $blocks;
 }
 
@@ -663,6 +668,27 @@ function tripal_block_info() {
 function tripal_block_view($delta = ''){
   // The $delta parameter tells us which block is being requested.
   switch ($delta) {
+    case 'powered_by_tripal':
+      $size = variable_get('powered_by_tripal_size', 'small');
+      $type = variable_get('powered_by_tripal_type', 'bw');
+
+      $image = 'powered_by_tripal_bw_small.png';
+      if ($size == 'small' and $type == 'col') {
+        $image = 'powered_by_tripal_small.png';
+      }
+      if ($size == 'large' and $type == 'bw') {
+        $image = 'powered_by_tripal_bw.png';
+      }
+      if ($size == 'large' and $type == 'col') {
+        $image = 'powered_by_tripal.png';
+      }
+
+      $block['title'] = '';
+      $block['content'] = array(
+        '#markup' => '<a href="http://tripal.info"><img border="0" src="' . drupal_get_path('module', 'tripal') . '/theme/images/' . $image . '"></a>',
+      );
+      break;
+
     case 'notifications_block':
       // Create your block content here
       $block['content'] = '';
@@ -738,4 +764,54 @@ function tripal_block_view($delta = ''){
       break;
   }
   return $block;
+}
+
+/**
+ * Implements hook_block_save().
+ */
+function tripal_block_save($delta = '', $edit = array()) {
+
+  switch ($delta) {
+    case 'powered_by_tripal':
+      if (!empty($edit['logo_size'])) {
+        variable_set('powered_by_tripal_size', $edit['logo_size']);
+      }
+
+      if (!empty($edit['logo_type'])) {
+        variable_set('powered_by_tripal_type', $edit['logo_type']);
+      }
+  }
+}
+/**
+ * Implements hook_block_configure().
+ */
+function tripal_block_configure ($delta = '') {
+  $form = array();
+
+  switch ($delta) {
+    case 'powered_by_tripal':
+      $form['logo_size'] = array(
+      '#type' => 'radios',
+      '#title' => t('Logo Size'),
+      '#default_value' => variable_get('powered_by_tripal_size', 'small'),
+      '#options' => array(
+      'large' => t('Large'),
+      'small' => t('Small')
+      ),
+      '#description' => t('Select if you would like a small or large "Powered by Tripal" logo.'),
+      );
+      $form['logo_type'] = array(
+        '#type' => 'radios',
+        '#title' => t('Logo Type'),
+        '#default_value' => variable_get('powered_by_tripal_type', 'bw'),
+        '#options' => array(
+          'bw' => t('Gray scale'),
+          'col' => t('Colored')
+        ),
+        '#description' => t('Select if you would like a black and white or colored "Powered by Tripal" logo.'),
+      );
+  }
+
+
+  return $form;
 }

+ 42 - 42
tripal_chado/api/tripal_chado.api.inc

@@ -317,28 +317,28 @@ function tripal_replace_chado_tokens($string, $record) {
 }
 
 /**
- * Retrieve entity_id for a chado record
- * 
+ * Retrieve an entity_id for a chado record.
+ *
  * @param string $chado_table
- *   the chado_table where the record is stored
+ *   The chado_table where the record is stored.
  * @param integer $record_id
- *   the record_id which is the primary key of the chado_table
- *   
+ *   The record_id which is the primary key of the chado table.
+ *
  * @return
- *   Return an integer representing the entity_id or NULL if not found. The record is then 
- *   accessible on the website through URL /bio_data/<entity_id>
+ *   Return an integer representing the entity_id or NULL if not found. The
+ *   record is then accessible on the website through URL /bio_data/<entity_id>
  */
 function tripal_get_chado_entity_id ($chado_table, $record_id) {
-  // To find the bundle_table, check if type_column is used for the chado_table
-  $type_column = 
+  // To find the bundle_table, check if type_column is used for the chado table.
+  $type_column =
     db_select('chado_bundle', 'CB')
     ->fields('CB', array('type_column'))
     ->condition('data_table', $chado_table)
     ->execute()
     ->fetchField();
-  
-  // if there is a type_column, get bundle_id by specifying the data_table,  type_column, 
-  // and type_id
+
+  // If there is a type_column, get bundle_id by specifying the data_table,
+  // type_column, and type_id.
   $bundle_id = NULL;
   if ($type_column) {
     $schema = chado_get_schema($chado_table);
@@ -346,48 +346,48 @@ function tripal_get_chado_entity_id ($chado_table, $record_id) {
     $type_id = NULL;
     if (key_exists($type_column, $schema['fields'])) {
       $type_id =
-        db_select('chado.' . $chado_table, 'C')
-        ->fields('C', array($type_column))
-        ->condition($pkey, $record_id)
-        ->execute()
-        ->fetchField();
+        chado_db_select($chado_table, 'C')
+          ->fields('C', array($type_column))
+          ->condition($pkey, $record_id)
+          ->execute()
+          ->fetchField();
     }
     if ($type_id) {
       $bundle_id =
         db_select('chado_bundle', 'CB')
-        ->fields('CB', array('bundle_id'))
-        ->condition('data_table', $chado_table)
-        ->condition('type_column', $type_column)
-        ->condition('type_id', $type_id)
-        ->execute()
-        ->fetchField();
+          ->fields('CB', array('bundle_id'))
+          ->condition('data_table', $chado_table)
+          ->condition('type_column', $type_column)
+          ->condition('type_id', $type_id)
+          ->execute()
+          ->fetchField();
     }
   }
-  // if type_column is not used, get bundle_id by specifying the data_table
+  // If type_column is not used, get bundle_id by specifying the data_table.
   else {
-    $bundle_id = 
+    $bundle_id =
       db_select('chado_bundle', 'CB')
-      ->fields('CB', array('bundle_id'))
-      ->condition('data_table', $chado_table)
-      ->execute()
-      ->fetchField();
+        ->fields('CB', array('bundle_id'))
+        ->condition('data_table', $chado_table)
+        ->execute()
+        ->fetchField();
   }
-  
-  // if bundle_id is found, find the bundle table name and return the entity_id
+
+  // If bundle_id is found, find the bundle table name and return the entity_id.
   $entity_id = NULL;
   if ($bundle_id) {
-    $table_name = 
+    $table_name =
       db_select('tripal_bundle', 'TB')
-      ->fields('TB', array('name'))
-      ->condition('id', $bundle_id)
-      ->execute()
-      ->fetchField();
-    $entity_id = 
+        ->fields('TB', array('name'))
+        ->condition('id', $bundle_id)
+        ->execute()
+        ->fetchField();
+    $entity_id =
       db_select('chado_' . $table_name, 'CBD')
-      ->fields('CBD', array('entity_id'))
-      ->condition('record_id', $record_id)
-      ->execute()
-      ->fetchField();
-  }  
+        ->fields('CBD', array('entity_id'))
+        ->condition('record_id', $record_id)
+        ->execute()
+        ->fetchField();
+  }
   return $entity_id;
 }

+ 1 - 1
tripal_chado/api/tripal_chado.mviews.api.inc

@@ -364,7 +364,7 @@ function tripal_populate_mview($mview_id) {
         $count = $results->fetchObject();
         $record = new stdClass();
         $record->mview_id = $mview_id;
-        $record->last_update = REQUEST_TIME;
+        $record->last_update = time();
         $record->status = "Populated with " . number_format($count->cnt) . " rows";
         drupal_write_record('tripal_mviews', $record, 'mview_id');
       }

+ 1 - 2
tripal_chado/includes/TripalFields/chado_linker__contact/chado_linker__contact_widget.inc

@@ -14,7 +14,6 @@ class chado_linker__contact_widget extends ChadoFieldWidget {
   public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
     parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
 
-    $entity = $form['#entity'];
     $field_name = $this->field['field_name'];
 
     // Get the FK column that links to the base table.
@@ -27,7 +26,7 @@ class chado_linker__contact_widget extends ChadoFieldWidget {
 
     // Get the field defaults.
     $record_id = '';
-    $fkey_value = $element['#entity']->chado_record_id;
+    $fkey_value = array_key_exists('#entity', $element) and $element['#entity'] ? $element['#entity']->chado_record_id : NULL;
     $contact_id = '';
     $name = '';
 

+ 6 - 1
tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship.inc

@@ -35,6 +35,12 @@ class sbo__relationship extends ChadoField {
     // type. This will create form elements when editing the field instance
     // to allow the site admin to change the term settings above.
     'term_fixed' => FALSE,
+    'relationships' => array(
+      'option1_vocabs' => '',
+      'option2_vocab' => '',
+      'option2_parent' => '',
+      'relationship_types' => '',
+    ),
   );
 
   // The default widget for this field.
@@ -549,7 +555,6 @@ class sbo__relationship extends ChadoField {
       '#default_value' => $this->instance['settings']['relationships']['option1_vocabs'],
       // TODO add ajax here so that the relationship autocomplete below works
     );
-
     $element['relationships']['option2'] = array(
       '#type' => 'item',
       '#title' => '<b>Option #2</b>',

+ 0 - 1
tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship_widget.inc

@@ -15,7 +15,6 @@ class sbo__relationship_widget extends ChadoFieldWidget {
     parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
 
     // Get the field settings.
-    $entity = $form['#entity'];
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];

+ 2 - 2
tripal_chado/includes/TripalFields/schema__alternate_name/schema__alternate_name_widget.inc

@@ -13,7 +13,7 @@ class schema__alternate_name_widget extends ChadoFieldWidget {
    */
   public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
     parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
-    $entity = $form['#entity'];
+
     $field_name = $this->field['field_name'];
 
     // Get the FK column that links to the base table.
@@ -26,7 +26,7 @@ class schema__alternate_name_widget extends ChadoFieldWidget {
 
     // Get the field defaults.
     $record_id = '';
-    $fkey_value = $element['#entity']->chado_record_id;
+    $fkey_value = array_key_exists('#entity', $element) and $element['#entity'] ? $element['#entity']->chado_record_id : NULL;
     $synonym_id = '';
     $pub_id = '';
     $is_current = TRUE;

+ 0 - 1
tripal_chado/includes/TripalFields/schema__publication/schema__publication.inc

@@ -90,7 +90,6 @@ class schema__publication extends ChadoField {
       'return_array' => 1,
     );
     $record = chado_expand_var($record, 'table', $linker_table, $options);
-
     if (count($record->$linker_table) > 0) {
       $i = 0;
       foreach ($record->$linker_table as $index => $linker) {

+ 6 - 1
tripal_chado/includes/TripalFields/schema__publication/schema__publication_formatter.inc

@@ -41,7 +41,12 @@ class schema__publication_formatter extends ChadoFieldFormatter {
 
     krsort($list_items, SORT_NUMERIC);
 
-    $list = 'There are no publications.';
+    if (count($list_items) == 0) {
+      $list = 'There are no publications.';
+    }
+    if (count($list_items) == 1) {
+      $list = $list_items[0];
+    }
     if (count($list_items) > 1) {
       $list = array(
         'title' => '',

+ 2 - 2
tripal_chado/includes/TripalFields/schema__publication/schema__publication_widget.inc

@@ -13,7 +13,7 @@ class schema__publication_widget extends ChadoFieldWidget {
    */
   public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
     parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
-    $entity = $form['#entity'];
+
     $field_name = $this->field['field_name'];
 
     // Get the FK column that links to the base table.
@@ -26,7 +26,7 @@ class schema__publication_widget extends ChadoFieldWidget {
 
     // Get the field defaults.
     $record_id = '';
-    $fkey_value = $element['#entity']->chado_record_id;
+    $fkey_value = array_key_exists('#entity', $element) and $element['#entity'] ? $element['#entity']->chado_record_id : NULL;
     $pub_id = '';
     $uname = '';
 

+ 1 - 1
tripal_chado/includes/loaders/tripal_chado.pub_importer_PMID.inc

@@ -144,7 +144,7 @@ function tripal_pub_remote_search_PMID($search_array, $num_to_retrieve, $page) {
   }
   if ($days) {
     // get the date of the day suggested
-    $past_timestamp = REQUEST_TIME - ($days * 86400);
+    $past_timestamp = time() - ($days * 86400);
     $past_date = getdate($past_timestamp);
     $search_str .= " AND (\"" . sprintf("%04d/%02d/%02d", $past_date['year'], $past_date['mon'], $past_date['mday']) . "\"[Date - Create] : \"3000\"[Date - Create]))";
   }

+ 1 - 1
tripal_chado/includes/tripal_chado.entity.inc

@@ -166,7 +166,7 @@ function tripal_chado_tripal_default_title_format($bundle, $available_tokens) {
   }
   if ($table == 'stock') {
     $format[] = array(
-      'format' => '[stock__name]',
+      'format' => '[schema__name]',
       'weight' => -5
     );
   }

+ 1 - 1
tripal_chado/includes/tripal_chado.field_storage.inc

@@ -415,7 +415,7 @@ function tripal_chado_field_storage_write_merge_fields($fields, $entity_type, $e
  * Implements hook_field_storage_query().
  */
 function tripal_chado_field_storage_query($query) {
-dpm($query);
+
   // Initialize the result array.
   $result = array(
     'TripalEntity' => array()

+ 15 - 15
tripal_chado/includes/tripal_chado.fields.inc

@@ -1,12 +1,12 @@
 <?php
 
 /**
- * Implements hook_bundle_create_fields().
+ * Implements hook_bundle_fields_info().
  *
  * This is a Tripal defined hook that supports integration with the
  * TripalEntity field.
  */
-function tripal_chado_bundle_create_fields($entity_type, $bundle) {
+function tripal_chado_bundle_fields_info($entity_type, $bundle) {
 
   $chado_bundle = db_select('chado_bundle', 'cb')
     ->fields('cb')
@@ -25,13 +25,13 @@ function tripal_chado_bundle_create_fields($entity_type, $bundle) {
   $info = array();
 
   // Create the fields for each column in the table.
-  tripal_chado_bundle_create_fields_base($info, $details, $entity_type, $bundle);
+  tripal_chado_bundle_fields_info_base($info, $details, $entity_type, $bundle);
 
   // Create custom fields.
-  tripal_chado_bundle_create_fields_custom($info, $details, $entity_type, $bundle);
+  tripal_chado_bundle_fields_info_custom($info, $details, $entity_type, $bundle);
 
   // Create fields for linking tables.
-  tripal_chado_bundle_create_fields_linker($info, $details, $entity_type, $bundle);
+  tripal_chado_bundle_fields_info_linker($info, $details, $entity_type, $bundle);
 
   return $info;
 
@@ -40,7 +40,7 @@ function tripal_chado_bundle_create_fields($entity_type, $bundle) {
  *
  * @param unknown $details
  */
-function tripal_chado_bundle_create_fields_base(&$info, $details, $entity_type, $bundle) {
+function tripal_chado_bundle_fields_info_base(&$info, $details, $entity_type, $bundle) {
 
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
@@ -171,7 +171,7 @@ function tripal_chado_bundle_create_fields_base(&$info, $details, $entity_type,
  *
  * @param unknown $details
  */
-function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type, $bundle) {
+function tripal_chado_bundle_fields_info_custom(&$info, $details, $entity_type, $bundle) {
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
   $type_field = $details['chado_type_column'];
@@ -357,7 +357,7 @@ function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type
  *
  * @param unknown $details
  */
-function tripal_chado_bundle_create_fields_linker(&$info, $details, $entity_type, $bundle) {
+function tripal_chado_bundle_fields_info_linker(&$info, $details, $entity_type, $bundle) {
 
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
@@ -586,7 +586,7 @@ function tripal_chado_bundle_create_fields_linker(&$info, $details, $entity_type
  * This is a Tripal defined hook that supports integration with the
  * TripalEntity field.
  */
-function tripal_chado_bundle_create_instances($entity_type, $bundle) {
+function tripal_chado_bundle_instances_info($entity_type, $bundle) {
 
   $chado_bundle = db_select('chado_bundle', 'cb')
     ->fields('cb')
@@ -602,9 +602,9 @@ function tripal_chado_bundle_create_instances($entity_type, $bundle) {
   );
 
   $info = array();
-  tripal_chado_bundle_create_instances_base($info, $entity_type, $bundle, $details);
-  tripal_chado_bundle_create_instances_custom($info, $entity_type, $bundle, $details);
-  tripal_chado_bundle_create_instances_linker($info, $entity_type, $bundle, $details);
+  tripal_chado_bundle_instances_info_base($info, $entity_type, $bundle, $details);
+  tripal_chado_bundle_instances_info_custom($info, $entity_type, $bundle, $details);
+  tripal_chado_bundle_instances_info_linker($info, $entity_type, $bundle, $details);
 
   return $info;
 
@@ -620,7 +620,7 @@ function tripal_chado_bundle_create_instances($entity_type, $bundle) {
  * @param $bundle
  * @param $details
  */
-function tripal_chado_bundle_create_instances_base(&$info, $entity_type, $bundle, $details) {
+function tripal_chado_bundle_instances_info_base(&$info, $entity_type, $bundle, $details) {
   $fields = array();
 
   // Get Chado information
@@ -827,7 +827,7 @@ function tripal_chado_bundle_create_instances_base(&$info, $entity_type, $bundle
  * @param $bundle
  * @param $details
  */
-function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bundle, $details) {
+function tripal_chado_bundle_instances_info_custom(&$info, $entity_type, $bundle, $details) {
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
   $type_field = $details['chado_type_column'];
@@ -1210,7 +1210,7 @@ function tripal_chado_bundle_create_instances_custom(&$info, $entity_type, $bund
  * @param unknown $bundle
  * @param unknown $details
  */
-function tripal_chado_bundle_create_instances_linker(&$info, $entity_type, $bundle, $details) {
+function tripal_chado_bundle_instances_info_linker(&$info, $entity_type, $bundle, $details) {
 
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];

+ 355 - 70
tripal_chado/includes/tripal_chado.migrate.inc

@@ -67,9 +67,8 @@ function tripal_chado_migrate_form($form, &$form_state) {
         visitors can continue to visit the Tripal v2 pages. Tripal
         v3 content types may remain private while customization is underway.
         Once customization is completed a subsequent step will allow you to
-        swap out Tripal v2 pages for the newer Tripal v3 pages.') .
-      t('If you would like to use Trial v3 web services you must migrate
-         content types.'),
+        swap out Tripal v2 pages for the newer Tripal v3 pages. If you would like to
+        use Trial v3 web services you must migrate content types.'),
   );
 
   $tv2_content_type = 'all';
@@ -130,12 +129,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       // Migrate selection only
       if ($table == 'organism') {
         $sql =
-          "SELECT count(*)
-              FROM {organism} O
-              INNER JOIN public.chado_organism CO ON O.organism_id = CO.organism_id
-              LEFT JOIN public.chado_entity CE ON CE.record_id = O.organism_id
-                AND CE.data_table = 'organism'
-              WHERE CE.record_id IS NULL";
+           "SELECT count(*)
+            FROM {organism} O
+            INNER JOIN public.chado_organism CO ON O.organism_id = CO.organism_id
+          ";
         $org_count = chado_query($sql)->fetchField();
         if ($org_count > 0) {
           $key = urldecode('tv3_content_type--OBI--0100026--organism');
@@ -149,11 +146,9 @@ function tripal_chado_migrate_form($form, &$form_state) {
       else if ($table == 'analysis') {
         $sql =
         "SELECT count(*)
-              FROM {analysis} A
-              INNER JOIN public.chado_analysis CA ON A.analysis_id = CA.analysis_id
-              LEFT JOIN public.chado_entity CE ON CE.record_id = A.analysis_id
-                AND CE.data_table = 'analysis'
-              WHERE CE.record_id IS NULL";
+          FROM {analysis} A
+          INNER JOIN public.chado_analysis CA ON A.analysis_id = CA.analysis_id
+         ";
         $ana_count = chado_query($sql)->fetchField();
         if ($ana_count > 0) {
           $key = urlencode('tv3_content_type--local--analysis--analysis');
@@ -166,12 +161,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       }
       else if ($table == 'project') {
         $sql =
-        "SELECT count(*)
-              FROM {project} P
-              INNER JOIN public.chado_project CP ON P.project_id = CP.project_id
-              LEFT JOIN public.chado_entity CE ON CE.record_id = P.project_id
-                AND CE.data_table = 'project'
-              WHERE CE.record_id IS NULL";
+          "SELECT count(*)
+           FROM {project} P
+           INNER JOIN public.chado_project CP ON P.project_id = CP.project_id
+          ";
         $proj_count = chado_query($sql)->fetchField();
         if ($proj_count > 0) {
           $key = urlencode('tv3_content_type--local--project--project');
@@ -184,12 +177,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       }
       else if ($table == 'featuremap') {
         $sql =
-        "SELECT count(*)
-              FROM {featuremap} M
-              INNER JOIN public.chado_featuremap CM ON M.featuremap_id = CM.featuremap_id
-              LEFT JOIN public.chado_entity CE ON CE.record_id = M.featuremap_id
-                AND CE.data_table = 'featuremap'
-              WHERE CE.record_id IS NULL";
+          "SELECT count(*)
+            FROM {featuremap} M
+            INNER JOIN public.chado_featuremap CM ON M.featuremap_id = CM.featuremap_id
+          ";
         $map_count = chado_query($sql)->fetchField();
         if ($map_count > 0) {
           $key = urlencode('tv3_content_type--data--1274--map');
@@ -202,12 +193,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       }
       else if ($table == 'pub') {
         $sql =
-        "SELECT count(*)
-              FROM {pub} P
-              INNER JOIN public.chado_pub CP ON P.pub_id = CP.pub_id
-              LEFT JOIN public.chado_entity CE ON CE.record_id = P.pub_id
-                AND CE.data_table = 'pub'
-              WHERE CE.record_id IS NULL";
+          "SELECT count(*)
+           FROM {pub} P
+           INNER JOIN public.chado_pub CP ON P.pub_id = CP.pub_id
+         ";
         $proj_count = chado_query($sql)->fetchField();
         if ($proj_count > 0) {
           $key = urlencode('tv3_content_type--TPUB--0000002--Publication');
@@ -221,15 +210,12 @@ function tripal_chado_migrate_form($form, &$form_state) {
       else if (key_exists('cvterm', $fkeys) && key_exists('type_id', $fkeys['cvterm']['columns'])) {
         // Get all Tripal v2 node types from the chad_* linking table
         $sql =
-          "SELECT V.name AS type, X.accession, db.name AS vocabulary , count(*) AS num
+            "SELECT V.name AS type, X.accession, db.name AS vocabulary , count(*) AS num
               FROM {" . $table . "} T
               INNER JOIN public.$tv2_content_type CT ON T.$pkey = CT.$pkey
               INNER JOIN {cvterm} V ON V.cvterm_id = T.type_id
               INNER JOIN {dbxref} X ON X.dbxref_id = V.dbxref_id
               INNER JOIN {db} ON db.db_id = X.db_id
-              LEFT JOIN public.chado_entity CE ON CE.record_id = T.$pkey
-              AND CE.data_table = '$table'
-              WHERE CE.record_id IS NULL
               GROUP BY V.name, X.accession, db.name";
         $tv3_content_types = chado_query($sql);
         while($tv3_content_type = $tv3_content_types->fetchObject()) {
@@ -260,6 +246,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       '#name' => 'migrate_btn',
       '#value' => "Migrate $tv2_options[$tv2_content_type]",
     );
+    // Disable the migration if all have been done
+    if (count($tv2_options) == 1 && key_exists('all', $tv2_options)) {
+      $form['step2']['step2_container']['migrate_btn']['#disabled'] = 1;
+    }
   }
 
   // Step 3
@@ -525,6 +515,10 @@ function tripal_chado_migrate_form_step2_ajax_callback(&$form, &$form_state) {
  *
  * @param boolean $all_option
  *   Include an 'all' option in the returned array
+ * @param boolean $has_template
+ *   Return TV2 content types only if it has a base template. This will exclude TV2 content
+ *   types such as Blast/Kegg/Interpro/Unigene which are all converted into the TV3
+ *   'Analysis' entity type
  * @return string[]
  *  Return a string array keyed by the node type
  */
@@ -726,7 +720,11 @@ function tripal_chado_migrate_selected_types($tv3_content_types) {
       'bundle_name' => $bundle_name
     );
     tripal_chado_publish_records($value);
-    
+
+    // Migrate Resource Titles/Blocks or Resource Links if available
+    tripal_chado_migrate_resource_blocks($bundle_name);
+    tripal_chado_migrate_resource_links($bundle_name);
+
     // Migrate organism images
     if ($term->name == 'organism') {
       tripal_chado_migrate_organism_images($bundle_name);
@@ -774,17 +772,21 @@ function tripal_chado_unpublish_selected_types($tv2_content_types = array()) {
  */
 function tripal_chado_copy_title_for_selected_types($tv2_content_types = array()) {
   foreach ($tv2_content_types AS $type) {
-    $sql = "SELECT nid, entity_id FROM chado_entity WHERE nid IN (SELECT nid FROM $type)";
-    $result = db_query($sql);
-    while ($entity = $result->fetchObject()) {
-      $usql = "
-          UPDATE tripal_entity
-          SET title = (SELECT title FROM node WHERE nid = :nid)
-          WHERE id = :entity_id";
-      db_query($usql, array(
-        ':nid' => $entity->nid,
-        ':entity_id' => $entity->entity_id)
-      );
+    $chado_table = str_replace('chado_', '', $type);
+    $bio_data_tables = tripal_chado_migrate_get_biodata_tables($chado_table);
+    foreach($bio_data_tables AS $bio_data_table) {
+      $sql = "SELECT nid, entity_id FROM $bio_data_table WHERE nid IN (SELECT nid FROM $type)";
+      $result = db_query($sql);
+      while ($entity = $result->fetchObject()) {
+        $usql = "
+            UPDATE tripal_entity
+            SET title = (SELECT title FROM node WHERE nid = :nid)
+            WHERE id = :entity_id";
+        db_query($usql, array(
+          ':nid' => $entity->nid,
+          ':entity_id' => $entity->entity_id)
+        );
+      }
     }
   }
 }
@@ -798,14 +800,18 @@ function tripal_chado_copy_title_for_selected_types($tv2_content_types = array()
  */
 function tripal_chado_migrate_url_alias_for_selected_types($tv2_content_types = array()) {
   foreach ($tv2_content_types AS $type) {
-    $sql = "SELECT nid, entity_id FROM chado_entity WHERE nid IN (SELECT nid FROM $type)";
-    $result = db_query($sql);
-    while ($entity = $result->fetchObject()) {
-      $usql = "
-          UPDATE url_alias
-          SET source = 'bio_data/" . $entity->entity_id .
-          "' WHERE source = 'node/" . $entity->nid . "'";
-      db_query($usql);
+    $chado_table = str_replace('chado_', '', $type);
+    $bio_data_tables = tripal_chado_migrate_get_biodata_tables($chado_table);
+    foreach($bio_data_tables AS $bio_data_table) {
+      $sql = "SELECT nid, entity_id FROM $bio_data_table WHERE nid IN (SELECT nid FROM $type)";
+      $result = db_query($sql);
+      while ($entity = $result->fetchObject()) {
+        $usql = "
+            UPDATE url_alias
+            SET source = 'bio_data/" . $entity->entity_id .
+            "' WHERE source = 'node/" . $entity->nid . "'";
+        db_query($usql);
+      }
     }
   }
 }
@@ -818,17 +824,17 @@ function tripal_chado_migrate_url_alias_for_selected_types($tv2_content_types =
  */
 function tripal_chado_migrate_organism_images () {
   // Get all organism entities
-  $results = 
-    db_select('chado_entity', 'ce')
+  $bio_data_table = array_pop(tripal_chado_migrate_get_biodata_tables('organism'));
+  $results =
+    db_select($bio_data_table, 'ce')
     ->fields('ce', array('entity_id', 'record_id', 'nid'))
-    ->condition('data_table', 'organism')
     ->execute();
-  
+
   // Iterate through each organism entity
   while ($organism = $results->fetchObject()) {
     $nid = $organism->nid;
     $entity_id = $organism->entity_id;
-    
+
     // check if there is a file record for the organism node
     $fid = db_select('file_usage', 'fu')
     ->fields('fu', array('fid'))
@@ -839,13 +845,13 @@ function tripal_chado_migrate_organism_images () {
     ->fetchField();
     // check if the image was added using the old interface.
     if (!$fid) {
-      $sql = 
-         "SELECT genus,species,nid 
-          FROM {organism} O 
-          INNER JOIN chado_organism CO ON O.organism_id = CO.organism_id 
+      $sql =
+         "SELECT genus,species,nid
+          FROM {organism} O
+          INNER JOIN chado_organism CO ON O.organism_id = CO.organism_id
           WHERE O.organism_id = :organism_id";
       $chado_org = chado_query($sql, array(':organism_id' => $organism->record_id))->fetchObject();
-      
+
       if ($chado_org) {
         $base_path = realpath('.');
         $image_dir = tripal_get_files_dir('tripal_organism') . "/images";
@@ -870,19 +876,19 @@ function tripal_chado_migrate_organism_images () {
         }
         if($file){
           tripal_chado_migrate_organism_image_add_file($file->fid, $entity_id);
-        }        
+        }
       }
     }
     else {
       // If there is an image, add it to the organism entity
       tripal_chado_migrate_organism_image_add_file ($fid, $entity_id);
     }
-    
+
   }
 }
 
 /**
- * 
+ *
  * Add image file for the organism entity
  *
  * @param unknown $fid
@@ -905,6 +911,285 @@ function tripal_chado_migrate_organism_image_add_file ($fid, $entity_id) {
     field_attach_update('TripalEntity', $entity);
     entity_get_controller('TripalEntity')->resetCache(array($entity_id));
     // Add a record to the field_data_data__image table
-    
+
+  }
+}
+
+/**
+ * Retrieve chado_biodata_* table name
+ *
+ * @param string $chado_table
+ *   the chado_table where the record is stored
+ *
+ * @return
+ *   Return all chado_biodata_* table names mapping to a chado_table
+ */
+function tripal_chado_migrate_get_biodata_tables ($chado_table) {
+  // To find the bundle_table, check if type_column is used for the chado_table
+  $query = db_select('chado_bundle', 'cb');
+  $query->join('tripal_bundle', 'tb', 'tb.id = cb.bundle_id');
+  $query->fields('cb', array('data_table'));
+  $query->fields('tb', array('name'));
+  $query->condition('cb.data_table', $chado_table);
+  $bundles = $query->execute();
+  $tables = array();
+  while ($bundle = $bundles->fetchObject()) {
+    array_push($tables, 'chado_' . $bundle->name);
   }
+  return $tables;
 }
+
+function tripal_chado_migrate_resource_blocks($bundle_name) {
+  $entites =
+    db_select('chado_' . $bundle_name, 'B')
+    ->fields('B', array('nid'))
+    ->execute();
+  while ($nid = $entites->fetchField()) {
+    // Only the latest revision is migrated
+    $sql = "
+      SELECT
+        entity_id,
+        max(revision_id) AS vid,
+        delta,
+        (SELECT field_resource_titles_value
+         FROM field_revision_field_resource_titles
+         WHERE entity_id = RT.entity_id
+         AND revision_id = max(RT.revision_id)
+         AND delta = RT.delta
+        ),
+        (SELECT field_resource_blocks_value
+         FROM field_revision_field_resource_blocks
+         WHERE entity_id = RT.entity_id
+         AND revision_id = max(RT.revision_id)
+         AND delta = RT.delta
+        )
+      FROM field_revision_field_resource_titles RT
+      WHERE RT.entity_id = :nid
+      GROUP BY entity_id, delta
+      ORDER BY RT.delta
+    ";
+    $results = db_query($sql, array(':nid' => $nid));
+    while ($resource = $results->fetchObject()) {
+      $title = $resource->field_resource_titles_value;
+      $content = $resource->field_resource_blocks_value;
+      $delta = $resource->delta;
+      $nid = $resource->entity_id;
+      $entity_id =
+        db_select('chado_' . $bundle_name, 'B')
+        ->fields('B', array('entity_id'))
+        ->condition('nid', $nid)
+        ->execute()
+        ->fetchField()
+       ;
+      // field name: (can not be longer than 32 chars)
+      // bio_data_<i>_resource_<title to lower case/space replaced with _/first 10 chars>
+      $field_name = $bundle_name . '_rsc_' . substr(preg_replace('/\s+/', '_', strtolower($title)), 0, 15);
+      // Create a field if it does not exist
+      if (!field_info_field($field_name)) {
+        field_create_field(array(
+          'field_name' => $field_name,
+          'type' => 'text',
+          'cardinality' => 1,
+          'locked' => FALSE,
+          'storage' => array(
+            'type' => 'field_sql_storage',
+          ),
+          'settings' => array(
+            'max_length' => 10485760,
+            'text_processing' => 1
+          )
+        ));
+      }
+      // Create field instance for the bundle if it does not exist
+      if (!field_info_instance('TripalEntity', $field_name, $bundle_name)) {
+        field_create_instance(array(
+          'field_name' => $field_name,
+          'entity_type' => 'TripalEntity',
+          'bundle' => $bundle_name,
+          'label' => $title,
+          'widget' => array(
+            'type' => 'text_textarea',
+          ),
+          'display' => array(
+            'default' => array(
+              'label' => 'hidden',
+            ),
+          ),
+          'settings' => array(
+            'text_processing' => 1,
+            'format' => 'full_html',
+            'term_vocabulary' => 'schema',
+            'term_name' => 'comment',
+            'term_accession' => 'comment',
+          ),
+        ));
+      }
+      // Migrate the field content
+      $ftable = 'field_data_' . $field_name;
+      $frtable = 'field_revision_' . $field_name;
+      $fvalue = $field_name . '_value';
+      $fformat = $field_name . '_format';
+      try {
+        $sql = "
+          INSERT INTO $ftable (entity_type, bundle, entity_id, revision_id, language, delta, $fvalue, $fformat)
+          VALUES (:entity_type, :bundle, :entity_id, :revision_id, :language, :delta, :value, :format)
+        ";
+        db_query($sql,
+          array (
+            ':entity_type' => 'TripalEntity',
+            ':bundle' => $bundle_name,
+            ':entity_id' => $entity_id,
+            'revision_id' => $entity_id,
+            ':language' => 'und',
+            ':delta' => 0,
+            ':value' => $content,
+            ':format' => 'full_html'
+          )
+        );
+        $rsql = "
+        INSERT INTO $frtable (entity_type, bundle, entity_id, revision_id, language, delta, $fvalue, $fformat)
+        VALUES (:entity_type, :bundle, :entity_id, :revision_id, :language, :delta, :value, :format)
+        ";
+        db_query($rsql,
+          array (
+            ':entity_type' => 'TripalEntity',
+            ':bundle' => $bundle_name,
+            ':entity_id' => $entity_id,
+            'revision_id' => $entity_id,
+            ':language' => 'und',
+            ':delta' => 0,
+            ':value' => $content,
+            ':format' => 'full_html'
+          )
+        );
+      } catch (\PDOException $e) {
+        $error = $e->getMessage();
+        watchdog_exception('tripal_chado', $e);
+      }
+    }
+  }
+}
+
+function tripal_chado_migrate_resource_links($bundle_name) {
+  $entites =
+  db_select('chado_' . $bundle_name, 'B')
+  ->fields('B', array('nid'))
+  ->execute();
+  while ($nid = $entites->fetchField()) {
+    // Only the latest revision is migrated
+    $sql = "
+      SELECT
+        entity_id,
+        max(revision_id) AS vid,
+        delta,
+        (SELECT field_resource_links_value
+         FROM field_revision_field_resource_links
+         WHERE entity_id = RT.entity_id
+         AND revision_id = max(RT.revision_id)
+         AND delta = RT.delta
+        )
+      FROM field_revision_field_resource_links RT
+      WHERE RT.entity_id = :nid
+      GROUP BY entity_id, delta
+      ORDER BY RT.delta
+    ";
+    $results = db_query($sql, array(':nid' => $nid));
+    while ($resource = $results->fetchObject()) {
+      $values = explode('|', $resource->field_resource_links_value);
+      $title = $values[0];
+      $link = $values[1];
+      $delta = $resource->delta;
+      $nid = $resource->entity_id;
+      $entity_id =
+      db_select('chado_' . $bundle_name, 'B')
+        ->fields('B', array('entity_id'))
+        ->condition('nid', $nid)
+        ->execute()
+        ->fetchField();
+
+      // field name: (can not be longer than 32 chars)
+      // bio_data_<i>_resource_<title to lower case/space replaced with _/first 10 chars>
+      $field_name = $bundle_name . '_resource_links';
+      // Create a field if it does not exist
+      if (!field_info_field($field_name)) {
+        field_create_field(array(
+          'field_name' => $field_name,
+          'type' => 'link_field',
+          'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+          'locked' => FALSE,
+          'storage' => array(
+            'type' => 'field_sql_storage',
+          ),
+          'settings' => array(
+          )
+        ));
+      }
+      // Create field instance for the bundle if it does not exist.
+      if (!field_info_instance('TripalEntity', $field_name, $bundle_name)) {
+        field_create_instance(array(
+          'field_name' => $field_name,
+          'entity_type' => 'TripalEntity',
+          'bundle' => $bundle_name,
+          'label' => 'Links',
+          'widget' => array(
+            'type' => 'link_field',
+          ),
+          'display' => array(
+            'default' => array(
+              'label' => 'hidden',
+            ),
+          ),
+          'settings' => array(
+            'term_vocabulary' => 'schema',
+            'term_name' => 'url',
+            'term_accession' => 'url',
+            'absolute_url' => 0,
+            'validate_url' => 0
+          ),
+        ));
+      }
+      // Migrate the field content
+      $ftable = 'field_data_' . $field_name;
+      $frtable = 'field_revision_' . $field_name;
+      $furl = $field_name . '_url';
+      $ftitle = $field_name . '_title';
+      try {
+        $sql = "
+        INSERT INTO $ftable (entity_type, bundle, entity_id, revision_id, language, delta, $furl, $ftitle)
+        VALUES (:entity_type, :bundle, :entity_id, :revision_id, :language, :delta, :url, :title)
+        ";
+        db_query($sql,
+          array (
+            ':entity_type' => 'TripalEntity',
+            ':bundle' => $bundle_name,
+            ':entity_id' => $entity_id,
+            'revision_id' => $entity_id,
+            ':language' => 'und',
+            ':delta' => $delta,
+            ':url' => $link,
+            ':title' => $title
+          )
+        );
+        $rsql = "
+        INSERT INTO $frtable (entity_type, bundle, entity_id, revision_id, language, delta, $furl, $ftitle)
+        VALUES (:entity_type, :bundle, :entity_id, :revision_id, :language, :delta, :url, :title)
+        ";
+        db_query($rsql,
+          array (
+            ':entity_type' => 'TripalEntity',
+            ':bundle' => $bundle_name,
+            ':entity_id' => $entity_id,
+            'revision_id' => $entity_id,
+            ':language' => 'und',
+            ':delta' => $delta,
+            ':url' => $link,
+            ':title' => $title
+          )
+        );
+      } catch (\PDOException $e) {
+        $error = $e->getMessage();
+        watchdog_exception('tripal_chado', $e);
+      }
+    }
+  }
+}

+ 20 - 3
tripal_chado/includes/tripal_chado.semweb.inc

@@ -219,6 +219,24 @@ function tripal_chado_populate_vocab_EDAM() {
     'url' => 'http://edamontology.org/page',
     'urlprefix' => 'http://edamontology.org/{db}_{accession}',
   ));
+  tripal_insert_db(array(
+    'name' => 'format',
+    'description' => 'A defined way or layout of representing and structuring data in a computer file, blob, string, message, or elsewhere. The main focus in EDAM lies on formats as means of structuring data exchanged between different tools or resources. ',
+    'url' => 'http://edamontology.org/page',
+    'urlprefix' => 'http://edamontology.org/{db}_{accession}',
+  ));
+  tripal_insert_db(array(
+    'name' => 'operation',
+    'description' => 'A function that processes a set of inputs and results in a set of outputs, or associates arguments (inputs) with values (outputs). Special cases are: a) An operation that consumes no input (has no input arguments).',
+    'url' => 'http://edamontology.org/page',
+    'urlprefix' => 'http://edamontology.org/{db}_{accession}',
+  ));
+  tripal_insert_db(array(
+    'name' => 'topic',
+    'description' => 'A category denoting a rather broad domain or field of interest, of study, application, work, data, or technology. Topics have no clearly defined borders between each other.',
+    'url' => 'http://edamontology.org/page',
+    'urlprefix' => 'http://edamontology.org/{db}_{accession}',
+  ));
   tripal_insert_db(array(
     'name' => 'EDAM',
     'description' => 'Bioinformatics operations, data types, formats, identifiers and topics.',
@@ -226,11 +244,10 @@ function tripal_chado_populate_vocab_EDAM() {
     'urlprefix' => 'http://edamontology.org/{db}_{accession}',
   ));
   tripal_insert_cv(
-    'data',
-    'Bioinformatics operations, data types, formats, identifiers and topics.'
+    'EDAM',
+    'EDAM is an ontology of well established, familiar concepts that are prevalent within bioinformatics, including types of data and data identifiers, data formats, operations and topics. EDAM is a simple ontology - essentially a set of terms with synonyms and definitions - organised into an intuitive hierarchy for convenient use by curators, software developers and end-users. EDAM is suitable for large-scale semantic annotations and categorization of diverse bioinformatics resources. EDAM is also suitable for diverse application including for example within workbenches and workflow-management systems, software distributions, and resource registries.'
   );
 
-
   $term = tripal_insert_cvterm(array(
     'id' => 'data:1249',
     'name' => 'Sequence length',

+ 1 - 0
tripal_chado/tripal_chado.info

@@ -15,4 +15,5 @@ stylesheets[all][] = theme/css/tripal_chado.css
 dependencies[] = tripal
 dependencies[] = date
 dependencies[] = image
+dependencies[] = link
 dependencies[] = tripal_chado_views

+ 90 - 41
tripal_chado/tripal_chado.install

@@ -182,6 +182,55 @@ function tripal_chado_schema() {
   // Map cvterm usage to chado tables
   $schema['chado_cvterm_mapping'] = tripal_chado_chado_cvterm_mapping_schema();
 
+  // When a chado Tripal content type is created, a linking table is also created to
+  // link the entity to it's record in chado (@see tripal_chado_bundle_create() ).
+  // This table is created via db_create_table() but in order to expose it to
+  // the Drupal Schema API, we also need to define each one here.
+  if (db_table_exists('chado_bundle')) {
+    $resource = db_query('SELECT tb.name FROM chado_bundle cb LEFT JOIN tripal_bundle tb ON tb.id=cb.bundle_id');
+    foreach ($resource as $r) {
+      $bundle_name = $r->name;
+      // This makes an assumption about the name of the linking table.
+      // @todo: Switch to tripal_chado_get_bundle_entity_table($bundle).
+      $chado_entity_table = 'chado_' . $bundle_name;
+      $schema[$chado_entity_table] = array(
+        'description' => 'The linker table that associates TripalEntities with Chado records for entities of type ' . $bundle_name . '.',
+        'fields' => array(
+          'mapping_id' => array(
+            'type' => 'serial',
+            'not null' => TRUE
+          ),
+          'entity_id' => array(
+            'description' => 'The unique entity id.',
+            'type' => 'int',
+            'not null' => TRUE,
+          ),
+          'record_id' => array(
+            'description' => 'The unique numerical identifier for the record that this entity is associated with (e.g. feature_id, stock_id, library_id, etc.).',
+            'type' => 'int',
+            'not null' => TRUE,
+          ),
+          'nid' => array(
+            'description' => 'Optional. For linking nid to the entity when migrating Tripal v2 content',
+            'type' => 'int',
+          )
+        ),
+        'primary key' => array(
+          'mapping_id',
+        ),
+        'indexes' => array(
+          'record_id' => array('record_id'),
+          'entity_id' => array('entity_id'),
+          'nid' => array('nid'),
+        ),
+        'unique keys' => array(
+          'table_record' => array('record_id'),
+          'entity_id' => array('entity_id'),
+        ),
+      );
+    }
+  }
+
   return $schema;
 }
 
@@ -264,39 +313,15 @@ function tripal_chado_upgrade_v2_v3_pre_enable() {
     if (db_query("SELECT 1 FROM pg_indexes WHERE indexname = 'tripal_cv_obo_pkey'")->fetchField()) {
       $sql = "ALTER INDEX tripal_cv_obo_pkey RENAME TO tripal_cv_obo_pkey2";
     }
+    if (db_query("SELECT 1 FROM pg_indexes WHERE indexname = 'tripal_cv_obo_tripal_cv_obo_idx1_idx'")->fetchField()) {
+      $sql = "ALTER INDEX tripal_cv_obo_tripal_cv_obo_idx1_idx RENAME TO tripal_cv_obo_tripal_cv_obo_idx1_idx2";
+    }
     else {
       $sql = "CREATE UNIQUE INDEX tripal_cv_obo_pkey2 ON tripal_cv_obo2 USING btree (obo_id)";
     }
     db_query($sql);
   }
 
-/*   if (db_table_exists('tripal_cv_defaults')) {
-    // Move the tripal_cv_defaults table out of the way.
-    $sql = "ALTER TABLE tripal_cv_defaults RENAME TO tripal_cv_defaults2";
-    db_query($sql);
-    if (db_query("SELECT 1 FROM pg_indexes WHERE indexname = 'tripal_cv_defaults_pkey'")->fetchField()) {
-      $sql = "ALTER INDEX tripal_cv_defaults_pkey RENAME TO tripal_cv_defaults_pkey2";
-    }
-    else {
-      $sql = "CREATE UNIQUE INDEX tripal_cv_defaults_pkey2 ON tripal_cv_defaults2 USING btree (cv_default_id)";
-    }
-    db_query($sql);
-    if (db_query("SELECT 1 FROM pg_indexes WHERE indexname = 'tripal_cv_defaults_tripal_cv_defaults_idx1_idx'")->fetchField()) {
-      $sql = "ALTER INDEX tripal_cv_defaults_tripal_cv_defaults_idx1_idx RENAME TO tripal_cv_defaults_tripal_cv_defaults_idx1_idx2";
-    }
-    else {
-      $sql = "CREATE INDEX tripal_cv_defaults_tripal_cv_defaults_idx1_idx2 ON tripal_cv_defaults2 USING btree (table_name, field_name)";
-    }
-    db_query($sql);
-    if (db_query("SELECT 1 FROM pg_indexes WHERE indexname = 'tripal_cv_defaults_tripal_cv_defaults_unq1_key'")->fetchField()) {
-      $sql = "ALTER INDEX tripal_cv_defaults_tripal_cv_defaults_unq1_key RENAME TO tripal_cv_defaults_tripal_cv_defaults_unq1_key2";
-    }
-    else {
-      $sql = "CREATE UNIQUE INDEX tripal_cv_defaults_tripal_cv_defaults_unq1_key2 ON tripal_cv_defaults2 USING btree (table_name, field_name, cv_id)";
-    }
-    db_query($sql);
-  } */
-
   if (db_table_exists('tripal_pub_import')) {
     // Move the tripal_pub_import table out of the way.
     $sql = "ALTER TABLE tripal_pub_import RENAME TO tripal_pub_import2";
@@ -363,21 +388,9 @@ function tripal_chado_upgrade_v2_v3_enable() {
     db_query($sql);
     $sql = "ALTER INDEX tripal_cv_obo_pkey2 RENAME TO tripal_cv_obo_pkey";
     db_query($sql);
-  }
-
-  // tripal_cv_defaults
-/*   if (db_table_exists('tripal_cv_defaults2')) {
-    $sql = "DROP TABLE tripal_cv_defaults";
-    db_query($sql);
-    $sql = "ALTER TABLE tripal_cv_defaults2 RENAME to tripal_cv_defaults";
-    db_query($sql);
-    $sql = "ALTER INDEX tripal_cv_defaults_pkey2 RENAME TO tripal_cv_defaults_pkey";
+    $sql = "ALTER INDEX tripal_cv_obo_tripal_cv_obo_idx1_idx2 RENAME TO tripal_cv_obo_tripal_cv_obo_idx1_idx";
     db_query($sql);
-    $sql = "ALTER INDEX tripal_cv_defaults_tripal_cv_defaults_idx1_idx2 RENAME TO tripal_cv_defaults_tripal_cv_defaults_idx1_idx";
-    db_query($sql);
-    $sql = "ALTER INDEX tripal_cv_defaults_tripal_cv_defaults_unq1_key2 RENAME TO tripal_cv_defaults_tripal_cv_defaults_unq1_key";
-    db_query($sql);
-  } */
+  }
 
   // tripal_pub_import
   if (db_table_exists('tripal_pub_import2')) {
@@ -742,3 +755,39 @@ function tripal_chado_update_7301() {
     throw new DrupalUpdateException('Could not perform update: '. $error);
   }
 }
+
+/**
+ * Corrections to the EDAM database.
+ */
+function tripal_chado_update_7302(){
+  try {
+    // Add the term for the field.
+    tripal_insert_db(array(
+      'name' => 'format',
+      'description' => 'A defined way or layout of representing and structuring data in a computer file, blob, string, message, or elsewhere. The main focus in EDAM lies on formats as means of structuring data exchanged between different tools or resources. ',
+      'url' => 'http://edamontology.org/page',
+      'urlprefix' => 'http://edamontology.org/{db}_{accession}',
+    ));
+    tripal_insert_db(array(
+      'name' => 'operation',
+      'description' => 'A function that processes a set of inputs and results in a set of outputs, or associates arguments (inputs) with values (outputs). Special cases are: a) An operation that consumes no input (has no input arguments).',
+      'url' => 'http://edamontology.org/page',
+      'urlprefix' => 'http://edamontology.org/{db}_{accession}',
+    ));
+    tripal_insert_db(array(
+      'name' => 'topic',
+      'description' => 'A category denoting a rather broad domain or field of interest, of study, application, work, data, or technology. Topics have no clearly defined borders between each other.',
+      'url' => 'http://edamontology.org/page',
+      'urlprefix' => 'http://edamontology.org/{db}_{accession}',
+    ));
+    tripal_insert_cv(
+      'EDAM',
+      'EDAM is an ontology of well established, familiar concepts that are prevalent within bioinformatics, including types of data and data identifiers, data formats, operations and topics. EDAM is a simple ontology - essentially a set of terms with synonyms and definitions - organised into an intuitive hierarchy for convenient use by curators, software developers and end-users. EDAM is suitable for large-scale semantic annotations and categorization of diverse bioinformatics resources. EDAM is also suitable for diverse application including for example within workbenches and workflow-management systems, software distributions, and resource registries.'
+    );
+  }
+  catch (\PDOException $e) {
+    $transaction->rollback();
+    $error = $e->getMessage();
+    throw new DrupalUpdateException('Could not perform update: '. $error);
+  }
+}