Browse Source

Finishgin up TripalJob and TripalImporter classes'

Stephen Ficklin 8 years ago
parent
commit
90bd7cd4e7

+ 6 - 4
tripal/api/tripal.importer.api.inc

@@ -88,7 +88,7 @@ function tripal_load_include_importer_class($class) {
  *   The ID of the import record.
  *   The ID of the import record.
  * @throws Exception
  * @throws Exception
  */
  */
-function tripal_run_importer($import_id, $job_id = NULL) {
+function tripal_run_importer($import_id, TripalJob $job = NULL) {
   $details = db_select('tripal_import', 'ti')
   $details = db_select('tripal_import', 'ti')
     ->fields('ti')
     ->fields('ti')
     ->condition('ti.import_id', $import_id)
     ->condition('ti.import_id', $import_id)
@@ -107,8 +107,9 @@ function tripal_run_importer($import_id, $job_id = NULL) {
     $class = $details->class;
     $class = $details->class;
     tripal_load_include_importer_class($class);
     tripal_load_include_importer_class($class);
     if (class_exists($class)) {
     if (class_exists($class)) {
+
       $loader_name = $class::$name;
       $loader_name = $class::$name;
-      $loader = new $class();
+      $loader = new $class($job);
       try {
       try {
 
 
         // begin the transaction
         // begin the transaction
@@ -117,13 +118,14 @@ function tripal_run_importer($import_id, $job_id = NULL) {
             "If the load fails or is terminated prematurely then the entire set of \n" .
             "If the load fails or is terminated prematurely then the entire set of \n" .
             "insertions/updates is rolled back and will not be found in the database\n\n";
             "insertions/updates is rolled back and will not be found in the database\n\n";
         $loader->preRun($details);
         $loader->preRun($details);
-        $loader->run($details, $job_id);
+        $loader->run($details);
         $loader->postRun($details);
         $loader->postRun($details);
+        $job->logMessage("Done");
+        print "\nDone\n";
 
 
         // Check for new fields and notify the user.
         // Check for new fields and notify the user.
         tripal_tripal_cron_notification();
         tripal_tripal_cron_notification();
 
 
-        print "\nDone\n";
       }
       }
       catch (Exception $e) {
       catch (Exception $e) {
         $transaction->rollback();
         $transaction->rollback();

+ 148 - 179
tripal/api/tripal.jobs.api.inc

@@ -80,77 +80,41 @@
 function tripal_add_job($job_name, $modulename, $callback, $arguments, $uid,
 function tripal_add_job($job_name, $modulename, $callback, $arguments, $uid,
     $priority = 10, $includes = array()) {
     $priority = 10, $includes = array()) {
 
 
-  if (!$job_name) {
-    watchdog('tripal', "Must provide a \$job_name argument to the tripal_add_job() function.");
-    return FALSE;
-  }
-  if (!$modulename) {
-    watchdog('tripal', "Must provide a \$modulename argument to the tripal_add_job() function.");
-    return FALSE;
-  }
-  if (!$callback) {
-    watchdog('tripal', "Must provide a \$callback argument to the tripal_add_job() function.");
-    return FALSE;
-  }
-  foreach ($includes as $include) {
-    require_once($include);
-  }
-  if (!function_exists($callback)) {
-    watchdog('tripal', "Must provide a valid callback function to the tripal_add_job() function.");
-    return FALSE;
-  }
-  if (!is_numeric($uid)) {
-    watchdog('tripal', "Must provide a numeric \$uid argument to the tripal_add_job() function.");
-    return FALSE;
-  }
-  if (!$priority or !is_numeric($priority) or $priority < 1 or $priority > 10) {
-    watchdog('tripal', "Must provide a numeric \$priority argument between 1 and 10 to the tripal_add_job() function.");
-    return FALSE;
-  }
-  if (!is_array($arguments)) {
-    watchdog('tripal', "Must provide an array as the \$arguments argument to the tripal_add_job() function.");
-    return FALSE;
-  }
-
   $user = user_load($uid);
   $user = user_load($uid);
 
 
-  // convert the arguments into a string for storage in the database
-  $args = array();
-  if (is_array($arguments)) {
-    $args = serialize($arguments);
-  }
-
-  $job_id = db_insert('tripal_jobs')
-  ->fields(array(
-    'job_name' => $job_name,
-    'modulename' => $modulename,
-    'callback' => $callback,
-    'status' => 'Waiting',
-    'submit_date' => time(),
-    'uid' => $uid,
-    # The lower the number the higher the priority.
-    'priority' => $priority,
-    'arguments' => $args,
-    'includes' => serialize($includes),
-  ))
-  ->execute();
-
-  if ($job_id) {
+  try {
+    $job = new TripalJob();
+    $job->create(array(
+      'job_name' => $job_name,
+      'modulename' => $modulename,
+      'callback' => $callback,
+      'arguments' => $arguments,
+      'uid' => $uid,
+      'priority' => $priority,
+      'includes' => $includes,
+    ));
+
+    // If no exceptions were thrown then we know the creation worked.  So
+    // let the user know!
     drupal_set_message(t("Job '%job_name' submitted.", array('%job_name' => $job_name)));
     drupal_set_message(t("Job '%job_name' submitted.", array('%job_name' => $job_name)));
+
+    // If this is the Tripal admin user then give a bit more information
+    // about how to run the job.
     if (user_access('administer tripal')) {
     if (user_access('administer tripal')) {
       $jobs_url = url("admin/tripal/tripal_jobs");
       $jobs_url = url("admin/tripal/tripal_jobs");
       drupal_set_message(t("Check the <a href='!jobs_url'>jobs page</a> for status.",
       drupal_set_message(t("Check the <a href='!jobs_url'>jobs page</a> for status.",
-        array('!jobs_url' => $jobs_url)));
+          array('!jobs_url' => $jobs_url)));
       drupal_set_message(t("You can execute the job queue manually on the command line " .
       drupal_set_message(t("You can execute the job queue manually on the command line " .
-        "using the following Drush command: <br>drush trp-run-jobs --username=%uname --root=%base_path",
-        array('%base_path' => DRUPAL_ROOT, '%uname' => $user->name)));
+          "using the following Drush command: <br>drush trp-run-jobs --username=%uname --root=%base_path",
+          array('%base_path' => DRUPAL_ROOT, '%uname' => $user->name)));
     }
     }
+    return $job->getJobID();
   }
   }
-  else {
-    drupal_set_message(t("Failed to add job %job_name.", array('%job_name' => $job_name)));
+  catch (Exception $e) {
+    tripal_report_error('tripal', TRIPAL_ERROR, $e->getMessage());
+    drupal_set_message($e->getMessage(), 'error');
+    return FALSE;
   }
   }
-
-  return $job_id;
 }
 }
 
 
 /**
 /**
@@ -160,24 +124,22 @@ function tripal_add_job($job_name, $modulename, $callback, $arguments, $uid,
  *   The unique identifier of the job
  *   The unique identifier of the job
  *
  *
  * @return
  * @return
- *   An object describing the job if a job is found or FALSE on failure.
+ *   An object representing a record from the tripal_job table or FALSE on
+ *   failure.
  *
  *
  * @ingroup tripal_jobs_api
  * @ingroup tripal_jobs_api
  */
  */
 function tripal_get_job($job_id) {
 function tripal_get_job($job_id) {
-  if (!$job_id or !is_numeric($job_id)) {
-    watchdog('tripal', "Must provide a numeric \$job_id to the tripal_cancel_job() function.");
+  try {
+    $job = new TripalJob();
+    $job->load($job_id);
+    return $job->getJob();
+  }
+  catch (Exception $e) {
+    tripal_report_error('tripal', TRIPAL_ERROR, $e->getMessage());
+    drupal_set_message($e->getMessage(), 'error');
     return FALSE;
     return FALSE;
   }
   }
-
-  $job = db_query('SELECT j.* FROM {tripal_jobs} j WHERE j.job_id=:job_id', array(':job_id' => $job_id))
-    ->fetchObject();
-
-  $job->submit_date_string = $job->submit_date ? format_date($job->submit_date) : '';
-  $job->start_time_string = $job->start_time ? format_date($job->start_time): '';
-  $job->end_time_string = $job->end_time ? format_date($job->end_time): '';
-
-  return $job;
 }
 }
 
 
 /**
 /**
@@ -280,24 +242,47 @@ function tripal_rerun_job($job_id, $goto_jobs_page = TRUE) {
 
 
   $user_id = $user->uid;
   $user_id = $user->uid;
 
 
-  $sql = "SELECT * FROM {tripal_jobs} WHERE job_id = :job_id";
-  $results = db_query($sql, array(':job_id' => $job_id));
-  $job = $results->fetchObject();
-  // arguments for jobs used to be stored as plain string with a double colon
-  // separating them.  But as of Tripal v2.0 the arguments are stored as
-  // a serialized array.  To be backwards compatible, we should check for serialization
-  // and if not then we will use the old style
-  $includes = unserialize($job->includes);
-  $args = unserialize($job->arguments);
-  if (!$args) {
-    $args = explode("::", $job->arguments);
+  $job = new TripalJob();
+  $job->load($job_id);
+
+  $arguments = $job->getArguments();
+  $includes = $job->getIncludes();
+
+  $newJob = new Tripaljob();
+  try {
+    $job->create(array(
+      'job_name' => $job->getJobName(),
+      'modulename' => $job->getModuleName(),
+      'callback' => $job->getCallback(),
+      'arguments' => $arguments,
+      'uid' => $user_id,
+      'priority' => $job->getPriority(),
+      'includes' => $includes
+    ));
+    // If no exceptions were thrown then we know the creation worked.  So
+    // let the user know!
+    drupal_set_message(t("Job '%job_name' submitted.", array('%job_name' => $job->getJobName())));
+
+    // If this is the Tripal admin user then give a bit more information
+    // about how to run the job.
+    if (user_access('administer tripal')) {
+      $jobs_url = url("admin/tripal/tripal_jobs");
+      drupal_set_message(t("Check the <a href='!jobs_url'>jobs page</a> for status.",
+          array('!jobs_url' => $jobs_url)));
+      drupal_set_message(t("You can execute the job queue manually on the command line " .
+          "using the following Drush command: <br>drush trp-run-jobs --username=%uname --root=%base_path",
+          array('%base_path' => DRUPAL_ROOT, '%uname' => $user->name)));
+    }
+    if ($goto_jobs_page) {
+      drupal_goto("admin/tripal/tripal_jobs");
+    }
   }
   }
-  $job_id = tripal_add_job($job->job_name, $job->modulename, $job->callback, $args, $user_id, $job->priority, $includes);
-
-  if ($goto_jobs_page) {
-    drupal_goto("admin/tripal/tripal_jobs");
+  catch (Exception $e){
+    drupal_set_message($e->getMessage(), 'error');
+    tripal_report_error('tripal', TRIPAL_ERROR, $e->getMessage());
   }
   }
-  return $job_id;
+
+
 }
 }
 
 
 /**
 /**
@@ -319,28 +304,21 @@ function tripal_cancel_job($job_id, $redirect = TRUE) {
     return FALSE;
     return FALSE;
   }
   }
 
 
-  $sql = "SELECT * FROM {tripal_jobs} WHERE job_id = :job_id";
-  $results = db_query($sql, array(':job_id' => $job_id));
-  $job = $results->fetchObject();
-
-  // set the end time for this job
-  if ($job->start_time == 0) {
-    $record = new stdClass();
-    $record->job_id = $job->job_id;
-    $record->end_time = time();
-    $record->status = 'Cancelled';
-    $record->progress = '0';
-    drupal_write_record('tripal_jobs', $record, 'job_id');
-    drupal_set_message(t("Job #%job_id cancelled", array('%job_id' => $job_id)));
-  }
-  else {
-    drupal_set_message(t("Job %job_id cannot be cancelled. It is in progress or has finished.", array('%job_id' => $job_id)));
-    return FALSE;
+  try {
+    $job = new Tripaljob();
+    $job->load($job_id);
+    $job->cancel();
+
+    drupal_set_message('Job is now cancelled.');
+    drupal_goto("admin/tripal/tripal_jobs");
+    return TRUE;
   }
   }
-  if ($redirect) {
+  catch (Exception $e) {
+    tripal_report_error('tripal', TRIPAL_ERROR, $e->getMessage());
+    drupal_set_message($e->getMessage(), 'error');
     drupal_goto("admin/tripal/tripal_jobs");
     drupal_goto("admin/tripal/tripal_jobs");
+    return FALSE;
   }
   }
-  return TRUE;
 }
 }
 
 
 /**
 /**
@@ -364,9 +342,8 @@ function tripal_cancel_job($job_id, $redirect = TRUE) {
  */
  */
 function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $single = 0) {
 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
+  // 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()) {
   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.\n";
     print "Jobs are still running. Use the --parallel=1 option with the Drush command to run jobs in parallel.\n";
     return;
     return;
@@ -377,55 +354,44 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $si
     return;
     return;
   }
   }
 
 
-  // get all jobs that have not started and order them such that
-  // they are processed in a FIFO manner.
+  // Get all jobs that have not started and order them such that they are
+  // processed in a FIFO manner.
   if ($job_id) {
   if ($job_id) {
-    $sql =  "SELECT * FROM {tripal_jobs} TJ " .
-            "WHERE TJ.start_time IS NULL and TJ.end_time IS NULL and TJ.job_id = :job_id " .
-            "ORDER BY priority ASC,job_id ASC";
-    $job_res = db_query($sql, array(':job_id' => $job_id));
+    $sql =  "
+      SELECT TJ.job_id
+      FROM {tripal_jobs} TJ
+      WHERE
+        TJ.start_time IS NULL AND
+        TJ.end_time IS NULL AND
+        TJ.job_id = :job_id
+      ORDER BY priority ASC, job_id ASC
+    ";
+    $jobs = db_query($sql, array(':job_id' => $job_id));
   }
   }
   else {
   else {
-    $sql =  "SELECT * FROM {tripal_jobs} TJ " .
-            "WHERE TJ.start_time IS NULL and TJ.end_time IS NULL " .
-            "ORDER BY priority ASC,job_id ASC";
-    $job_res = db_query($sql);
+    $sql =  "
+      SELECT TJ.job_id
+      FROM {tripal_jobs} TJ
+      WHERE
+        TJ.start_time IS NULL AND
+        TJ.end_time IS NULL
+      ORDER BY priority ASC,job_id ASC
+    ";
+    $jobs = db_query($sql);
   }
   }
-  print "There are " . $job_res->rowCount() . " jobs queued.\n";
-  foreach ($job_res as $job) {
+  print "There are " . $jobs->rowCount() . " jobs queued.\n";
+  foreach ($jobs as $jid) {
 
 
-    // Include the necessary files
-    foreach (unserialize($job->includes) as $path) {
-      if ($path) {
-        require_once $path;
-      }
-    }
-    // set the start time for this job
-    $record = new stdClass();
-    $record->job_id = $job->job_id;
-    $record->start_time = time();
-    $record->status = 'Running';
-    $record->pid = getmypid();
-    drupal_write_record('tripal_jobs', $record, 'job_id');
-
-    // call the function provided in the callback column.
-    // Add the job_id as the last item in the list of arguments. All
-    // callback functions should support this argument.
-    $callback = $job->callback;
-
-    // arguments for jobs used to be stored as plain string with a double colon
-    // separating them.  But as of Tripal v2.0 the arguments are stored as
-    // a serialized array.  To be backwards compatible, we should check for serialization
-    // and if not then we will use the old style
-    $args = unserialize($job->arguments);
-    if (!$args) {
-      $args = explode("::", $job->arguments);
-    }
-    $args[] = $job->job_id;
+    $job_id = $jid->job_id;
+
+    // Create the Tripoaljob object.
+    $job = new TripalJob();
+    $job->load($job_id);
 
 
     // We need to do some additional processing for printing since the switch
     // We need to do some additional processing for printing since the switch
     // to serialized arrays now allows nested arrays which cause errors when
     // to serialized arrays now allows nested arrays which cause errors when
     // printed using implode alone.
     // printed using implode alone.
+    $args = $job->getArguments();
     $string_args = array();
     $string_args = array();
     foreach ($args as $k => $a) {
     foreach ($args as $k => $a) {
       if (is_array($a)) {
       if (is_array($a)) {
@@ -439,13 +405,16 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $si
       }
       }
     }
     }
 
 
-    print "Calling: $callback(" . implode(", ", $string_args) . ")\n";
-    call_user_func_array($callback, $args);
-    // set the end time for this job
-    $record->end_time = time();
-    $record->status = 'Completed';
-    $record->progress = '100';
-    drupal_write_record('tripal_jobs', $record, 'job_id');
+    // Run the job
+    $callback = $job->getCallback();
+    print "Calling Job #$job_id: $callback(" . implode(", ", $string_args) . ")\n";
+    try {
+      $job->run();
+    }
+    catch (Exception $e) {
+      tripal_report_error('tripal', TRIPAL_ERROR, $e->getMessage());
+      drupal_set_message($e->getMessage(), 'error');
+    }
 
 
     if ($single) {
     if ($single) {
       // Don't start any more jobs
       // Don't start any more jobs
@@ -455,7 +424,7 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $si
       break;
       break;
     }
     }
 
 
-    // send an email to the user advising that the job has finished
+    // TODO: Send an email to the user advising that the job has finished
   }
   }
 }
 }
 
 
@@ -474,16 +443,17 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $si
  */
  */
 function tripal_set_job_progress($job_id, $percentage) {
 function tripal_set_job_progress($job_id, $percentage) {
 
 
-  if (preg_match("/^(\d+|100)$/", $percentage)) {
-    $record = new stdClass();
-    $record->job_id = $job_id;
-    $record->progress = $percentage;
-    if (drupal_write_record('tripal_jobs', $record, 'job_id')) {
-      return TRUE;
-    }
+  try {
+    $job = new TripalJob();
+    $job->load($job_id);
+    $job->setProgress($percentage);
   }
   }
-
-  return FALSE;
+  catch (Exception $e) {
+    tripal_report_error('tripal', TRIPAL_ERROR, $e->getMessage());
+    drupal_set_message($e->getMessage(), 'error');
+    return FALSE;
+  }
+  return TRUE;
 }
 }
 
 
 /**
 /**
@@ -494,22 +464,21 @@ function tripal_set_job_progress($job_id, $percentage) {
  *
  *
  * @return
  * @return
  *   A value between 0 and 100 indicating the percentage complete of the job.
  *   A value between 0 and 100 indicating the percentage complete of the job.
+ *   FALSE on failure.
  */
  */
 function tripal_get_job_progress($job_id) {
 function tripal_get_job_progress($job_id) {
 
 
-  if (!$job_id) {
-    watchdog('tripal', "Must provide a \$$job_id argument to the tripal_get_job_progress() function.");
+  try {
+    $job = new TripalJob();
+    $job->load($job_id);
+    $progress = $job->getProgress();
+    return $progress;
+  }
+  catch (Exception $e) {
+    tripal_report_error('tripal', TRIPAL_ERROR, $e->getMessage());
+    drupal_set_message($e->getMessage(), 'error');
     return FALSE;
     return FALSE;
   }
   }
-
-  // Get the progress.
-  $progress = db_select('tripal_jobs', 'tj')
-    ->fields('tj', array('progress'))
-    ->condition('job_id', $job_id)
-    ->execute()
-    ->fetchField();
-
-  return $progress;
 }
 }
 /**
 /**
  * Returns a list of jobs that are active.
  * Returns a list of jobs that are active.

+ 4 - 3
tripal/api/tripal.notice.api.inc

@@ -29,9 +29,10 @@ define('TRIPAL_DEBUG',7);
 
 
 
 
 /**
 /**
- * Provide better error notice for Tripal. If the environment variable
- * 'TRIPAL_DEBUG' is set to 1 then this function will add backtrace
- * information to the message.
+ * Provide better error notice for Tripal.
+ *
+ * If the environment variable 'TRIPAL_DEBUG' is set to 1 then this function
+ * will add backtrace information to the message.
  *
  *
  * @param $type
  * @param $type
  *   The catagory to which this message belongs. Can be any string, but the
  *   The catagory to which this message belongs. Can be any string, but the

+ 180 - 6
tripal/includes/TripalImporter.inc

@@ -1,5 +1,6 @@
 <?php
 <?php
 class TripalImporter {
 class TripalImporter {
+
   // --------------------------------------------------------------------------
   // --------------------------------------------------------------------------
   //                     EDITABLE STATIC CONSTANTS
   //                     EDITABLE STATIC CONSTANTS
   //
   //
@@ -43,6 +44,61 @@ class TripalImporter {
    */
    */
   public static $upload_title = 'File Upload';
   public static $upload_title = 'File Upload';
 
 
+  /**
+   * If the loader should require an analysis record.  To maintain provenance
+   * we should always indiate where the data we are uploading comes from.
+   * The method that Tripal attempts to use for this by associating upload files
+   * with an analysis record.  The analysis record provides the details for
+   * how the file was created or obtained. Set this to FALSE if the loader
+   * should not require an analysis when loading. if $use_analysis is set to
+   * true then the form values will have an 'analysis_id' key in the $form_state
+   * array on submitted forms.
+   */
+  public static $use_analysis = TRUE;
+
+  /**
+   * If the $use_analysis value is set above then this value indicates if the
+   * analysis should be required.
+   */
+  public static $require_analysis = TRUE;
+
+
+  // --------------------------------------------------------------------------
+  //                  PRIVATE MEMBERS -- DO NOT EDIT
+  // --------------------------------------------------------------------------
+  /**
+   * The job that this importer is associated with.  This is needed for
+   * updating the status of the job.
+   */
+  private $job = NULL;
+
+  /**
+   * The number of items that this importer needs to process. A progress
+   * can be calculated by dividing the number of items process by this
+   * number.
+   */
+  private $total_items = 0;
+
+  /**
+   * The number of items that have been handled so far.  This must never
+   * be below 0 and never exceed $total_items;
+   */
+  private $num_handled = 0;
+
+  /**
+   * The interval when the job progress should be updated. Updating the job
+   * progress incurrs a database write which takes time and if it occurs to
+   * frequently can slow down the loader.  This should be a value between
+   * 0 and 100 to indicate a percent interval (e.g. 1 means update the
+   * progress every time the num_handled increases by 1%).
+   */
+  private $interval = 1;
+
+  /**
+   * Each time the job progress is updated this variable gets set.  It is
+   * used to calculate if the $interval has passed for the next update.
+   */
+  private $prev_update = 0;
 
 
   // --------------------------------------------------------------------------
   // --------------------------------------------------------------------------
   //                          CONSTRUCTORS
   //                          CONSTRUCTORS
@@ -50,10 +106,11 @@ class TripalImporter {
   /**
   /**
    * Instantiates a new TripalImporter object.
    * Instantiates a new TripalImporter object.
    *
    *
-   * @param $job_id
+   * @param TripalJob $job
+   *   An optional TripalJob object that this loader is associated with.
    */
    */
-  public function __construct() {
-
+  public function __construct(TripalJob $job = NULL) {
+    $this->job = $job;
   }
   }
 
 
   // --------------------------------------------------------------------------
   // --------------------------------------------------------------------------
@@ -66,7 +123,6 @@ class TripalImporter {
   // --------------------------------------------------------------------------
   // --------------------------------------------------------------------------
 
 
   public function form($form, &$form_state) {
   public function form($form, &$form_state) {
-
     return $form;
     return $form;
   }
   }
   public function formSubmit($form, &$form_state) {
   public function formSubmit($form, &$form_state) {
@@ -78,10 +134,128 @@ class TripalImporter {
   public function preRun($details) {
   public function preRun($details) {
 
 
   }
   }
-  public function run($details, $job_id = NULL) {
-
+  public function run($details) {
   }
   }
   public function postRun($details) {
   public function postRun($details) {
 
 
   }
   }
+  /**
+   * Logs a message for the importer.
+   *
+   * There is no distinction between status messages and error logs.  Any
+   * message that is intended for the user to review the status of the loading
+   * can be provided here.  If this importer is associated with a job then
+   * the logging is passed on to the job for storage.
+   *
+   * Messages that are are of severity TRIPAL_CRITICAL or TRIPAL_ERROR
+   * are also logged to the watchdog.
+   *
+   * @param $message
+   *   The message to store in the log. Keep $message translatable by not
+   *   concatenating dynamic values into it! Variables in the message should
+   *   be added by using placeholder strings alongside the variables argument
+   *   to declare the value of the placeholders. See t() for documentation on
+   *   how $message and $variables interact.
+   * @param $variables
+   *   Array of variables to replace in the message on display or NULL if
+   *   message is already translated or not possible to translate.
+   * @param $severity
+   *   The severity of the message; one of the following values:
+   *     - TRIPAL_CRITICAL: Critical conditions.
+   *     - TRIPAL_ERROR: Error conditions.
+   *     - TRIPAL_WARNING: Warning conditions.
+   *     - TRIPAL_NOTICE: Normal but significant conditions.
+   *     - TRIPAL_INFO: (default) Informational messages.
+   *     - TRIPAL_DEBUG: Debug-level messages.
+   */
+  protected function logMessage($message, $variables = array(), $severity = TRIPAL_INFO) {
+    // Generate a translated message.
+    $tmessage = t($message, $variables);
+
+    // For the sake of the command-line user, print the message to the
+    // terminal.
+    print $tmessage . "\n";
+
+    // If we have a job then pass along the messaging to the job.
+    if ($this->job) {
+      $this->job->logMessage($message, $variables, $severity);
+    }
+    // If we don't have a job then just use the drpual_set_message.
+    else {
+      // Report this message to watchdog or set a message.
+      if ($severity == TRIPAL_CRITICAL or $severity == TRIPAL_ERROR) {
+        drupal_set_message($tmessage, 'error');
+      }
+      if ($severity == TRIPAL_WARNING) {
+        drupal_set_message($tmessage, 'warning');
+      }
+    }
+  }
+
+  /**
+   * Sets the total number if items to be processed.
+   *
+   * This should typically be called near the beginning of the loading process
+   * to indicate the number of items that must be processed.
+   *
+   * @param $total_items
+   *   The total number of items to process.
+   */
+  protected function setTotalItems($total_items) {
+     $this->total_items = $total_items;
+  }
+  /**
+   * Adds to the count of the total number of items that have been handle.d
+   * @param unknown $num_handled
+   */
+  protected function addItemsHandled($num_handled) {
+    $this->setItemsHandled($this->num_handled += $num_handled);
+  }
+  /**
+   * Sets the number of items that have been processed.
+   *
+   * This should be called anytime the loader wants to indicate how many
+   * items have been processed.  The amount of progress will be
+   * calculated using this number.  If the amount of items handled exceeds
+   * the interval specified then the progress is reported to the user.  If
+   * this loader is associated with a job then the job progress is also updated.
+   *
+   * @param $total_handled
+   *   The total number of items that have been processed.
+   */
+  protected function setItemsHandled($total_handled) {
+    // First set the number of items handled.
+    $this->num_handled = $total_handled;
+
+    // Now see if we need to report to the user the percent done.  A message
+    // will be printed on the command-line if the job is run there.
+    $percent = sprintf("%.2f", ($this->num_handled / $this->total_items) * 100);
+    $diff = $percent - $this->prev_update;
+    if ($diff >= $interval) {
+      $this->prev_update = $diff;
+      $memory = number_format(memory_get_usage());
+      print "Percent complete: " . $percent . "%. Memory: " . $memory . " bytes.\r";
+
+      // If we have a job the update the job progress too.
+      if ($this->job) {
+        $this->job->setProgress($percent);
+      }
+    }
+  }
+
+  /**
+   * Updates the percent interval when the job progress is updated.
+   *
+   * Updating the job
+   * progress incurrs a database write which takes time and if it occurs to
+   * frequently can slow down the loader.  This should be a value between
+   * 0 and 100 to indicate a percent interval (e.g. 1 means update the
+   * progress every time the num_handled increases by 1%).
+   *
+   * @param $interval
+   *   A number between 0 and 100.
+   */
+  protected function setInterval($interval) {
+    $this->interval = $interval;
+  }
 }
 }

+ 430 - 26
tripal/includes/TripalJob.inc

@@ -3,30 +3,437 @@
 class TripalJob {
 class TripalJob {
 
 
   /**
   /**
-   * A database connection distinct from the transaction used for the job.
-   * This allows for updating the job progress without that progress being
-   * wiped out if the job fails.
+   * The ID of the job.
    */
    */
-  private $logger;
+  private $job_id = NULL;
+
+  /**
+   * Contains the job record for this job.
+   */
+  private $job = NULL;
 
 
   /**
   /**
    * Instantiates a new TripalJob object.
    * Instantiates a new TripalJob object.
    *
    *
-   * @param $job_id
+   * By default the job object is "empty". It must be associated with
+   * job details either by calling the load() function or the
+   * create() function.
    */
    */
   public function __construct() {
   public function __construct() {
-    $logger =
+    $this->log = '';
+  }
+
+  /**
+   * Loads a job for this object.
+   *
+   * @param $job_id
+   *   The ID of the job.
+   */
+  public function load($job_id) {
+    if (!$job_id or !is_numeric($job_id)) {
+      throw new Exception("Must provide a numeric \$job_id to the tripal_cancel_job() function.");
+    }
+
+    $sql = 'SELECT j.* FROM {tripal_jobs} j WHERE j.job_id = :job_id';
+    $args = array(':job_id' => $job_id);
+    $this->job = db_query($sql, $args)->fetchObject();
+    if (!$this->job) {
+      throw new Exception("Cannot find a job with this ID provided.");
+    }
+
+    // Fix the date/time fields.
+    $this->job->submit_date_string = $this->job->submit_date ? format_date($this->job->submit_date) : '';
+    $this->job->start_time_string = $this->job->start_time ? format_date($this->job->start_time): '';
+    $this->job->end_time_string = $this->job->end_time ? format_date($this->job->end_time): '';
+
+    // Unserialize the includes.
+    $this->job->includes = unserialize($this->job->includes);
+
+    // Arguments for jobs used to be stored as plain string with a double colon
+    // separating them.  But as of Tripal v2.0 the arguments are stored as
+    // a serialized array.  To be backwards compatible, we should check for
+    // serialization and if not then we will use the old style
+    $this->job->arguments = unserialize($this->job->arguments);
+    if (!is_array($this->job->arguments)) {
+      $this->job->arguments = explode("::", $this->job->arguments);
+    }
+
+  }
+
+  /**
+   * Creates a new job.
+   *
+   * @param $details
+   *   An associative array of the job details or a single job_id.  If the
+   *   details are provided then the job is created and added to the database
+   *   otherwise if a job_id is provided then the object is loaded from the
+   *   database.  The following keys are allowed:
+   *   - job_name: The human readable name for the job.
+   *   - modulename: The name of the module adding the job.
+   *   - callback: The name of a function to be called when the job is executed.
+   *   - arguments:  An array of arguments to be passed on to the callback.
+   *   - uid: The uid of the user adding the job
+   *   - priority: The priority at which to run the job where the highest
+   *     priority is 10 and the lowest priority is 1. The default
+   *     priority is 10.
+   *   - includes: An array of paths to files that should be included in order
+   *     to execute the job. Use the module_load_include function to get a path
+   *     for a given file.
+   *
+   * @throws Exception
+   *   On failure an exception is thrown.
+   */
+  public function create($details) {
+
+    // Set some defaults
+    if (!array_key_exists('prority', $details)) {
+      $details['priority'] = 10;
+    }
+    if (!array_key_exists('includes', $details)) {
+      $details['includes'] = array();
+    }
+
+    // Make sure the arguments are correct.
+    if (!$details['job_name']) {
+      throw new Exception("Must provide a \$job_name argument to the tripal_add_job() function.");
+    }
+    if (!$details['modulename']) {
+      throw new Exception("Must provide a \$modulename argument to the tripal_add_job() function.");
+    }
+    if (!$details['callback']) {
+      throw new Exception("Must provide a \$callback argument to the tripal_add_job() function.");
+    }
 
 
+    $includes = $details['includes'];
+    foreach ($includes as $include) {
+      require_once($include);
+    }
+    if (!function_exists($details['callback'])) {
+      throw new Exception("Must provide a valid callback function to the tripal_add_job() function.");
+    }
+    if (!is_numeric($details['uid'])) {
+     throw new Exception("Must provide a numeric \$uid argument to the tripal_add_job() function.");
+    }
+    $priority = $details['priority'];
+    if (!$priority or !is_numeric($priority) or $priority < 1 or $priority > 10) {
+      throw new Exception("Must provide a numeric \$priority argument between 1 and 10 to the tripal_add_job() function.");
+    }
+    $arguments = $details['arguments'];
+    if (!is_array($arguments)) {
+      throw new Exception("Must provide an array as the \$arguments argument to the tripal_add_job() function.");
+    }
+
+    // convert the arguments into a string for storage in the database
+    $args = array();
+    if (is_array($arguments)) {
+      $args = serialize($arguments);
+    }
+
+    try {
+      $job_id = db_insert('tripal_jobs')
+        ->fields(array(
+          'job_name' => $details['job_name'],
+          'modulename' => $details['modulename'],
+          'callback' => $details['callback'],
+          'status' => 'Waiting',
+          'submit_date' => time(),
+          'uid' => $details['uid'],
+          'priority' => $priority,
+          'arguments' => $args,
+          'includes' => serialize($includes),
+        ))
+        ->execute();
+      // Now load the job into this object.
+      $this->load($job_id);
+    }
+    catch (Exception $e) {
+      throw new Exception('Cannot create job: ' .  $e->getMessage());
+    }
   }
   }
 
 
+  /**
+   * Cancels the job and prevents it from running.
+   */
+  public function cancel() {
+
+    if (!$this->job) {
+      throw new Exception("There is no job associated with this object. Cannot cancel");
+    }
+
+    if ($this->job->status == 'Running') {
+      throw new Exception("Job Cannot be cancelled it is currently running.");
+
+    }
+    if ($this->job->status == 'Completed') {
+      throw new Exception("Job Cannot be cancelled it has already finished.");
+    }
+    if ($this->job->status == 'Error') {
+      throw new Exception("Job Cannot be cancelled it is in an error state.");
+    }
+    if ($this->job->status == 'Cancelled') {
+      throw new Exception("Job Cannot be cancelled it is already cancelled.");
+    }
+
+    // Set the end time for this job.
+    try {
+      if ($this->job->start_time == 0) {
+        $record = new stdClass();
+        $record->job_id = $this->job->job_id;
+        $record->status = 'Cancelled';
+        $record->progress = '0';
+        drupal_write_record('tripal_jobs', $record, 'job_id');
+      }
+    }
+    catch (Exception $e) {
+      throw new Exception('Cannot cancel job: ' .  $e->getMessage());
+    }
+  }
+
+  /**
+   * Executes the job.
+   */
   public function run() {
   public function run() {
 
 
+    if (!$this->job) {
+      throw new Exception('Cannot launch job as no job is associated with this object.');
+    }
+
+    try {
+
+      // Include the necessary files needed to run the job.
+      foreach ($this->job->includes as $path) {
+        if ($path) {
+          require_once $path;
+        }
+      }
+
+      // Set the start time for this job.
+      $record = new stdClass();
+      $record->job_id = $this->job->job_id;
+      $record->start_time = time();
+      $record->status = 'Running';
+      $record->pid = getmypid();
+      drupal_write_record('tripal_jobs', $record, 'job_id');
+
+
+      // Callback functions need the job in order to update
+      // progress.  But prior to Tripal v3 the job callback functions
+      // only accepted a $job_id as the final argument.  So, we need
+      // to see if the callback is Tv3 compatible or older.  If older
+      // we want to still support it and pass the job_id.
+      $arguments = $this->job->arguments;
+      $callback = $this->job->callback;
+      $ref = new ReflectionFunction($callback);
+      $refparams = $ref->getParameters();
+      if (count($refparams) > 0) {
+        $lastparam = $refparams[count($refparams)-1];
+        if ($lastparam->getName() == 'job_id') {
+          $arguments[] = $this->job->job_id;
+        }
+        else {
+          $arguments[] = $this;
+        }
+      }
+
+      // Launch the job.
+      call_user_func_array($callback, $arguments);
+
+      // Set the end time for this job.
+      $record = new stdClass();
+      $record->job_id = $this->job->job_id;
+      $record->end_time = time();
+      $record->error_msg = $this->job->error_msg;
+      $record->progress = $this->job->progress;
+      $record->status = 'Completed';
+      $record->pid = '';
+
+      drupal_write_record('tripal_jobs', $record, 'job_id');
+      $this->load($this->job->job_id);
+    }
+    catch (Exception $e) {
+      $record->end_time = time();
+      $record->error_msg = $this->job->error_msg;
+      $record->progress = $this->job->progress;
+      $record->status = 'Error';
+      $record->pid = '';
+      drupal_write_record('tripal_jobs', $record, 'job_id');
+      drupal_set_message('Job execution failed: ' . $e->getMessage(), 'error');
+    }
+  }
+
+  /**
+   * Inidcates if the job is running.
+   *
+   * @return
+   *   TRUE if the job is running, FALSE otherwise.
+   */
+  public function isRunning() {
+    if (!$this->job) {
+      throw new Exception('Cannot check running status as no job is associated with this object.');
+    }
+
+    $status = shell_exec('ps -p ' . escapeshellarg($this->job->pid) . ' -o pid=');
+    if ($this->job->pid && $status) {
+      // The job is still running.
+      return TRUE;
+    }
+    // return FALSE to indicate that no jobs are currently running.
+    return FALSE;
+  }
+
+  /**
+   * Retrieve the job object as if from a database query.
+   */
+  public function getJob(){
+    return $this->job;
+  }
+  /**
+   * Retrieves the job ID.
+   */
+  public function getJobID(){
+    return $this->job->job_id;
+  }
+  /**
+   * Retrieves the user ID of the user that submitted the job.
+   */
+  public function getUID() {
+    return $this->job->uid;
+  }
+  /**
+   * Retrieves the job name.
+   */
+  public function getJobName() {
+    return $this->job->job_name;
+  }
+  /**
+   * Retrieves the name of the module that submitted the job.
+   */
+  public function getModuleName() {
+    return $this->job->modulename;
+  }
+  /**
+   * Retrieves the callback function for the job.
+   */
+  public function getCallback() {
+    return $this->job->callback;
+  }
+  /**
+   * Retrieves the array of arguments for the job.
+   */
+  public function getArguments() {
+    return $this->job->arguments;
+  }
+  /**
+   * Retrieves the current percent complete (i.e. progress) of the job.
+   */
+  public function getProgress() {
+    return $this->job->progress;
+  }
+  /**
+   * Sets the current percent complete of a job.
+   *
+   * @param $percent_done
+   *   A value between 0 and 100 indicating the percentage complete of the job.
+   */
+  public function setProgress($percent_done) {
+    if (!$this->job) {
+      throw new Exception('Cannot set progress as no job is associated with this object.');
+    }
+
+    $this->job->progress = $percent_done;
+
+    $progress = sprintf("%d", $percent_done);
+    db_update('tripal_jobs')
+      ->fields(array(
+        'progress' => $progress,
+      ))
+      ->condition('job_id', $this->job->job_id)
+      ->execute();
+  }
+  /**
+   * Retrieves the status of the job.
+   */
+  public function getStatus() {
+    return $this->job->status;
+  }
+  /**
+   * Retrieves the time the job was submitted.
+   */
+  public function getSubmitTime() {
+    return $this->job->submit_date;
+  }
+  /**
+   * Retieves the time the job began execution (i.e. the start time).
+   */
+  public function getStartTime() {
+    return $this->job->start_time;
+  }
+  /**
+   * Retieves the time the job completed execution (i.e. the end time).
+   */
+  public function getEndTime() {
+    return $this->job->end_time;
+  }
+  /**
+   * Retieves the log for the job.
+   *
+   * @return
+   *   A large string containing the text of the job log.  It contains both
+   *   status upates and errors.
+   */
+  public function getLog() {
+    return $this->job->error_msg;
+  }
+  /**
+   * Retrieves the process ID of the job.
+   */
+  public function getPID() {
+    return $this->job->pid;
+  }
+  /**
+   * Retreieves the priority that is currently set for the job.
+   */
+  public function getPriority() {
+    return $this->job->priority;
+  }
+  /**
+   * Get the MLock value of the job.
+   *
+   * The MLock value indicates if no other jobs from a give module
+   * should be executed while this job is running.
+   */
+  public function getMLock() {
+    return $this->job->mlock;
+  }
+  /**
+   * Get the lock value of the job.
+   *
+   * The lock value indicates if no other jobs from any module
+   * should be executed while this job is running.
+   */
+  public function getLock() {
+    return $this->job->lock;
+  }
+  /**
+   * Get the list of files that must be included prior to job execution.
+   */
+  public function getIncludes() {
+    return $this->job->includes;
   }
   }
 
 
   /**
   /**
-   * Provides a message to the user by logging a system message.
+   * Logs a message for the job.
+   *
+   * There is no distinction between status messages and error logs.  Any
+   * message that is intended for the user to review the status of the job
+   * can be provided here.
+   *
+   * Messages that are are of severity TRIPAL_CRITICAL or TRIPAL_ERROR
+   * are also logged to the watchdog.
    *
    *
-   * This function takes similar arguments as Drupal's watchdog function.
+   * Logging works regardless if the job uses a transaction. If the
+   * transaction must be rolled back to to an error the error messages will
+   * persist.
    *
    *
    * @param $message
    * @param $message
    *   The message to store in the log. Keep $message translatable by not
    *   The message to store in the log. Keep $message translatable by not
@@ -46,25 +453,22 @@ class TripalJob {
    *     - TRIPAL_INFO: (default) Informational messages.
    *     - TRIPAL_INFO: (default) Informational messages.
    *     - TRIPAL_DEBUG: Debug-level messages.
    *     - TRIPAL_DEBUG: Debug-level messages.
    */
    */
-  public function logError($message, $variables = array(), $severity = TRIPAL_INFO) {
+  public function logMessage($message, $variables = array(), $severity = TRIPAL_INFO) {
+    // Generate a translated message.
+    $tmessage = t($message, $variables);
 
 
-  }
-  /**
-   * @param $message
-   *   (optional) The translated message to be displayed to the user. For
-   *   consistency with other messages, it should begin with a capital letter
-   *   and end with a period.
-   * @param $type
-   *   (optional) The message's type. Defaults to 'status'. These values are
-   *   supported:
-   *     - 'status'
-   *     - 'warning'
-   *     - 'error'
-   * @param $repeat
-   *   (optional) If this is FALSE and the message is already set, then the
-   *   message won't be repeated. Defaults to TRUE.
-   */
-  public function logOutput($message, $type = 'status', $repeat = FALSE) {
+    // Add this message to the job's log.
+    $this->job->error_msg .= "\n" . $tmessage;
 
 
+    // Report this message to watchdog or set a message.
+    if ($severity == TRIPAL_CRITICAL or $severity == TRIPAL_ERROR) {
+      tripal_report_error('tripal_job', $severity, $message, $variables);
+    }
+    if ($severity == TRIPAL_WARNING) {
+      drupal_set_message($tmessage, 'warning');
+    }
+    else {
+      drupal_set_message($tmessage, 'status');
+    }
   }
   }
 }
 }

+ 23 - 0
tripal/includes/tripal.importer.inc

@@ -36,6 +36,29 @@ function tripal_get_importer_form($form, &$form_state, $class) {
     '#description'   => t('If the file is local to the Tripal server please provide the full path here.'),
     '#description'   => t('If the file is local to the Tripal server please provide the full path here.'),
   );
   );
 
 
+  if ($class::$use_analysis) {
+    // get the list of analyses
+    $sql = "SELECT * FROM {analysis} ORDER BY name";
+    $org_rset = chado_query($sql);
+    $analyses = array();
+    $analyses[''] = '';
+    while ($analysis = $org_rset->fetchObject()) {
+      $analyses[$analysis->analysis_id] = "$analysis->name ($analysis->program $analysis->programversion, $analysis->sourcename)";
+    }
+    $form['analysis_id'] = array(
+      '#title'       => t('Analysis'),
+      '#type'        => t('select'),
+      '#description' => t('Choose the analysis to which the uploaded data will be associated. ' .
+        'Why specify an analysis for a data load?  All data comes from some place, even if ' .
+        'downloaded from a website. By specifying analysis details for all data imports it ' .
+        'provides provenance and helps end user to reproduce the data set if needed. At ' .
+        'a minimum it indicates the source of the data.'),
+      '#required'    => $class::$require_analysis,
+      '#options'     => $analyses,
+    );
+  }
+
+
   $importer = new $class();
   $importer = new $class();
   $element = array();
   $element = array();
   $form['class_elements'] = $importer->form($element, $form_state);
   $form['class_elements'] = $importer->form($element, $form_state);

+ 1 - 0
tripal/tripal.module

@@ -29,6 +29,7 @@ require_once "includes/TripalFields/TripalField.inc";
 require_once "includes/TripalFields/TripalFieldWidget.inc";
 require_once "includes/TripalFields/TripalFieldWidget.inc";
 require_once "includes/TripalFields/TripalFieldFormatter.inc";
 require_once "includes/TripalFields/TripalFieldFormatter.inc";
 require_once "includes/TripalFieldQuery.inc";
 require_once "includes/TripalFieldQuery.inc";
+require_once "includes/TripalJob.inc";
 require_once "includes/TripalImporter.inc";
 require_once "includes/TripalImporter.inc";
 
 
 /**
 /**

+ 3 - 5
tripal/tripal.views.inc

@@ -30,7 +30,7 @@ function tripal_views_data() {
   $data = array();
   $data = array();
   // Job Management System
   // Job Management System
   tripal_views_data_jobs($data);
   tripal_views_data_jobs($data);
-  tripal_entity_views_data($data);
+  tripal_views_data_tripal_entity($data);
   tripal_views_data_fields($data);
   tripal_views_data_fields($data);
 
 
   return $data;
   return $data;
@@ -78,7 +78,7 @@ function tripal_views_data_fields(&$data) {
 /**
 /**
  * Integrates the TripalEntity entities with Drupal Views.
  * Integrates the TripalEntity entities with Drupal Views.
  */
  */
-function tripal_entity_views_data(&$data) {
+function tripal_views_data_tripal_entity(&$data) {
 
 
   // Get the list of all of the bundles (entity types) and add them
   // Get the list of all of the bundles (entity types) and add them
   // as "base tables" for views.
   // as "base tables" for views.
@@ -122,7 +122,7 @@ function tripal_entity_views_data(&$data) {
  *
  *
  * @ingroup tripal
  * @ingroup tripal
  */
  */
-function tripal_views_data_jobs($data) {
+function tripal_views_data_jobs(&$data) {
 
 
   $data['tripal_jobs']['table']['group'] = t('Tripal Jobs');
   $data['tripal_jobs']['table']['group'] = t('Tripal Jobs');
   $data['tripal_jobs']['table']['base'] = array(
   $data['tripal_jobs']['table']['base'] = array(
@@ -371,6 +371,4 @@ function tripal_views_data_jobs($data) {
       'handler' => 'views_handler_sort',
       'handler' => 'views_handler_sort',
     ),
     ),
   );
   );
-
-  return $data;
 }
 }

+ 3 - 0
tripal_chado/api/tripal_chado.mviews.api.inc

@@ -354,6 +354,7 @@ function tripal_populate_mview($mview_id) {
     // execute the query inside a transaction so that it doesn't destroy existing data
     // execute the query inside a transaction so that it doesn't destroy existing data
     // that may leave parts of the site unfunctional
     // that may leave parts of the site unfunctional
     $transaction = db_transaction();
     $transaction = db_transaction();
+    $previous_db = chado_set_active('chado');  // use chado database
     try {
     try {
       $success = chado_query("DELETE FROM {" . $mview->mv_table . "}");
       $success = chado_query("DELETE FROM {" . $mview->mv_table . "}");
       $success = chado_query("INSERT INTO {" . $mview->mv_table . "} ($mview->query)");
       $success = chado_query("INSERT INTO {" . $mview->mv_table . "} ($mview->query)");
@@ -372,8 +373,10 @@ function tripal_populate_mview($mview_id) {
       else {
       else {
         throw new Exception("ERROR populating the materialized view ". $mview->mv_table . ". See Drupal's recent log entries for details.");
         throw new Exception("ERROR populating the materialized view ". $mview->mv_table . ". See Drupal's recent log entries for details.");
       }
       }
+      chado_set_active($previous_db);
     }
     }
     catch (Exception $e) {
     catch (Exception $e) {
+      chado_set_active($previous_db);
       $transaction->rollback();
       $transaction->rollback();
       // print and save the error message
       // print and save the error message
       $record = new stdClass();
       $record = new stdClass();

+ 332 - 391
tripal_chado/includes/TripalImporter/FASTAImporter.inc

@@ -46,9 +46,12 @@ class FASTAImporter extends TripalImporter {
     while ($organism = $org_rset->fetchObject()) {
     while ($organism = $org_rset->fetchObject()) {
       $organisms[$organism->organism_id] = "$organism->genus $organism->species ($organism->common_name)";
       $organisms[$organism->organism_id] = "$organism->genus $organism->species ($organism->common_name)";
     }
     }
-    $form['organism_id'] = array('#title' => t('Organism'),'#type' => t('select'),
+    $form['organism_id'] = array(
+      '#title' => t('Organism'),
+      '#type' => t('select'),
       '#description' => t("Choose the organism to which these sequences are associated"),
       '#description' => t("Choose the organism to which these sequences are associated"),
-      '#required' => TRUE,'#options' => $organisms
+      '#required' => TRUE,
+      '#options' => $organisms
     );
     );
 
 
     // get the sequence ontology CV ID
     // get the sequence ontology CV ID
@@ -56,102 +59,97 @@ class FASTAImporter extends TripalImporter {
     $cv = chado_select_record('cv', array('cv_id'), $values);
     $cv = chado_select_record('cv', array('cv_id'), $values);
     $cv_id = $cv[0]->cv_id;
     $cv_id = $cv[0]->cv_id;
 
 
-    $form['seqtype'] = array('#type' => 'textfield','#title' => t('Sequence Type'),
+    $form['seqtype'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Sequence Type'),
       '#required' => TRUE,
       '#required' => TRUE,
       '#description' => t('Please enter the Sequence Ontology (SO) term name that describes the sequences in the FASTA file (e.g. gene, mRNA, polypeptide, etc...)'),
       '#description' => t('Please enter the Sequence Ontology (SO) term name that describes the sequences in the FASTA file (e.g. gene, mRNA, polypeptide, etc...)'),
       '#autocomplete_path' => "admin/tripal/storage/chado/auto_name/cvterm/$cv_id"
       '#autocomplete_path' => "admin/tripal/storage/chado/auto_name/cvterm/$cv_id"
     );
     );
 
 
-    $form['method'] = array('#type' => 'radios','#title' => 'Method','#required' => TRUE,
-      '#options' => array(t('Insert only'),t('Update only'),t('Insert and update')
+    $form['method'] = array(
+      '#type' => 'radios',
+      '#title' => 'Method',
+      '#required' => TRUE,
+      '#options' => array(
+        t('Insert only'),
+        t('Update only'),
+        t('Insert and update')
       ),
       ),
       '#description' => t('Select how features in the FASTA file are handled.
       '#description' => t('Select how features in the FASTA file are handled.
-       Select "Insert only" to insert the new features. If a feature already
-       exists with the same name or unique name and type then it is skipped.
-       Select "Update only" to only update featues that already exist in the
-       database.  Select "Insert and Update" to insert features that do
-       not exist and upate those that do.'),'#default_value' => 2
+         Select "Insert only" to insert the new features. If a feature already
+         exists with the same name or unique name and type then it is skipped.
+         Select "Update only" to only update featues that already exist in the
+         database.  Select "Insert and Update" to insert features that do
+         not exist and upate those that do.'),
+      '#default_value' => 2
     );
     );
     $form['match_type'] = array('#type' => 'radios','#title' => 'Name Match Type','#required' => TRUE,
     $form['match_type'] = array('#type' => 'radios','#title' => 'Name Match Type','#required' => TRUE,
       '#options' => array(t('Name'),t('Unique name')
       '#options' => array(t('Name'),t('Unique name')
       ),
       ),
       '#description' => t('Used for "updates only" or "insert and update" methods. Not required if method type is "insert".
       '#description' => t('Used for "updates only" or "insert and update" methods. Not required if method type is "insert".
-      Feature data is stored in Chado with both a human-readable
-      name and a unique name. If the features in your FASTA file are uniquely identified using
-      a human-readable name then select the "Name" button. If your features are
-      uniquely identified using the unique name then select the "Unique name" button.  If you
-      loaded your features first using the GFF loader then the unique name of each
-      features were indicated by the "ID=" attribute and the name by the "Name=" attribute.
-      By default, the FASTA loader will use the first word (character string
-      before the first space) as  the name for your feature. If
-      this does not uniquely identify your feature consider specifying a regular expression in the advanced section below.
-      Additionally, you may import both a name and a unique name for each sequence using the advanced options.'),
+        Feature data is stored in Chado with both a human-readable
+        name and a unique name. If the features in your FASTA file are uniquely identified using
+        a human-readable name then select the "Name" button. If your features are
+        uniquely identified using the unique name then select the "Unique name" button.  If you
+        loaded your features first using the GFF loader then the unique name of each
+        features were indicated by the "ID=" attribute and the name by the "Name=" attribute.
+        By default, the FASTA loader will use the first word (character string
+        before the first space) as  the name for your feature. If
+        this does not uniquely identify your feature consider specifying a regular expression in the advanced section below.
+        Additionally, you may import both a name and a unique name for each sequence using the advanced options.'),
       '#default_value' => 1
       '#default_value' => 1
     );
     );
 
 
-    $form['analysis'] = array('#type' => 'fieldset','#title' => t('Analysis Used to Derive Features'),
+    // Additional Options
+    $form['additional'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Additional Options'),
+      '#collapsible' => TRUE,
       '#collapsed' => TRUE
       '#collapsed' => TRUE
     );
     );
-    $form['analysis']['desc'] = array(
-      '#markup' => t("Why specify an analysis for a data load?  All data comes
-       from some place, even if downloaded from Genbank. By specifying
-       analysis details for all data uploads, it allows an end user to reproduce the
-       data set, but at least indicates the source of the data.")
-    );
-
-    // get the list of organisms
-    $sql = "SELECT * FROM {analysis} ORDER BY name";
-    $org_rset = chado_query($sql);
-    $analyses = array();
-    $analyses[''] = '';
-    while ($analysis = $org_rset->fetchObject()) {
-      $analyses[$analysis->analysis_id] = "$analysis->name ($analysis->program $analysis->programversion, $analysis->sourcename)";
-    }
-    $form['analysis']['analysis_id'] = array('#title' => t('Analysis'),'#type' => t('select'),
-      '#description' => t("Choose the analysis to which these features are associated"),
-      '#required' => TRUE,'#options' => $analyses
-    );
 
 
-    // Advanced Options
-    $form['advanced'] = array('#type' => 'fieldset','#title' => t('Advanced Options'),
-      '#collapsible' => TRUE,'#collapsed' => TRUE
-    );
-    $form['advanced']['re_help'] = array('#type' => 'item',
+    $form['additional']['re_help'] = array('#type' => 'item',
       '#value' => t('A regular expression is an advanced method for extracting information from a string of text.
       '#value' => t('A regular expression is an advanced method for extracting information from a string of text.
-                   Your FASTA file may contain both a human-readable name and a unique name for each sequence.
-                   If you want to import
-                   both the name and unique name for all sequences, then you must provide regular expressions
-                   so that the loader knows how to separate them.
-                   Otherwise the name and uniquename will be the same.
-                   By default, this loader will use the first word in the definition
-                   lines of the FASTA file
-                   as the name or unique name of the feature.')
+         Your FASTA file may contain both a human-readable name and a unique name for each sequence.
+         If you want to import
+         both the name and unique name for all sequences, then you must provide regular expressions
+         so that the loader knows how to separate them.
+         Otherwise the name and uniquename will be the same.
+         By default, this loader will use the first word in the definition
+         lines of the FASTA file
+         as the name or unique name of the feature.')
     );
     );
-    $form['advanced']['re_name'] = array('#type' => 'textfield',
+    $form['additional']['re_name'] = array('#type' => 'textfield',
       '#title' => t('Regular expression for the name'),'#required' => FALSE,
       '#title' => t('Regular expression for the name'),'#required' => FALSE,
       '#description' => t('Enter the regular expression that will extract the
       '#description' => t('Enter the regular expression that will extract the
-       feature name from the FASTA definition line. For example, for a
-       defintion line with a name and unique name separated by a bar \'|\' (>seqname|uniquename),
-       the regular expression for the name would be, "^(.*?)\|.*$".  All FASTA
-       definition lines begin with the ">" symbol.  You do not need to incldue
-       this symbol in your regular expression.')
+         feature name from the FASTA definition line. For example, for a
+         defintion line with a name and unique name separated by a bar \'|\' (>seqname|uniquename),
+         the regular expression for the name would be, "^(.*?)\|.*$".  All FASTA
+         definition lines begin with the ">" symbol.  You do not need to incldue
+         this symbol in your regular expression.')
     );
     );
-    $form['advanced']['re_uname'] = array('#type' => 'textfield',
+    $form['additional']['re_uname'] = array('#type' => 'textfield',
       '#title' => t('Regular expression for the unique name'),'#required' => FALSE,
       '#title' => t('Regular expression for the unique name'),'#required' => FALSE,
       '#description' => t('Enter the regular expression that will extract the
       '#description' => t('Enter the regular expression that will extract the
-       feature name from the FASTA definition line. For example, for a
-       defintion line with a name and unique name separated by a bar \'|\' (>seqname|uniquename),
-       the regular expression for the unique name would be "^.*?\|(.*)$").  All FASTA
-       definition lines begin with the ">" symbol.  You do not need to incldue
-       this symbol in your regular expression.')
+         feature name from the FASTA definition line. For example, for a
+         defintion line with a name and unique name separated by a bar \'|\' (>seqname|uniquename),
+         the regular expression for the unique name would be "^.*?\|(.*)$").  All FASTA
+         definition lines begin with the ">" symbol.  You do not need to incldue
+         this symbol in your regular expression.')
     );
     );
 
 
     // Advanced database cross reference options.
     // Advanced database cross reference options.
-    $form['advanced']['db'] = array('#type' => 'fieldset',
-      '#title' => t('External Database Reference'),'#weight' => 6,'#collapsed' => TRUE
+    $form['additional']['db'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('External Database Reference'),
+      '#weight' => 6,
+      '#collapsed' => TRUE
     );
     );
-    $form['advanced']['db']['re_accession'] = array('#type' => 'textfield',
-      '#title' => t('Regular expression for the accession'),'#required' => FALSE,
+    $form['additional']['db']['re_accession'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Regular expression for the accession'),
+      '#required' => FALSE,
       '#description' => t('Enter the regular expression that will extract the accession for the external database for each feature from the FASTA definition line.'),
       '#description' => t('Enter the regular expression that will extract the accession for the external database for each feature from the FASTA definition line.'),
       '#weight' => 2
       '#weight' => 2
     );
     );
@@ -164,13 +162,18 @@ class FASTAImporter extends TripalImporter {
     while ($db = $db_rset->fetchObject()) {
     while ($db = $db_rset->fetchObject()) {
       $dbs[$db->db_id] = "$db->name";
       $dbs[$db->db_id] = "$db->name";
     }
     }
-    $form['advanced']['db']['db_id'] = array('#title' => t('External Database'),
+    $form['additional']['db']['db_id'] = array(
+      '#title' => t('External Database'),
       '#type' => t('select'),
       '#type' => t('select'),
       '#description' => t("Plese choose an external database for which these sequences have a cross reference."),
       '#description' => t("Plese choose an external database for which these sequences have a cross reference."),
-      '#required' => FALSE,'#options' => $dbs,'#weight' => 1
+      '#required' => FALSE,
+      '#options' => $dbs,
+      '#weight' => 1
     );
     );
 
 
-    $form['advanced']['relationship'] = array('#type' => 'fieldset','#title' => t('Relationships'),
+    $form['additional']['relationship'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Relationships'),
       '#weight' => 6,'#collapsed' => TRUE
       '#weight' => 6,'#collapsed' => TRUE
     );
     );
     $rels = array();
     $rels = array();
@@ -179,22 +182,30 @@ class FASTAImporter extends TripalImporter {
     $rels['derives_from'] = 'produced by (derives from)';
     $rels['derives_from'] = 'produced by (derives from)';
 
 
     // Advanced references options
     // Advanced references options
-    $form['advanced']['relationship']['rel_type'] = array('#title' => t('Relationship Type'),
+    $form['additional']['relationship']['rel_type'] = array(
+      '#title' => t('Relationship Type'),
       '#type' => t('select'),
       '#type' => t('select'),
       '#description' => t("Use this option to create associations, or relationships between the
       '#description' => t("Use this option to create associations, or relationships between the
                         features of this FASTA file and existing features in the database. For
                         features of this FASTA file and existing features in the database. For
                         example, to associate a FASTA file of peptides to existing genes or transcript sequence,
                         example, to associate a FASTA file of peptides to existing genes or transcript sequence,
                         select the type 'produced by'. For a CDS sequences select the type 'part of'"),
                         select the type 'produced by'. For a CDS sequences select the type 'part of'"),
-      '#required' => FALSE,'#options' => $rels,'#weight' => 5
+      '#required' => FALSE,
+      '#options' => $rels,
+      '#weight' => 5
     );
     );
-    $form['advanced']['relationship']['re_subject'] = array('#type' => 'textfield',
-      '#title' => t('Regular expression for the parent'),'#required' => FALSE,
+    $form['additional']['relationship']['re_subject'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Regular expression for the parent'),
+      '#required' => FALSE,
       '#description' => t('Enter the regular expression that will extract the unique
       '#description' => t('Enter the regular expression that will extract the unique
                          name needed to identify the existing sequence for which the
                          name needed to identify the existing sequence for which the
-                         relationship type selected above will apply.'),'#weight' => 6
+                         relationship type selected above will apply.'),
+      '#weight' => 6
     );
     );
-    $form['advanced']['relationship']['parent_type'] = array('#type' => 'textfield',
-      '#title' => t('Parent Type'),'#required' => FALSE,
+    $form['additional']['relationship']['parent_type'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Parent Type'),
+      '#required' => FALSE,
       '#description' => t('Please enter the Sequence Ontology term for the parent.  For example
       '#description' => t('Please enter the Sequence Ontology term for the parent.  For example
                          if the FASTA file being loaded is a set of proteins that are
                          if the FASTA file being loaded is a set of proteins that are
                          products of genes, then use the SO term \'gene\' or \'transcript\' or equivalent. However,
                          products of genes, then use the SO term \'gene\' or \'transcript\' or equivalent. However,
@@ -305,7 +316,7 @@ class FASTAImporter extends TripalImporter {
   /**
   /**
    * @see TripalImporter::run()
    * @see TripalImporter::run()
    */
    */
-  public function run($details, $job_id = NULL) {
+  public function run($details) {
     $arguments = $details->arguments;
     $arguments = $details->arguments;
 
 
     $dfile = $arguments['file_path'];
     $dfile = $arguments['file_path'];
@@ -324,7 +335,7 @@ class FASTAImporter extends TripalImporter {
 
 
     $this->load($dfile, $organism_id, $type, $re_name, $re_uname, $re_accession,
     $this->load($dfile, $organism_id, $type, $re_name, $re_uname, $re_accession,
       $db_id, $rel_type, $re_subject, $parent_type, $method, $uid, $analysis_id,
       $db_id, $rel_type, $re_subject, $parent_type, $method, $uid, $analysis_id,
-      $match_type, $job_id);
+      $match_type);
   }
   }
   /**
   /**
    * Load a fasta file.
    * Load a fasta file.
@@ -361,25 +372,21 @@ class FASTAImporter extends TripalImporter {
    *   The analysis_id to associate the features in this fasta file with.
    *   The analysis_id to associate the features in this fasta file with.
    * @param $match_type
    * @param $match_type
    *  Whether to match existing features based on the 'Name' or 'Unique name'.
    *  Whether to match existing features based on the 'Name' or 'Unique name'.
-   * @param $job
-   *  The tripal job
    */
    */
   private function loadFasta($dfile, $organism_id, $type, $re_name, $re_uname, $re_accession,
   private function loadFasta($dfile, $organism_id, $type, $re_name, $re_uname, $re_accession,
-      $db_id, $rel_type, $re_subject, $parent_type, $method, $uid, $analysis_id, $match_type,
-      $job = NULL) {
+      $db_id, $rel_type, $re_subject, $parent_type, $method, $uid, $analysis_id, $match_type) {
 
 
     // First get the type for this sequence.
     // First get the type for this sequence.
     $cvtermsql = "
     $cvtermsql = "
-    SELECT CVT.cvterm_id
-    FROM {cvterm} CVT
-      INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id
-      LEFT JOIN {cvtermsynonym} CVTS on CVTS.cvterm_id = CVT.cvterm_id
-    WHERE cv.name = :cvname and (CVT.name = :name or CVTS.synonym = :synonym)
-  ";
+      SELECT CVT.cvterm_id
+      FROM {cvterm} CVT
+        INNER JOIN {cv} CV on CVT.cv_id = CV.cv_id
+        LEFT JOIN {cvtermsynonym} CVTS on CVTS.cvterm_id = CVT.cvterm_id
+      WHERE cv.name = :cvname and (CVT.name = :name or CVTS.synonym = :synonym)
+    ";
     $cvterm = chado_query($cvtermsql, array(':cvname' => 'sequence',':name' => $type,':synonym' => $type))->fetchObject();
     $cvterm = chado_query($cvtermsql, array(':cvname' => 'sequence',':name' => $type,':synonym' => $type))->fetchObject();
     if (!$cvterm) {
     if (!$cvterm) {
-      tripal_report_error("T_fasta_loader", TRIPAL_ERROR,
-          "Cannot find the term type: '%type'", array('%type' => $type));
+      $this->logMessage("Cannot find the term type: '%type'", array('%type' => $type), TRIPAL_ERROR);
       return 0;
       return 0;
     }
     }
 
 
@@ -387,9 +394,9 @@ class FASTAImporter extends TripalImporter {
     if ($parent_type) {
     if ($parent_type) {
       $parentcvterm = chado_query($cvtermsql, array(':cvname' => 'sequence', ':name' => $parent_type,':synonym' => $parent_type))->fetchObject();
       $parentcvterm = chado_query($cvtermsql, array(':cvname' => 'sequence', ':name' => $parent_type,':synonym' => $parent_type))->fetchObject();
       if (!$parentcvterm) {
       if (!$parentcvterm) {
-        tripal_report_error("T_fasta_loader", TRIPAL_ERROR, "Cannot find the paretne term type: '%type'", array(
+        $this->logMessage("Cannot find the paretne term type: '%type'", array(
           '%type' => $parentcvterm
           '%type' => $parentcvterm
-        ));
+        ), TRIPAL_ERROR);
         return 0;
         return 0;
       }
       }
     }
     }
@@ -398,9 +405,9 @@ class FASTAImporter extends TripalImporter {
     if ($rel_type) {
     if ($rel_type) {
       $relcvterm = chado_query($cvtermsql, array(':cvname' => 'sequence',':name' => $rel_type,':synonym' => $rel_type))->fetchObject();
       $relcvterm = chado_query($cvtermsql, array(':cvname' => 'sequence',':name' => $rel_type,':synonym' => $rel_type))->fetchObject();
       if (!$relcvterm) {
       if (!$relcvterm) {
-        tripal_report_error("T_fasta_loader", TRIPAL_ERROR, "Cannot find the relationship term type: '%type'", array(
+        $this->logMessage("Cannot find the relationship term type: '%type'", array(
           '%type' => $relcvterm
           '%type' => $relcvterm
-        ));
+        ), TRIPAL_ERROR);
         return 0;
         return 0;
       }
       }
     }
     }
@@ -410,22 +417,16 @@ class FASTAImporter extends TripalImporter {
     $feature_tbl = chado_get_schema('feature');
     $feature_tbl = chado_get_schema('feature');
     $dbxref_tbl = chado_get_schema('dbxref');
     $dbxref_tbl = chado_get_schema('dbxref');
 
 
-    print "Step 1: finding sequences\n";
+    $this->logMessage(t("Step 1: finding sequences\n"));
     $filesize = filesize($dfile);
     $filesize = filesize($dfile);
+    $this->setTotalItems($filesize);
     $fh = fopen($dfile, 'r');
     $fh = fopen($dfile, 'r');
     if (!$fh) {
     if (!$fh) {
-      tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "cannot open file: %dfile", array(
+      $this->logMessage("Cannot open file: %dfile", array(
         '%dfile' => $dfile
         '%dfile' => $dfile
-      ));
+      ), TRIPAL_ERROR);
       return 0;
       return 0;
     }
     }
-
-    // Calculate the interval at which we will print to the screen that status.
-    $interval = intval($filesize * 0.01);
-    if ($interval < 1) {
-      $interval = 1;
-    }
-    $inv_read = 0;
     $num_read = 0;
     $num_read = 0;
 
 
     // Iterate through the lines of the file. Keep a record for
     // Iterate through the lines of the file. Keep a record for
@@ -436,7 +437,6 @@ class FASTAImporter extends TripalImporter {
     $set_start = FALSE;
     $set_start = FALSE;
     while ($line = fgets($fh)) {
     while ($line = fgets($fh)) {
       $num_read += strlen($line);
       $num_read += strlen($line);
-      $intv_read += strlen($line);
 
 
       // If we encounter a definition line then get the name, uniquename,
       // If we encounter a definition line then get the name, uniquename,
       // accession and relationship subject from the definition line.
       // accession and relationship subject from the definition line.
@@ -448,14 +448,12 @@ class FASTAImporter extends TripalImporter {
         // Get the feature name if a regular expression is provided.
         // Get the feature name if a regular expression is provided.
         if ($re_name) {
         if ($re_name) {
           if (!preg_match("/$re_name/", $defline, $matches)) {
           if (!preg_match("/$re_name/", $defline, $matches)) {
-            tripal_report_error('trp-fasta', "ERROR: Regular expression for the feature name finds nothing. Line %line.", array(
-              '%line' => $i
-            ), 'error');
+            $this->logMessage("Regular expression for the feature name finds nothing. Line %line.",
+              array('%line' => $i), TRIPAL_ERROR);
           }
           }
           elseif (strlen($matches[1]) > $feature_tbl['fields']['name']['length']) {
           elseif (strlen($matches[1]) > $feature_tbl['fields']['name']['length']) {
-            tripal_report_error('trp-fasta', "WARNING: Regular expression retrieves a value too long for the feature name. Line %line.", array(
-              '%line' => $i
-            ), 'error');
+            $this->logMessage("Regular expression retrieves a value too long for the feature name. Line %line.",
+              array('%line' => $i), TRIPAL_WARNING);
           }
           }
           else {
           else {
             $name = trim($matches[1]);
             $name = trim($matches[1]);
@@ -466,24 +464,23 @@ class FASTAImporter extends TripalImporter {
         elseif (strcmp($match_type, 'Name') == 0) {
         elseif (strcmp($match_type, 'Name') == 0) {
           if (preg_match("/^\s*(.*?)[\s\|].*$/", $defline, $matches)) {
           if (preg_match("/^\s*(.*?)[\s\|].*$/", $defline, $matches)) {
             if (strlen($matches[1]) > $feature_tbl['fields']['name']['length']) {
             if (strlen($matches[1]) > $feature_tbl['fields']['name']['length']) {
-              tripal_report_error('trp-fasta', "WARNING: Regular expression retrieves a feature name too long for the feature name. Line %line.", array(
-                '%line' => $i), 'error');
+              $this->logMessage("Regular expression retrieves a feature name too long for the feature name. Line %line.",
+                array('%line' => $i), TRIPAL_WARNING);
             }
             }
             else {
             else {
               $name = trim($matches[1]);
               $name = trim($matches[1]);
             }
             }
           }
           }
           else {
           else {
-            tripal_report_error('trp-fasta', "ERROR: Cannot find a feature name. Line %line.", array(
-              '%line' => $i), 'error');
+            $this->logMessage("Cannot find a feature name. Line %line.", array('%line' => $i), TRIPAL_WARNING);
           }
           }
         }
         }
 
 
         // Get the feature uniquename if a regular expression is provided.
         // Get the feature uniquename if a regular expression is provided.
         if ($re_uname) {
         if ($re_uname) {
           if (!preg_match("/$re_uname/", $defline, $matches)) {
           if (!preg_match("/$re_uname/", $defline, $matches)) {
-            tripal_report_error('trp-fasta', "ERROR: Regular expression for the feature unique name finds nothing. Line %line.", array(
-              '%line' => $i), 'error');
+            $this->logMessage("Regular expression for the feature unique name finds nothing. Line %line.",
+              array('%line' => $i), TRIPAL_ERROR);
           }
           }
           $uname = trim($matches[1]);
           $uname = trim($matches[1]);
         }
         }
@@ -495,17 +492,16 @@ class FASTAImporter extends TripalImporter {
             $uname = trim($matches[1]);
             $uname = trim($matches[1]);
           }
           }
           else {
           else {
-            tripal_report_error('trp-fasta', "ERROR: Cannot find a feature unique name. Line %line.", array(
-              '%line' => $i), 'error');
+            $this->logMessage("Cannot find a feature unique name. Line %line.",
+              array('%line' => $i), TRIPAL_ERROR);
           }
           }
         }
         }
 
 
         // Get the accession if a regular expression is provided.
         // Get the accession if a regular expression is provided.
         preg_match("/$re_accession/", $defline, $matches);
         preg_match("/$re_accession/", $defline, $matches);
         if (strlen($matches[1]) > $dbxref_tbl['fields']['accession']['length']) {
         if (strlen($matches[1]) > $dbxref_tbl['fields']['accession']['length']) {
-          tripal_report_error('trp-fasta', "WARNING: Regular expression retrieves an accession too long for the feature name. " .
-              "Cannot add cross reference. Line %line.", array('%line' => $i
-              ), 'warning');
+          $this->logMessage("Regular expression retrieves an accession too long for the feature name. " .
+            "Cannot add cross reference. Line %line.", array('%line' => $i), TRIPAL_WARNING);
         }
         }
         else {
         else {
           $accession = trim($matches[1]);
           $accession = trim($matches[1]);
@@ -535,36 +531,18 @@ class FASTAImporter extends TripalImporter {
       // ending position
       // ending position
       $prev_pos = ftell($fh);
       $prev_pos = ftell($fh);
 
 
-      // update the job status every % bytes
-      if ($job and $intv_read >= $interval) {
-        $intv_read = 0;
-        $percent = sprintf("%.2f", ($num_read / $filesize) * 100);
-        if ($name) {
-          print "Parsing Line $i (" . $percent . "%). Memory: " . number_format(memory_get_usage()) .
-          " bytes.\r";
-        }
-        else {
-          print "Parsing Line $i (" . $percent . "%). Memory: " . number_format(memory_get_usage()) .
-          " bytes.\r";
-        }
-        tripal_set_job_progress($job, intval(($num_read / $filesize) * 100));
-      }
     }
     }
-    $percent = sprintf("%.2f", ($num_read / $filesize) * 100);
-    print "Parsing Line $i (" . $percent . "%). Memory: " . number_format(memory_get_usage()) .
-    " bytes.\r";
-    tripal_set_job_progress($job, 50);
 
 
     // Set the end position for the last sequence.
     // Set the end position for the last sequence.
     $seqs[$num_seqs - 1]['seq_end'] = $num_read - strlen($line);
     $seqs[$num_seqs - 1]['seq_end'] = $num_read - strlen($line);
 
 
     // Now that we know where the sequences are in the file we need to add them.
     // Now that we know where the sequences are in the file we need to add them.
-    print "\nStep 2: Importing sequences\n";
+    $this->logMessage("\nStep 2: Importing sequences\n");
     for ($i = 0; $i < $num_seqs; $i++) {
     for ($i = 0; $i < $num_seqs; $i++) {
       $seq = $seqs[$i];
       $seq = $seqs[$i];
-      print "Importing " . ($i + 1) . " of $num_seqs. ";
+      $this->logMessage("Importing " . ($i + 1) . " of $num_seqs. ");
       if ($name) {
       if ($name) {
-        print "Current feature: " . $seq['name'] . ".\n";
+        $this->logMessage("Current feature: " . $seq['name'] . ".\n");
       }
       }
       else {
       else {
         print "Current feature: " . $seq['uname'] . ".\n";
         print "Current feature: " . $seq['uname'] . ".\n";
@@ -572,7 +550,9 @@ class FASTAImporter extends TripalImporter {
 
 
       loadFastaFeature($fh, $seq['name'], $seq['uname'], $db_id, $seq['accession'], $seq['subject'], $rel_type, $parent_type, $analysis_id, $organism_id, $cvterm, $source, $method, $re_name, $match_type, $parentcvterm, $relcvterm, $seq['seq_start'], $seq['seq_end']);
       loadFastaFeature($fh, $seq['name'], $seq['uname'], $db_id, $seq['accession'], $seq['subject'], $rel_type, $parent_type, $analysis_id, $organism_id, $cvterm, $source, $method, $re_name, $match_type, $parentcvterm, $relcvterm, $seq['seq_start'], $seq['seq_end']);
     }
     }
-    tripal_set_job_progress($job, 100);
+    if ($this->job) {
+      tripal_set_job_progress($this->job->job_id, 100);
+    }
     fclose($fh);
     fclose($fh);
 
 
   }
   }
@@ -593,8 +573,8 @@ class FASTAImporter extends TripalImporter {
       $results = chado_select_record('feature', array('feature_id'
       $results = chado_select_record('feature', array('feature_id'
       ), $values);
       ), $values);
       if (count($results) > 1) {
       if (count($results) > 1) {
-        tripal_report_error('T_fasta_loader', "Multiple features exist with the name '%name' of type
-               '%type' for the organism.  skipping", array('%name' => $name,'%type' => $type));
+        $this->logMessage("Multiple features exist with the name '%name' of type '%type' for the organism.  skipping",
+          array('%name' => $name,'%type' => $type), TRIPAL_ERROR);
         return 0;
         return 0;
       }
       }
       if (count($results) == 1) {
       if (count($results) == 1) {
@@ -612,8 +592,8 @@ class FASTAImporter extends TripalImporter {
 
 
       $results = chado_select_record('feature', array('feature_id'), $values);
       $results = chado_select_record('feature', array('feature_id'), $values);
       if (count($results) > 1) {
       if (count($results) > 1) {
-        tripal_report_error('T_fasta_loader', TRIPAL_WARNING, "Multiple features exist with the name '%name' of type '%type' for the organism.  skipping", array(
-          '%name' => $name,'%type' => $type));
+        $this->logMessage("Multiple features exist with the name '%name' of type '%type' for the organism.  skipping",
+          array('%name' => $name,'%type' => $type), TRIPAL_WARNING);
         return 0;
         return 0;
       }
       }
       if (count($results) == 1) {
       if (count($results) == 1) {
@@ -622,9 +602,8 @@ class FASTAImporter extends TripalImporter {
 
 
       // If the feature exists but this is an "insert only" then skip.
       // If the feature exists but this is an "insert only" then skip.
       if ($feature and (strcmp($method, 'Insert only') == 0)) {
       if ($feature and (strcmp($method, 'Insert only') == 0)) {
-        tripal_report_error('T_fasta_loader', TRIPAL_WARNING, "Feature already exists '%name' ('%uname') while matching on %type. Skipping insert.", array(
-          '%name' => $name,'%uname' => $uname,'%type' => drupal_strtolower($match_type)
-        ));
+        $this->logMessage("Feature already exists '%name' ('%uname') while matching on %type. Skipping insert.",
+          array('%name' => $name,'%uname' => $uname,'%type' => drupal_strtolower($match_type)), TRIPAL_WARNING);
         return 0;
         return 0;
       }
       }
     }
     }
@@ -649,8 +628,8 @@ class FASTAImporter extends TripalImporter {
       );
       );
       $success = chado_insert_record('feature', $values);
       $success = chado_insert_record('feature', $values);
       if (!$success) {
       if (!$success) {
-        tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to insert feature '%name (%uname)'", array(
-          '%name' => $name,'%uname' => $numane));
+        $this->logMessage("Failed to insert feature '%name (%uname)'", array(
+          '%name' => $name,'%uname' => $numane), TRIPAL_ERROR);
         return 0;
         return 0;
       }
       }
 
 
@@ -666,8 +645,8 @@ class FASTAImporter extends TripalImporter {
         $feature = $results[0];
         $feature = $results[0];
       }
       }
       else {
       else {
-        tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to retreive newly inserted feature '%name (%uname)'", array(
-          '%name' => $name,'%uname' => $numane));
+        $this->logMessage("Failed to retreive newly inserted feature '%name (%uname)'", array(
+          '%name' => $name,'%uname' => $numane), TRIPAL_ERRORR);
         return 0;
         return 0;
       }
       }
 
 
@@ -678,186 +657,175 @@ class FASTAImporter extends TripalImporter {
     // if we don't have a feature and the user wants to do an update then fail
     // if we don't have a feature and the user wants to do an update then fail
     if (!$feature and (strcmp($method, 'Update only') == 0 or
     if (!$feature and (strcmp($method, 'Update only') == 0 or
         drupal_strcmp($method, 'Insert and update') == 0)) {
         drupal_strcmp($method, 'Insert and update') == 0)) {
-          tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to find feature '%name' ('%uname') while matching on " .
-              drupal_strtolower($match_type), array('%name' => $name,'%uname' => $uname));
-          return 0;
-        }
+      $this->logMessage("Failed to find feature '%name' ('%uname') while matching on " . drupal_strtolower($match_type) . ".",
+          array('%name' => $name,'%uname' => $uname), TRIPAL_ERROR);
+      return 0;
+    }
+
+    // if we do have a feature and this is an update then proceed with the update
+    if ($feature and !$inserted and (strcmp($method, 'Update only') == 0 or
+        strcmp($method, 'Insert and update') == 0)) {
+
+      // if the user wants to match on the Name field
+      if (strcmp($match_type, 'Name') == 0) {
+
+        // if we're matching on the name but do not have a unique name then we
+        // don't want to update the uniquename.
+        $values = array();
+        if ($uname) {
 
 
-        // if we do have a feature and this is an update then proceed with the update
-        if ($feature and !$inserted and (strcmp($method, 'Update only') == 0 or
-            strcmp($method, 'Insert and update') == 0)) {
-
-              // if the user wants to match on the Name field
-              if (strcmp($match_type, 'Name') == 0) {
-
-                // if we're matching on the name but do not have a unique name then we
-                // don't want to update the uniquename.
-                $values = array();
-                if ($uname) {
-
-                  // First check to make sure that by changing the unique name of this
-                  // feature that we won't conflict with another existing feature of
-                  // the same name
-        $values = array(
-          'organism_id' => $organism_id,
-          'uniquename' => $uname,
-          'type_id' => $cvterm->cvterm_id
-                  );
-                      $results = chado_select_record('feature', array('feature_id'
-          ), $values);
+          // First check to make sure that by changing the unique name of this
+          // feature that we won't conflict with another existing feature of
+          // the same name
+          $values = array(
+            'organism_id' => $organism_id,
+            'uniquename' => $uname,
+            'type_id' => $cvterm->cvterm_id
+          );
+          $results = chado_select_record('feature', array('feature_id'), $values);
           if (count($results) > 0) {
           if (count($results) > 0) {
-          tripal_report_error('T_fasta_loader', "Cannot update the feature '%name' with a uniquename of '%uname' and type of '%type' as it
-            conflicts with an existing feature with the same uniquename and type.", array(
-                  '%name' => $name,'%uname' => $uname,'%type' => $type
-          ));
-          return 0;
-                }
-
-                // the changes to the uniquename don't conflict so proceed with the update
-                $values = array('uniquename' => $uname);
-                  $match = array(
-                  'name' => $name,
-                  'organism_id' => $organism_id,
-                  'type_id' => $cvterm->cvterm_id
-                );
-
-                // perform the update
-                  $success = chado_update_record('feature', $match, $values);
-        if (!$success) {
-          tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to update feature '%name' ('%name')", array(
-                  '%name' => $name,'%uiname' => $uname
-                  ));
-                  return 0;
-            }
-  }
-  }
+            $this->logMessage("Cannot update the feature '%name' with a uniquename of '%uname' and type of '%type' as it " .
+              "conflicts with an existing feature with the same uniquename and type.",
+              array('%name' => $name,'%uname' => $uname,'%type' => $type), TRIPAL_ERROR);
+            return 0;
+          }
+
+          // the changes to the uniquename don't conflict so proceed with the update
+          $values = array('uniquename' => $uname);
+            $match = array(
+            'name' => $name,
+            'organism_id' => $organism_id,
+            'type_id' => $cvterm->cvterm_id
+          );
+
+          // perform the update
+          $success = chado_update_record('feature', $match, $values);
+          if (!$success) {
+            $this->logMessage("Failed to update feature '%name' ('%name')",
+              array('%name' => $name,'%uiname' => $uname), TRIPAL_ERROR);
+            return 0;
+          }
+        }
+      }
 
 
-  // If the user wants to match on the unique name field.
-  if (strcmp($match_type, 'Unique name') == 0) {
-  // If we're matching on the uniquename and have a new name then
-  // we want to update the name.
-  $values = array();
-  if ($name) {
-      $values = array('name' => $name);
-        $match = array(
-          'uniquename' => $uname,
-          'organism_id' => $organism_id,
-          'type_id' => $cvterm->cvterm_id
-  );
-  $success = chado_update_record('feature', $match, $values);
+      // If the user wants to match on the unique name field.
+      if (strcmp($match_type, 'Unique name') == 0) {
+        // If we're matching on the uniquename and have a new name then
+        // we want to update the name.
+        $values = array();
+        if ($name) {
+          $values = array('name' => $name);
+          $match = array(
+            'uniquename' => $uname,
+            'organism_id' => $organism_id,
+            'type_id' => $cvterm->cvterm_id
+          );
+          $success = chado_update_record('feature', $match, $values);
+          if (!$success) {
+           $this->logMessage("Failed to update feature '%name' ('%name')",
+             array('%name' => $name,'%uiname' => $uname), TRIPAL_ERROR);
+           return 0;
+          }
+        }
+      }
+    }
+
+    // Update the residues for this feature
+    loadFastaResidues($fh, $feature->feature_id, $seq_start, $seq_end);
+
+    // add in the analysis link
+    if ($analysis_id) {
+      // if the association doens't alredy exist then add one
+      $values = array(
+          'analysis_id' => $analysis_id,
+          'feature_id' => $feature->feature_id
+      );
+      $results = chado_select_record('analysisfeature', array('analysisfeature_id'), $values);
+      if (count($results) == 0) {
+        $success = chado_insert_record('analysisfeature', $values);
         if (!$success) {
         if (!$success) {
-          tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to update feature '%name' ('%name')", array(
-          '%name' => $name,'%uiname' => $uname
-          ));
+          $this->logMessage("Failed to associate analysis and feature '%name' ('%name')",
+            array('%name' => $name,'%uname' => $uname), TRIPAL_ERROR);
           return 0;
           return 0;
-  }
-  }
-  }
-  }
+        }
+      }
+    }
+
+    // now add the database cross reference
+    if ($db_id) {
+      // check to see if this accession reference exists, if not add it
+      $values = array(
+      'db_id' => $db_id,
+          'accession' => $accession
+      );
+      $results = chado_select_record('dbxref', array('dbxref_id'), $values);
 
 
-  // Update the residues for this feature
-  loadFastaResidues($fh, $feature->feature_id, $seq_start, $seq_end);
-
-  // add in the analysis link
-  if ($analysis_id) {
-  // if the association doens't alredy exist then add one
-  $values = array(
-      'analysis_id' => $analysis_id,
-      'feature_id' => $feature->feature_id
-  );
-  $results = chado_select_record('analysisfeature', array('analysisfeature_id'), $values);
-                  if (count($results) == 0) {
-                  $success = chado_insert_record('analysisfeature', $values);
-                    if (!$success) {
-                        tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to associate analysis and feature '%name' ('%name')", array(
-                        '%name' => $name,'%uname' => $uname
-                        ));
-                        return 0;
-                        }
-                        }
-                        }
-
-                        // now add the database cross reference
-                        if ($db_id) {
-                        // check to see if this accession reference exists, if not add it
-                        $values = array(
-                        'db_id' => $db_id,
-                            'accession' => $accession
-                        );
-    $results = chado_select_record('dbxref', array('dbxref_id'), $values);
       // if the accession doesn't exist then add it
       // if the accession doesn't exist then add it
-                            if (count($results) == 0) {
-                            $results = chado_insert_record('dbxref', $values);
-                            if (!$results) {
-                            tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to add database accession '%accession'", array(
-                                '%accession' => $accession));
-                        return 0;
-                        }
-                        $results = chado_select_record('dbxref', array('dbxref_id'), $values);
-                        if (count($results) == 1) {
-                        $dbxref = $results[0];
-                        }
-                        else {
-        tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to retreive newly inserted dbxref '%name (%uname)'", array(
-          '%name' => $name,'%uname' => $numane));
+      if (count($results) == 0) {
+        $results = chado_insert_record('dbxref', $values);
+        if (!$results) {
+          $this->logMessage("Failed to add database accession '%accession'",
+            array('%accession' => $accession), TRIPAL_ERROR);
             return 0;
             return 0;
-                        }
-                        }
-                        else {
-      $dbxref = $results[0];
-    }
-
-    // check to see if the feature dbxref record exists if not, then add it
-                        $values = array(
-                        'feature_id' => $feature->feature_id,
-                        'dbxref_id' => $dbxref->dbxref_id
-                        );
-                        $results = chado_select_record('feature_dbxref', array('feature_dbxref_id'), $values);
-                        if (count($results) == 0) {
-                        $success = chado_insert_record('feature_dbxref', $values);
-      if (!$success) {
-        tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to add associate database accession '%accession' with feature", array(
-          '%accession' => $accession
-          ));
+          }
+          $results = chado_select_record('dbxref', array('dbxref_id'), $values);
+          if (count($results) == 1) {
+            $dbxref = $results[0];
+          }
+        else {
+          $this->logMessage("Failed to retreive newly inserted dbxref '%name (%uname)'",
+            array('%name' => $name,'%uname' => $numane), TRIPAL_ERROR);
+            return 0;
+        }
+      }
+      else {
+        $dbxref = $results[0];
+      }
+
+      // check to see if the feature dbxref record exists if not, then add it
+      $values = array(
+        'feature_id' => $feature->feature_id,
+        'dbxref_id' => $dbxref->dbxref_id
+      );
+      $results = chado_select_record('feature_dbxref', array('feature_dbxref_id'), $values);
+      if (count($results) == 0) {
+        $success = chado_insert_record('feature_dbxref', $values);
+        if (!$success) {
+          $this->logMessage("Failed to add associate database accession '%accession' with feature",
+            array('%accession' => $accession), TRIPAL_ERROR);
           return 0;
           return 0;
-                        }
-                        }
-                        }
-
-                        // now add in the relationship if one exists. If not, then add it
-                        if ($rel_type) {
-                        $values = array('organism_id' => $organism_id,'uniquename' => $parent,
-      'type_id' => $parentcvterm->cvterm_id
-                        );
-                          $results = chado_select_record('feature', array('feature_id'
-                          ), $values);
-    if (count($results) != 1) {
-      tripal_report_error('T_fasta_loader', "Cannot find a unique fature for the parent '%parent' of type
-        '%type' for the feature.", array(
-                          '%parent' => $parent,'%type' => $parent_type
-                        ));
-                          return 0;
-                          }
-                          $parent_feature = $results[0];
-
-                          // check to see if the relationship already exists if not then add it
-                          $values = array(
-                            'subject_id' => $feature->feature_id,
-                            'object_id' => $parent_feature->feature_id,
-                            'type_id' => $relcvterm->cvterm_id
-                          );
-                          $results = chado_select_record('feature_relationship', array('feature_relationship_id'), $values);
-                          if (count($results) == 0) {
-                          $success = chado_insert_record('feature_relationship', $values);
-                          if (!$success) {
-                          tripal_report_error('T_fasta_loader', TRIPAL_ERROR, "Failed to add associate database accession '%accession' with feature", array(
-                          '%accession' => $accession
-                          ));
-                          return 0;
+        }
+      }
+    }
+
+    // now add in the relationship if one exists. If not, then add it
+    if ($rel_type) {
+      $values = array('organism_id' => $organism_id,'uniquename' => $parent, 'type_id' => $parentcvterm->cvterm_id);
+      $results = chado_select_record('feature', array('feature_id'), $values);
+      if (count($results) != 1) {
+        $this->logMessage("Cannot find a unique fature for the parent '%parent' of type '%type' for the feature.",
+          array('%parent' => $parent,'%type' => $parent_type), TRIPAL_ERROR);
+          return 0;
+      }
+      $parent_feature = $results[0];
+
+      // check to see if the relationship already exists if not then add it
+      $values = array(
+        'subject_id' => $feature->feature_id,
+        'object_id' => $parent_feature->feature_id,
+        'type_id' => $relcvterm->cvterm_id
+      );
+      $results = chado_select_record('feature_relationship', array('feature_relationship_id'), $values);
+      if (count($results) == 0) {
+        $success = chado_insert_record('feature_relationship', $values);
+        if (!$success) {
+          $this->logMessage("Failed to add associate database accession '%accession' with feature",
+            array('%accession' => $accession), TRIPAL_ERROR);
+          return 0;
+        }
       }
       }
     }
     }
   }
   }
-}
 
 
   /**
   /**
    * Adds the residues column to the feature.
    * Adds the residues column to the feature.
@@ -871,66 +839,45 @@ class FASTAImporter extends TripalImporter {
    * @param $seq_start
    * @param $seq_start
    * @param $seq_end
    * @param $seq_end
    */
    */
-   private function loadFastaResidues($fh, $feature_id, $seq_start, $seq_end) {
-
-     // First position the file at the beginning of the sequence
-     fseek($fh, $seq_start, SEEK_SET);
-     $chunk_size = 100000000;
-     $chunk = '';
-     $seqlen = ($seq_end - $seq_start) + 1;
-
-  // Calculate the interval at which we updated the precent complete.
-  $interval = intval($seqlen * 0.01);
-    if ($interval < 1) {
-    $interval = 1;
-     }
-  // We don't to repeat the update too often or it slows things down, so
-    // if the interval is less than 1000 then bring it up to that.
-    if ($interval < 100000) {
-        $interval = 100000;
-     }
-     $chunk_intv_read = 0;
-     $intv_read = 0;
-       $num_read = 0;
-       $total_seq_size = 0;
-
-       // First, make sure we don't have a null in the residues
-       $sql = "UPDATE {feature} SET residues = '' WHERE feature_id = :feature_id";
-       chado_query($sql, array(':feature_id' => $feature_id
-       ));
-
-       // Read in the lines until we reach the end of the sequence. Once we
-         // get a specific bytes read then append the sequence to the one in the
-         // database.
-           print "Sequence complete: 0%. Memory: " . number_format(memory_get_usage()) . " bytes. \r";
-  while ($line = fgets($fh)) {
-           $num_read += strlen($line) + 1;
-    $chunk_intv_read += strlen($line) + 1;
-           $intv_read += strlen($line) + 1;
-           $chunk .= trim($line);
-
-           // If we've read in enough of the sequence then append it to the database.
-           if ($chunk_intv_read >= $chunk_size) {
-      $sql = "
-        UPDATE {feature}
-        SET residues = residues || :chunk
-        WHERE feature_id = :feature_id
-          ";
-          $success = chado_query($sql, array(':feature_id' => $feature_id,':chunk' => $chunk
-           ));
-      if (!$success) {
-        return FALSE;
-                          }
-                          $total_seq_size += strlen($chunk);
+  private function loadFastaResidues($fh, $feature_id, $seq_start, $seq_end) {
+
+    // First position the file at the beginning of the sequence
+    fseek($fh, $seq_start, SEEK_SET);
+    $chunk_size = 100000000;
+    $chunk = '';
+    $seqlen = ($seq_end - $seq_start) + 1;
+
+    $num_read = 0;
+    $total_seq_size = 0;
+
+    // First, make sure we don't have a null in the residues
+    $sql = "UPDATE {feature} SET residues = '' WHERE feature_id = :feature_id";
+    chado_query($sql, array(':feature_id' => $feature_id));
+
+    // Read in the lines until we reach the end of the sequence. Once we
+    // get a specific bytes read then append the sequence to the one in the
+    // database.
+    while ($line = fgets($fh)) {
+      $num_read += strlen($line) + 1;
+      $chunk_intv_read += strlen($line) + 1;
+      $this->addItemsHandled($num_read);
+      $chunk .= trim($line);
+
+      // If we've read in enough of the sequence then append it to the database.
+      if ($chunk_intv_read >= $chunk_size) {
+        $sql = "
+          UPDATE {feature}
+          SET residues = residues || :chunk
+          WHERE feature_id = :feature_id
+        ";
+        $success = chado_query($sql, array(':feature_id' => $feature_id,':chunk' => $chunk));
+        if (!$success) {
+          return FALSE;
+        }
+        $total_seq_size += strlen($chunk);
         $chunk = '';
         $chunk = '';
         $chunk_intv_read = 0;
         $chunk_intv_read = 0;
       }
       }
-      if ($intv_read >= $interval) {
-        $percent = sprintf("%.2f", ($total_seq_size / $seqlen) * 100);
-        print "Sequence complete: " . $percent . "%. Memory: " . number_format(memory_get_usage()) .
-           " bytes. \r";
-        $intv_read = 0;
-      }
 
 
       // If we've reached the ned of the sequence then break out of the loop
       // If we've reached the ned of the sequence then break out of the loop
       if (ftell($fh) == $seq_end) {
       if (ftell($fh) == $seq_end) {
@@ -945,8 +892,7 @@ class FASTAImporter extends TripalImporter {
           SET residues = residues || :chunk
           SET residues = residues || :chunk
           WHERE feature_id = :feature_id
           WHERE feature_id = :feature_id
         ";
         ";
-      $success = chado_query($sql, array(':feature_id' => $feature_id,':chunk' => $chunk
-      ));
+      $success = chado_query($sql, array(':feature_id' => $feature_id,':chunk' => $chunk));
       if (!$success) {
       if (!$success) {
         return FALSE;
         return FALSE;
       }
       }
@@ -957,12 +903,7 @@ class FASTAImporter extends TripalImporter {
 
 
     // Now update the seqlen and md5checksum fields
     // Now update the seqlen and md5checksum fields
     $sql = "UPDATE {feature} SET seqlen = char_length(residues),  md5checksum = md5(residues) WHERE feature_id = :feature_id";
     $sql = "UPDATE {feature} SET seqlen = char_length(residues),  md5checksum = md5(residues) WHERE feature_id = :feature_id";
-    chado_query($sql, array(':feature_id' => $feature_id
-    ));
+    chado_query($sql, array(':feature_id' => $feature_id));
 
 
-    $percent = sprintf("%.2f", ($num_read / $seqlen) * 100);
-    print "Sequence complete: " . $percent . "%. Memory: " . number_format(memory_get_usage()) .
-       " bytes. \r";
   }
   }
-
 }
 }

File diff suppressed because it is too large
+ 509 - 597
tripal_chado/includes/TripalImporter/GFF3Importer.inc


+ 0 - 3
tripal_chado/includes/setup/tripal_chado.setup.inc

@@ -140,9 +140,6 @@ function tripal_chado_prepare_chado() {
     // We want to force the version of Chado to be set properly.
     // We want to force the version of Chado to be set properly.
     $real_version = chado_get_version(TRUE);
     $real_version = chado_get_version(TRUE);
 
 
-    // Create the temp table we will use for loading OBO files.
-    tripal_chado_add_tripal_obo_temp_table();
-
     // Import commonly used ontologies if needed.
     // Import commonly used ontologies if needed.
     tripal_chado_load_ontologies();
     tripal_chado_load_ontologies();
 
 

+ 10 - 10
tripal_chado/tripal_chado.module

@@ -357,16 +357,16 @@ function tripal_chado_menu() {
     'type' => MENU_NORMAL_ITEM,
     'type' => MENU_NORMAL_ITEM,
     'weight' => 6
     'weight' => 6
   );
   );
-  $items['admin/tripal/loaders/fasta_loader'] = array(
-    'title' => 'Chado FASTA File Loader',
-    'description' => 'Load sequences from a multi-FASTA file into Chado',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('tripal_feature_fasta_load_form'),
-    'access arguments' => array('administer tripal'),
-    'file' => 'includes/loaders/tripal_chado.fasta_loader.inc',
-    'file path' => drupal_get_path('module', 'tripal_chado'),
-    'type' => MENU_NORMAL_ITEM,
-  );
+//   $items['admin/tripal/loaders/fasta_loader'] = array(
+//     'title' => 'Chado FASTA File Loader',
+//     'description' => 'Load sequences from a multi-FASTA file into Chado',
+//     'page callback' => 'drupal_get_form',
+//     'page arguments' => array('tripal_feature_fasta_load_form'),
+//     'access arguments' => array('administer tripal'),
+//     'file' => 'includes/loaders/tripal_chado.fasta_loader.inc',
+//     'file path' => drupal_get_path('module', 'tripal_chado'),
+//     'type' => MENU_NORMAL_ITEM,
+//   );
 //   $items['admin/tripal/loaders/gff3_load'] = array(
 //   $items['admin/tripal/loaders/gff3_load'] = array(
 //     'title' => 'Chado GFF3 File Loader',
 //     'title' => 'Chado GFF3 File Loader',
 //     'description' => 'Import a GFF3 file into Chado',
 //     'description' => 'Import a GFF3 file into Chado',

Some files were not shown because too many files changed in this diff