Explorar o código

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

Stephen Ficklin %!s(int64=8) %!d(string=hai) anos
pai
achega
76b173868f
Modificáronse 30 ficheiros con 720 adicións e 209 borrados
  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=BIN
      tripal/theme/images/TripalLogo-sm.png
  7. BIN=BIN
      tripal/theme/images/powered_by_tripal.png
  8. BIN=BIN
      tripal/theme/images/powered_by_tripal_bw.png
  9. BIN=BIN
      tripal/theme/images/powered_by_tripal_bw_small.png
  10. BIN=BIN
      tripal/theme/images/powered_by_tripal_small.png
  11. BIN=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,
 Tripal is a toolkit for construction of online biological (genetics, genomics,
 breeding, etc), community database, and is a member of the 
 breeding, etc), community database, and is a member of the 
 [GMOD](http://www.gmod.org) family of tools. Tripal v3 provides by default
 [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).
 integration with the [GMOD Chado database](http://gmod.org/wiki/Chado_-_Getting_Started).
 Tripal's primary goals are: 
 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
 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.
 can facility creation of an online site for display, search and visualization.
 2. To use community-derived standards and ontologies to facility continuity
 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);
   $day = preg_replace("/^\d+-\d+-0?(\d+) .*/", "$1", $default_time);
   // If the time is not set, use current time
   // If the time is not set, use current time
   if (!$default_time) {
   if (!$default_time) {
-    $default_time = REQUEST_TIME;
+    $default_time = time();
     $year  = format_date($default_time, 'custom', 'Y');
     $year  = format_date($default_time, 'custom', 'Y');
     $month = format_date($default_time, 'custom', 'n');
     $month = format_date($default_time, 'custom', 'n');
     $day   = format_date($default_time, 'custom', 'j');
     $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.
     // Allow modules to add fields to the new bundle.
     $modules = module_implements('bundle_create_fields');
     $modules = module_implements('bundle_create_fields');
     foreach ($modules as $module) {
     foreach ($modules as $module) {
-      $function = $module . '_bundle_create_fields';
+      $function = $module . '_bundle_fields_info';
       $info = $function('TripalEntity', $bundle);
       $info = $function('TripalEntity', $bundle);
       foreach ($info as $field_name => $details) {
       foreach ($info as $field_name => $details) {
         $field_type = $details['type'];
         $field_type = $details['type'];
@@ -359,7 +359,7 @@ function tripal_create_bundle($args, &$error = '') {
     // Allow modules to add instances to the new bundle.
     // Allow modules to add instances to the new bundle.
     $modules = module_implements('bundle_create_instances');
     $modules = module_implements('bundle_create_instances');
     foreach ($modules as $module) {
     foreach ($modules as $module) {
-      $function = $module . '_bundle_create_instances';
+      $function = $module . '_bundle_instances_info';
       $info = $function('TripalEntity', $bundle);
       $info = $function('TripalEntity', $bundle);
       foreach ($info as $field_name => $details) {
       foreach ($info as $field_name => $details) {
         // If the field is already attached to this bundle then skip it.
         // 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.
     // Allow modules to add fields to the new bundle.
     $modules = module_implements('bundle_create_fields');
     $modules = module_implements('bundle_create_fields');
     foreach ($modules as $module) {
     foreach ($modules as $module) {
-      $function = $module . '_bundle_create_fields';
+      $function = $module . '_bundle_fields_info';
       $info = $function('TripalEntity', $bundle);
       $info = $function('TripalEntity', $bundle);
       foreach ($info as $field_name => $details) {
       foreach ($info as $field_name => $details) {
 
 
@@ -510,7 +510,7 @@ function tripal_tripal_cron_notification() {
     // Allow modules to add instances to the new bundle.
     // Allow modules to add instances to the new bundle.
     $modules = module_implements('bundle_create_instances');
     $modules = module_implements('bundle_create_instances');
     foreach ($modules as $module) {
     foreach ($modules as $module) {
-      $function = $module . '_bundle_create_instances';
+      $function = $module . '_bundle_instances_info';
       $info = $function('TripalEntity', $bundle);
       $info = $function('TripalEntity', $bundle);
       foreach ($info as $field_name => $details) {
       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.
   // Allow modules to add fields to the new bundle.
   $modules = module_implements('bundle_create_fields');
   $modules = module_implements('bundle_create_fields');
   foreach ($modules as $module) {
   foreach ($modules as $module) {
-    $function = $module . '_bundle_create_fields';
+    $function = $module . '_bundle_fields_info';
     $info = $function('TripalEntity', $bundle);
     $info = $function('TripalEntity', $bundle);
     foreach ($info as $field_name => $details) {
     foreach ($info as $field_name => $details) {
       $field_type = $details['type'];
       $field_type = $details['type'];
@@ -599,7 +599,7 @@ function tripal_refresh_bundle_fields($bundle_name) {
   // Allow modules to add instances to the new bundle.
   // Allow modules to add instances to the new bundle.
   $modules = module_implements('bundle_create_instances');
   $modules = module_implements('bundle_create_instances');
   foreach ($modules as $module) {
   foreach ($modules as $module) {
-    $function = $module . '_bundle_create_instances';
+    $function = $module . '_bundle_instances_info';
     $info = $function('TripalEntity', $bundle);
     $info = $function('TripalEntity', $bundle);
     foreach ($info as $field_name => $details) {
     foreach ($info as $field_name => $details) {
       // If the field is already attached to this bundle then skip it.
       // 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,
     'modulename' => $modulename,
     'callback' => $callback,
     'callback' => $callback,
     'status' => 'Waiting',
     'status' => 'Waiting',
-    'submit_date' => REQUEST_TIME,
+    'submit_date' => time(),
     'uid' => $uid,
     'uid' => $uid,
     # The lower the number the higher the priority.
     # The lower the number the higher the priority.
     'priority' => $priority,
     'priority' => $priority,
@@ -212,7 +212,7 @@ function tripal_is_job_running() {
       // the job is not running so terminate it
       // the job is not running so terminate it
       $record = new stdClass();
       $record = new stdClass();
       $record->job_id = $job->job_id;
       $record->job_id = $job->job_id;
-      $record->end_time = REQUEST_TIME;
+      $record->end_time = time();
       $record->status = 'Error';
       $record->status = 'Error';
       $record->error_msg = 'Job has terminated unexpectedly.';
       $record->error_msg = 'Job has terminated unexpectedly.';
       drupal_write_record('tripal_jobs', $record, 'job_id');
       drupal_write_record('tripal_jobs', $record, 'job_id');
@@ -223,6 +223,47 @@ function tripal_is_job_running() {
   return FALSE;
   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)
  * 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) {
   if ($job->start_time == 0) {
     $record = new stdClass();
     $record = new stdClass();
     $record->job_id = $job->job_id;
     $record->job_id = $job->job_id;
-    $record->end_time = REQUEST_TIME;
+    $record->end_time = time();
     $record->status = 'Cancelled';
     $record->status = 'Cancelled';
     $record->progress = '0';
     $record->progress = '0';
     drupal_write_record('tripal_jobs', $record, 'job_id');
     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
  *   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
  *   job needs to be launched and this argument will allow it.  Only jobs
  *   which have not been run previously will run.
  *   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
  * @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
   // first check if any jobs are currently running
   // if they are, don't continue, we don't want to have
   // if they are, don't continue, we don't want to have
   // more than one job script running at a time
   // more than one job script running at a time
   if (!$do_parallel and tripal_is_job_running()) {
   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;
     return;
   }
   }
 
 
@@ -341,6 +391,7 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL) {
             "ORDER BY priority ASC,job_id ASC";
             "ORDER BY priority ASC,job_id ASC";
     $job_res = db_query($sql);
     $job_res = db_query($sql);
   }
   }
+  print "There are " . $job_res->rowCount() . " jobs queued.\n";
   foreach ($job_res as $job) {
   foreach ($job_res as $job) {
 
 
     // Include the necessary files
     // 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
     // set the start time for this job
     $record = new stdClass();
     $record = new stdClass();
     $record->job_id = $job->job_id;
     $record->job_id = $job->job_id;
-    $record->start_time = REQUEST_TIME;
+    $record->start_time = time();
     $record->status = 'Running';
     $record->status = 'Running';
     $record->pid = getmypid();
     $record->pid = getmypid();
     drupal_write_record('tripal_jobs', $record, 'job_id');
     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";
     print "Calling: $callback(" . implode(", ", $string_args) . ")\n";
     call_user_func_array($callback, $args);
     call_user_func_array($callback, $args);
     // set the end time for this job
     // set the end time for this job
-    $record->end_time = REQUEST_TIME;
+    $record->end_time = time();
     $record->status = 'Completed';
     $record->status = 'Completed';
     $record->progress = '100';
     $record->progress = '100';
     drupal_write_record('tripal_jobs', $record, 'job_id');
     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
     // 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'){
   if($field_or_instance == 'field'){
-    $function = $module . '_bundle_create_fields';
+    $function = $module . '_bundle_fields_info';
     $info = $function('TripalEntity', $bundle);
     $info = $function('TripalEntity', $bundle);
     foreach ($info as $field_name => $details) {
     foreach ($info as $field_name => $details) {
       if($details['field_name'] == $field_name_note) {
       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'){
   else if($field_or_instance == 'instance'){
-    $function = $module . '_bundle_create_instances';
+    $function = $module . '_bundle_instances_info';
     $info = $function('TripalEntity', $bundle);
     $info = $function('TripalEntity', $bundle);
     foreach ($info as $field_name => $details) {
     foreach ($info as $field_name => $details) {
       if($details['field_name'] == $field_name_note) {
       if($details['field_name'] == $field_name_note) {

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


BIN=BIN
tripal/theme/images/powered_by_tripal.png


BIN=BIN
tripal/theme/images/powered_by_tripal_bw.png


BIN=BIN
tripal/theme/images/powered_by_tripal_bw_small.png


BIN=BIN
tripal/theme/images/powered_by_tripal_small.png


BIN=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.'),
     '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(
     'examples' => array(
       'Single Job' => 'drush trp-run-jobs --username=administrator',
       '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(),
     'arguments' => array(),
     'options' => 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.'),
       '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'),
       '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(
   $items['trp-rerun-job'] = array(
     'description' => dt('Re-run a specific job from the queue.'),
     'description' => dt('Re-run a specific job from the queue.'),
     'examples' => array(
     'examples' => array(
       'Single Job' => 'drush trp-rerun-job --username=administrator --job_id=2',
       '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(),
     'arguments' => array(),
     'options' => array(
     'options' => array(
@@ -100,6 +104,8 @@ function tripal_drush_command() {
         'required' => TRUE,
         '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.'),
       '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() {
 function drush_tripal_trp_run_jobs() {
   $parallel = drush_get_option('parallel');
   $parallel = drush_get_option('parallel');
   $job_id   = drush_get_option('job_id');
   $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
   // Unfortunately later versions of Drush use the '--user' argument which
   // makes it incompatible with how Tripal was using it.  For backwards
   // 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_tripal_set_user($username);
 
 
+  drush_print("\n" . date('Y-m-d H:i:s'));
   if ($parallel) {
   if ($parallel) {
     drush_print("Tripal Job Launcher (in 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("Running as user '$username'");
     drush_print("-------------------");
     drush_print("-------------------");
-    tripal_launch_job($parallel, $job_id);
+    tripal_launch_job($parallel, $job_id, $max_jobs, $single);
   }
   }
   else {
   else {
     drush_print("Tripal Job Launcher");
     drush_print("Tripal Job Launcher");
     drush_print("Running as user '$username'");
     drush_print("Running as user '$username'");
     drush_print("-------------------");
     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');
   $parallel = drush_get_option('parallel');
   $job_id   = drush_get_option('job_id');
   $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);
   drush_tripal_set_user($username);
   $new_job_id = tripal_rerun_job($job_id, FALSE);
   $new_job_id = tripal_rerun_job($job_id, FALSE);
 
 
+  drush_print("\n" . date('Y-m-d H:i:s'));
   if ($parallel) {
   if ($parallel) {
     drush_print("Tripal Job Launcher (in parallel)");
     drush_print("Tripal Job Launcher (in parallel)");
     drush_print("Running as user '$username'");
     drush_print("Running as user '$username'");
     drush_print("-------------------");
     drush_print("-------------------");
-    tripal_launch_job($parallel, $new_job_id);
+    tripal_launch_job($parallel, $new_job_id, $max_jobs, $single);
   }
   }
   else {
   else {
     drush_print("Tripal Job Launcher");
     drush_print("Tripal Job Launcher");
     drush_print("Running as user '$username'");
     drush_print("Running as user '$username'");
     drush_print("-------------------");
     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" .
         "Module: " . $job->modulename . "\n" .
         "Callback: " . $job->callback . "\n" .
         "Callback: " . $job->callback . "\n" .
         "Process ID: " . $job->pid . "\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);
     drush_print($output);
   }
   }
   if (!$job_pid) {
   if (!$job_pid) {

+ 76 - 0
tripal/tripal.module

@@ -654,6 +654,11 @@ function tripal_block_info() {
       'administrative' => TRUE,
       'administrative' => TRUE,
     ),
     ),
   );
   );
+
+  $blocks['powered_by_tripal'] = array(
+    'info' => t('Powered by Tripal'),
+    'cache' => DRUPAL_NO_CACHE,
+  );
   return $blocks;
   return $blocks;
 }
 }
 
 
@@ -663,6 +668,27 @@ function tripal_block_info() {
 function tripal_block_view($delta = ''){
 function tripal_block_view($delta = ''){
   // The $delta parameter tells us which block is being requested.
   // The $delta parameter tells us which block is being requested.
   switch ($delta) {
   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':
     case 'notifications_block':
       // Create your block content here
       // Create your block content here
       $block['content'] = '';
       $block['content'] = '';
@@ -738,4 +764,54 @@ function tripal_block_view($delta = ''){
       break;
       break;
   }
   }
   return $block;
   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
  * @param string $chado_table
- *   the chado_table where the record is stored
+ *   The chado_table where the record is stored.
  * @param integer $record_id
  * @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
- *   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) {
 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')
     db_select('chado_bundle', 'CB')
     ->fields('CB', array('type_column'))
     ->fields('CB', array('type_column'))
     ->condition('data_table', $chado_table)
     ->condition('data_table', $chado_table)
     ->execute()
     ->execute()
     ->fetchField();
     ->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;
   $bundle_id = NULL;
   if ($type_column) {
   if ($type_column) {
     $schema = chado_get_schema($chado_table);
     $schema = chado_get_schema($chado_table);
@@ -346,48 +346,48 @@ function tripal_get_chado_entity_id ($chado_table, $record_id) {
     $type_id = NULL;
     $type_id = NULL;
     if (key_exists($type_column, $schema['fields'])) {
     if (key_exists($type_column, $schema['fields'])) {
       $type_id =
       $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) {
     if ($type_id) {
       $bundle_id =
       $bundle_id =
         db_select('chado_bundle', 'CB')
         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 {
   else {
-    $bundle_id = 
+    $bundle_id =
       db_select('chado_bundle', 'CB')
       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;
   $entity_id = NULL;
   if ($bundle_id) {
   if ($bundle_id) {
-    $table_name = 
+    $table_name =
       db_select('tripal_bundle', 'TB')
       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')
       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;
   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();
         $count = $results->fetchObject();
         $record = new stdClass();
         $record = new stdClass();
         $record->mview_id = $mview_id;
         $record->mview_id = $mview_id;
-        $record->last_update = REQUEST_TIME;
+        $record->last_update = time();
         $record->status = "Populated with " . number_format($count->cnt) . " rows";
         $record->status = "Populated with " . number_format($count->cnt) . " rows";
         drupal_write_record('tripal_mviews', $record, 'mview_id');
         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) {
   public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
     parent::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'];
     $field_name = $this->field['field_name'];
 
 
     // Get the FK column that links to the base table.
     // 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.
     // Get the field defaults.
     $record_id = '';
     $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 = '';
     $contact_id = '';
     $name = '';
     $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
     // type. This will create form elements when editing the field instance
     // to allow the site admin to change the term settings above.
     // to allow the site admin to change the term settings above.
     'term_fixed' => FALSE,
     'term_fixed' => FALSE,
+    'relationships' => array(
+      'option1_vocabs' => '',
+      'option2_vocab' => '',
+      'option2_parent' => '',
+      'relationship_types' => '',
+    ),
   );
   );
 
 
   // The default widget for this field.
   // The default widget for this field.
@@ -549,7 +555,6 @@ class sbo__relationship extends ChadoField {
       '#default_value' => $this->instance['settings']['relationships']['option1_vocabs'],
       '#default_value' => $this->instance['settings']['relationships']['option1_vocabs'],
       // TODO add ajax here so that the relationship autocomplete below works
       // TODO add ajax here so that the relationship autocomplete below works
     );
     );
-
     $element['relationships']['option2'] = array(
     $element['relationships']['option2'] = array(
       '#type' => 'item',
       '#type' => 'item',
       '#title' => '<b>Option #2</b>',
       '#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);
     parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
 
 
     // Get the field settings.
     // Get the field settings.
-    $entity = $form['#entity'];
     $field_name = $this->field['field_name'];
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];
     $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) {
   public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
     parent::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'];
     $field_name = $this->field['field_name'];
 
 
     // Get the FK column that links to the base table.
     // 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.
     // Get the field defaults.
     $record_id = '';
     $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 = '';
     $synonym_id = '';
     $pub_id = '';
     $pub_id = '';
     $is_current = TRUE;
     $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,
       'return_array' => 1,
     );
     );
     $record = chado_expand_var($record, 'table', $linker_table, $options);
     $record = chado_expand_var($record, 'table', $linker_table, $options);
-
     if (count($record->$linker_table) > 0) {
     if (count($record->$linker_table) > 0) {
       $i = 0;
       $i = 0;
       foreach ($record->$linker_table as $index => $linker) {
       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);
     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) {
     if (count($list_items) > 1) {
       $list = array(
       $list = array(
         'title' => '',
         '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) {
   public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
     parent::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'];
     $field_name = $this->field['field_name'];
 
 
     // Get the FK column that links to the base table.
     // Get the FK column that links to the base table.
@@ -26,7 +26,7 @@ class schema__publication_widget extends ChadoFieldWidget {
 
 
     // Get the field defaults.
     // Get the field defaults.
     $record_id = '';
     $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 = '';
     $pub_id = '';
     $uname = '';
     $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) {
   if ($days) {
     // get the date of the day suggested
     // get the date of the day suggested
-    $past_timestamp = REQUEST_TIME - ($days * 86400);
+    $past_timestamp = time() - ($days * 86400);
     $past_date = getdate($past_timestamp);
     $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]))";
     $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') {
   if ($table == 'stock') {
     $format[] = array(
     $format[] = array(
-      'format' => '[stock__name]',
+      'format' => '[schema__name]',
       'weight' => -5
       '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().
  * Implements hook_field_storage_query().
  */
  */
 function tripal_chado_field_storage_query($query) {
 function tripal_chado_field_storage_query($query) {
-dpm($query);
+
   // Initialize the result array.
   // Initialize the result array.
   $result = array(
   $result = array(
     'TripalEntity' => array()
     'TripalEntity' => array()

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

@@ -1,12 +1,12 @@
 <?php
 <?php
 
 
 /**
 /**
- * Implements hook_bundle_create_fields().
+ * Implements hook_bundle_fields_info().
  *
  *
  * This is a Tripal defined hook that supports integration with the
  * This is a Tripal defined hook that supports integration with the
  * TripalEntity field.
  * 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')
   $chado_bundle = db_select('chado_bundle', 'cb')
     ->fields('cb')
     ->fields('cb')
@@ -25,13 +25,13 @@ function tripal_chado_bundle_create_fields($entity_type, $bundle) {
   $info = array();
   $info = array();
 
 
   // Create the fields for each column in the table.
   // 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.
   // 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.
   // 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;
   return $info;
 
 
@@ -40,7 +40,7 @@ function tripal_chado_bundle_create_fields($entity_type, $bundle) {
  *
  *
  * @param unknown $details
  * @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'];
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_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
  * @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'];
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
   $type_table = $details['chado_type_table'];
   $type_field = $details['chado_type_column'];
   $type_field = $details['chado_type_column'];
@@ -357,7 +357,7 @@ function tripal_chado_bundle_create_fields_custom(&$info, $details, $entity_type
  *
  *
  * @param unknown $details
  * @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'];
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_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
  * This is a Tripal defined hook that supports integration with the
  * TripalEntity field.
  * 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')
   $chado_bundle = db_select('chado_bundle', 'cb')
     ->fields('cb')
     ->fields('cb')
@@ -602,9 +602,9 @@ function tripal_chado_bundle_create_instances($entity_type, $bundle) {
   );
   );
 
 
   $info = array();
   $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;
   return $info;
 
 
@@ -620,7 +620,7 @@ function tripal_chado_bundle_create_instances($entity_type, $bundle) {
  * @param $bundle
  * @param $bundle
  * @param $details
  * @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();
   $fields = array();
 
 
   // Get Chado information
   // Get Chado information
@@ -827,7 +827,7 @@ function tripal_chado_bundle_create_instances_base(&$info, $entity_type, $bundle
  * @param $bundle
  * @param $bundle
  * @param $details
  * @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'];
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_table'];
   $type_table = $details['chado_type_table'];
   $type_field = $details['chado_type_column'];
   $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 $bundle
  * @param unknown $details
  * @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'];
   $table_name = $details['chado_table'];
   $type_table = $details['chado_type_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
         visitors can continue to visit the Tripal v2 pages. Tripal
         v3 content types may remain private while customization is underway.
         v3 content types may remain private while customization is underway.
         Once customization is completed a subsequent step will allow you to
         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';
   $tv2_content_type = 'all';
@@ -130,12 +129,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       // Migrate selection only
       // Migrate selection only
       if ($table == 'organism') {
       if ($table == 'organism') {
         $sql =
         $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();
         $org_count = chado_query($sql)->fetchField();
         if ($org_count > 0) {
         if ($org_count > 0) {
           $key = urldecode('tv3_content_type--OBI--0100026--organism');
           $key = urldecode('tv3_content_type--OBI--0100026--organism');
@@ -149,11 +146,9 @@ function tripal_chado_migrate_form($form, &$form_state) {
       else if ($table == 'analysis') {
       else if ($table == 'analysis') {
         $sql =
         $sql =
         "SELECT count(*)
         "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();
         $ana_count = chado_query($sql)->fetchField();
         if ($ana_count > 0) {
         if ($ana_count > 0) {
           $key = urlencode('tv3_content_type--local--analysis--analysis');
           $key = urlencode('tv3_content_type--local--analysis--analysis');
@@ -166,12 +161,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       }
       }
       else if ($table == 'project') {
       else if ($table == 'project') {
         $sql =
         $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();
         $proj_count = chado_query($sql)->fetchField();
         if ($proj_count > 0) {
         if ($proj_count > 0) {
           $key = urlencode('tv3_content_type--local--project--project');
           $key = urlencode('tv3_content_type--local--project--project');
@@ -184,12 +177,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       }
       }
       else if ($table == 'featuremap') {
       else if ($table == 'featuremap') {
         $sql =
         $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();
         $map_count = chado_query($sql)->fetchField();
         if ($map_count > 0) {
         if ($map_count > 0) {
           $key = urlencode('tv3_content_type--data--1274--map');
           $key = urlencode('tv3_content_type--data--1274--map');
@@ -202,12 +193,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       }
       }
       else if ($table == 'pub') {
       else if ($table == 'pub') {
         $sql =
         $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();
         $proj_count = chado_query($sql)->fetchField();
         if ($proj_count > 0) {
         if ($proj_count > 0) {
           $key = urlencode('tv3_content_type--TPUB--0000002--Publication');
           $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'])) {
       else if (key_exists('cvterm', $fkeys) && key_exists('type_id', $fkeys['cvterm']['columns'])) {
         // Get all Tripal v2 node types from the chad_* linking table
         // Get all Tripal v2 node types from the chad_* linking table
         $sql =
         $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
               FROM {" . $table . "} T
               INNER JOIN public.$tv2_content_type CT ON T.$pkey = CT.$pkey
               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 {cvterm} V ON V.cvterm_id = T.type_id
               INNER JOIN {dbxref} X ON X.dbxref_id = V.dbxref_id
               INNER JOIN {dbxref} X ON X.dbxref_id = V.dbxref_id
               INNER JOIN {db} ON db.db_id = X.db_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";
               GROUP BY V.name, X.accession, db.name";
         $tv3_content_types = chado_query($sql);
         $tv3_content_types = chado_query($sql);
         while($tv3_content_type = $tv3_content_types->fetchObject()) {
         while($tv3_content_type = $tv3_content_types->fetchObject()) {
@@ -260,6 +246,10 @@ function tripal_chado_migrate_form($form, &$form_state) {
       '#name' => 'migrate_btn',
       '#name' => 'migrate_btn',
       '#value' => "Migrate $tv2_options[$tv2_content_type]",
       '#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
   // Step 3
@@ -525,6 +515,10 @@ function tripal_chado_migrate_form_step2_ajax_callback(&$form, &$form_state) {
  *
  *
  * @param boolean $all_option
  * @param boolean $all_option
  *   Include an 'all' option in the returned array
  *   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 string[]
  *  Return a string array keyed by the node type
  *  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
       'bundle_name' => $bundle_name
     );
     );
     tripal_chado_publish_records($value);
     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
     // Migrate organism images
     if ($term->name == 'organism') {
     if ($term->name == 'organism') {
       tripal_chado_migrate_organism_images($bundle_name);
       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()) {
 function tripal_chado_copy_title_for_selected_types($tv2_content_types = array()) {
   foreach ($tv2_content_types AS $type) {
   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()) {
 function tripal_chado_migrate_url_alias_for_selected_types($tv2_content_types = array()) {
   foreach ($tv2_content_types AS $type) {
   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 () {
 function tripal_chado_migrate_organism_images () {
   // Get all organism entities
   // 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'))
     ->fields('ce', array('entity_id', 'record_id', 'nid'))
-    ->condition('data_table', 'organism')
     ->execute();
     ->execute();
-  
+
   // Iterate through each organism entity
   // Iterate through each organism entity
   while ($organism = $results->fetchObject()) {
   while ($organism = $results->fetchObject()) {
     $nid = $organism->nid;
     $nid = $organism->nid;
     $entity_id = $organism->entity_id;
     $entity_id = $organism->entity_id;
-    
+
     // check if there is a file record for the organism node
     // check if there is a file record for the organism node
     $fid = db_select('file_usage', 'fu')
     $fid = db_select('file_usage', 'fu')
     ->fields('fu', array('fid'))
     ->fields('fu', array('fid'))
@@ -839,13 +845,13 @@ function tripal_chado_migrate_organism_images () {
     ->fetchField();
     ->fetchField();
     // check if the image was added using the old interface.
     // check if the image was added using the old interface.
     if (!$fid) {
     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";
           WHERE O.organism_id = :organism_id";
       $chado_org = chado_query($sql, array(':organism_id' => $organism->record_id))->fetchObject();
       $chado_org = chado_query($sql, array(':organism_id' => $organism->record_id))->fetchObject();
-      
+
       if ($chado_org) {
       if ($chado_org) {
         $base_path = realpath('.');
         $base_path = realpath('.');
         $image_dir = tripal_get_files_dir('tripal_organism') . "/images";
         $image_dir = tripal_get_files_dir('tripal_organism') . "/images";
@@ -870,19 +876,19 @@ function tripal_chado_migrate_organism_images () {
         }
         }
         if($file){
         if($file){
           tripal_chado_migrate_organism_image_add_file($file->fid, $entity_id);
           tripal_chado_migrate_organism_image_add_file($file->fid, $entity_id);
-        }        
+        }
       }
       }
     }
     }
     else {
     else {
       // If there is an image, add it to the organism entity
       // If there is an image, add it to the organism entity
       tripal_chado_migrate_organism_image_add_file ($fid, $entity_id);
       tripal_chado_migrate_organism_image_add_file ($fid, $entity_id);
     }
     }
-    
+
   }
   }
 }
 }
 
 
 /**
 /**
- * 
+ *
  * Add image file for the organism entity
  * Add image file for the organism entity
  *
  *
  * @param unknown $fid
  * @param unknown $fid
@@ -905,6 +911,285 @@ function tripal_chado_migrate_organism_image_add_file ($fid, $entity_id) {
     field_attach_update('TripalEntity', $entity);
     field_attach_update('TripalEntity', $entity);
     entity_get_controller('TripalEntity')->resetCache(array($entity_id));
     entity_get_controller('TripalEntity')->resetCache(array($entity_id));
     // Add a record to the field_data_data__image table
     // 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',
     'url' => 'http://edamontology.org/page',
     'urlprefix' => 'http://edamontology.org/{db}_{accession}',
     '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(
   tripal_insert_db(array(
     'name' => 'EDAM',
     'name' => 'EDAM',
     'description' => 'Bioinformatics operations, data types, formats, identifiers and topics.',
     '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}',
     'urlprefix' => 'http://edamontology.org/{db}_{accession}',
   ));
   ));
   tripal_insert_cv(
   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(
   $term = tripal_insert_cvterm(array(
     'id' => 'data:1249',
     'id' => 'data:1249',
     'name' => 'Sequence length',
     'name' => 'Sequence length',

+ 1 - 0
tripal_chado/tripal_chado.info

@@ -15,4 +15,5 @@ stylesheets[all][] = theme/css/tripal_chado.css
 dependencies[] = tripal
 dependencies[] = tripal
 dependencies[] = date
 dependencies[] = date
 dependencies[] = image
 dependencies[] = image
+dependencies[] = link
 dependencies[] = tripal_chado_views
 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
   // Map cvterm usage to chado tables
   $schema['chado_cvterm_mapping'] = tripal_chado_chado_cvterm_mapping_schema();
   $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;
   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()) {
     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";
       $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 {
     else {
       $sql = "CREATE UNIQUE INDEX tripal_cv_obo_pkey2 ON tripal_cv_obo2 USING btree (obo_id)";
       $sql = "CREATE UNIQUE INDEX tripal_cv_obo_pkey2 ON tripal_cv_obo2 USING btree (obo_id)";
     }
     }
     db_query($sql);
     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')) {
   if (db_table_exists('tripal_pub_import')) {
     // Move the tripal_pub_import table out of the way.
     // Move the tripal_pub_import table out of the way.
     $sql = "ALTER TABLE tripal_pub_import RENAME TO tripal_pub_import2";
     $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);
     db_query($sql);
     $sql = "ALTER INDEX tripal_cv_obo_pkey2 RENAME TO tripal_cv_obo_pkey";
     $sql = "ALTER INDEX tripal_cv_obo_pkey2 RENAME TO tripal_cv_obo_pkey";
     db_query($sql);
     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);
     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
   // tripal_pub_import
   if (db_table_exists('tripal_pub_import2')) {
   if (db_table_exists('tripal_pub_import2')) {
@@ -742,3 +755,39 @@ function tripal_chado_update_7301() {
     throw new DrupalUpdateException('Could not perform update: '. $error);
     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);
+  }
+}