فهرست منبع

Merge branch '7.x-3.x-dashboard' of github.com:tripal/tripal into 7.x-3.x-dashboard

Shawna Spoor 7 سال پیش
والد
کامیت
0200ee0ba0
100فایلهای تغییر یافته به همراه2530 افزوده شده و 4300 حذف شده
  1. 1 1
      docs/tripal_doxygen.config
  2. 2 2
      legacy/tripal_analysis/includes/tripal_analysis.chado_node.inc
  3. 2 2
      legacy/tripal_analysis/tripal_analysis.install
  4. 1 1
      legacy/tripal_contact/tripal_contact.install
  5. 9 9
      legacy/tripal_core/api/tripal_core.chado_nodes.properties.api.inc
  6. 2 2
      legacy/tripal_core/api/tripal_core.chado_nodes.relationships.api.inc
  7. 1 1
      legacy/tripal_cv/api/tripal_cv.api.inc
  8. 3 42
      legacy/tripal_cv/includes/tripal_cv.cv_defaults.inc
  9. 0 256
      legacy/tripal_cv/includes/tripal_cv.cv_form.inc
  10. 0 474
      legacy/tripal_cv/includes/tripal_cv.cvterm_form.inc
  11. 0 110
      legacy/tripal_example/README.txt
  12. 0 35
      legacy/tripal_example/api/tripal_example.api.inc
  13. 0 96
      legacy/tripal_example/includes/tripal_example.admin.inc
  14. 0 880
      legacy/tripal_example/includes/tripal_example.chado_node.inc
  15. 0 0
      legacy/tripal_example/theme/css/tripal_example.css
  16. 0 9
      legacy/tripal_example/theme/js/tripal_example.js
  17. 0 85
      legacy/tripal_example/theme/templates/tripal_example_base.tpl.php
  18. 0 8
      legacy/tripal_example/theme/templates/tripal_example_help.tpl.php
  19. 0 70
      legacy/tripal_example/theme/templates/tripal_example_properties.tpl.php
  20. 0 70
      legacy/tripal_example/theme/templates/tripal_example_references.tpl.php
  21. 0 151
      legacy/tripal_example/theme/templates/tripal_example_relationships.tpl.php
  22. 0 14
      legacy/tripal_example/theme/templates/tripal_example_teaser.tpl.php
  23. 0 113
      legacy/tripal_example/theme/tripal_example.theme.inc
  24. 0 50
      legacy/tripal_example/tripal_example.info
  25. 0 608
      legacy/tripal_example/tripal_example.install
  26. 0 365
      legacy/tripal_example/tripal_example.module
  27. 0 9
      legacy/tripal_example/tripal_example.views.inc
  28. 0 25
      legacy/tripal_example/tripal_example.views_default.inc
  29. 1 1
      legacy/tripal_feature/includes/tripal_feature.chado_node.inc
  30. 1 1
      legacy/tripal_feature/includes/tripal_feature.delete.inc
  31. 5 5
      legacy/tripal_feature/tripal_feature.install
  32. 1 1
      legacy/tripal_featuremap/tripal_featuremap.install
  33. 1 1
      legacy/tripal_library/includes/tripal_library.chado_node.inc
  34. 12 2
      legacy/tripal_pub/includes/tripal_pub.chado_node.inc
  35. 1 1
      legacy/tripal_pub/tripal_pub.install
  36. 1 1
      legacy/tripal_stock/includes/tripal_stock.chado_node.inc
  37. 0 14
      tripal/api/tripal.entities.api.inc
  38. 137 0
      tripal/api/tripal.importer.api.inc
  39. 150 182
      tripal/api/tripal.jobs.api.inc
  40. 12 6
      tripal/api/tripal.notice.api.inc
  41. 42 309
      tripal/includes/TripalBundleUIController.inc
  42. 1 1
      tripal/includes/TripalEntity.inc
  43. 2 2
      tripal/includes/TripalEntityUIController.inc
  44. 18 21
      tripal/includes/TripalFieldQuery.inc
  45. 41 5
      tripal/includes/TripalFields/TripalFieldFormatter.inc
  46. 1 1
      tripal/includes/TripalFields/content_type/content_type.inc
  47. 1 1
      tripal/includes/TripalFields/rdfs__type/rdfs__type.inc
  48. 606 0
      tripal/includes/TripalImporter.inc
  49. 472 0
      tripal/includes/TripalJob.inc
  50. 4 2
      tripal/includes/tripal.entity.inc
  51. 1 2
      tripal/includes/tripal.field_storage.inc
  52. 1 1
      tripal/includes/tripal.fields.inc
  53. 211 0
      tripal/includes/tripal.importer.inc
  54. 2 2
      tripal/includes/tripal.upload.inc
  55. 0 1
      tripal/includes/tripal_admin_usage_page.inc
  56. 2 4
      tripal/theme/css/tripal.css
  57. 3 2
      tripal/theme/js/TripalUploadFile.js
  58. 1 1
      tripal/theme/js/TripalUploader.js
  59. 20 0
      tripal/theme/js/tripal.file.js
  60. 8 7
      tripal/theme/js/tripal.js
  61. 108 48
      tripal/tripal.install
  62. 212 27
      tripal/tripal.module
  63. 3 5
      tripal/tripal.views.inc
  64. 2 2
      tripal_chado/api/modules/tripal_chado.analysis.api.inc
  65. 3 1
      tripal_chado/api/modules/tripal_chado.cv.api.inc
  66. 36 11
      tripal_chado/api/tripal_chado.api.inc
  67. 3 0
      tripal_chado/api/tripal_chado.mviews.api.inc
  68. 25 0
      tripal_chado/api/tripal_chado.property.api.inc
  69. 3 7
      tripal_chado/api/tripal_chado.query.api.inc
  70. 7 0
      tripal_chado/api/tripal_chado.schema.api.inc
  71. 19 19
      tripal_chado/api/tripal_chado.schema_v1.11.api.inc
  72. 20 20
      tripal_chado/api/tripal_chado.schema_v1.2.api.inc
  73. 9 9
      tripal_chado/api/tripal_chado.schema_v1.3.api.inc
  74. 4 3
      tripal_chado/includes/TripalFields/chado_linker__contact/chado_linker__contact.inc
  75. 1 1
      tripal_chado/includes/TripalFields/chado_linker__cvterm/chado_linker__cvterm.inc
  76. 1 1
      tripal_chado/includes/TripalFields/chado_linker__prop/chado_linker__prop.inc
  77. 2 2
      tripal_chado/includes/TripalFields/data__accession/data__accession.inc
  78. 1 1
      tripal_chado/includes/TripalFields/data__accession/data__accession_widget.inc
  79. 2 2
      tripal_chado/includes/TripalFields/data__protein_sequence/data__protein_sequence.inc
  80. 2 2
      tripal_chado/includes/TripalFields/data__sequence/data__sequence.inc
  81. 1 1
      tripal_chado/includes/TripalFields/data__sequence_coordinates/data__sequence_coordinates.inc
  82. 4 3
      tripal_chado/includes/TripalFields/go__gene_expression/go__gene_expression.inc
  83. 2 2
      tripal_chado/includes/TripalFields/local__source_data/local__source_data.inc
  84. 2 2
      tripal_chado/includes/TripalFields/obi__organism/obi__organism.inc
  85. 3 2
      tripal_chado/includes/TripalFields/ogi__location_on_map/ogi__location_on_map.inc
  86. 2 2
      tripal_chado/includes/TripalFields/sbo__database_cross_reference/sbo__database_cross_reference.inc
  87. 1 1
      tripal_chado/includes/TripalFields/sbo__database_cross_reference/sbo__database_cross_reference_widget.inc
  88. 3 3
      tripal_chado/includes/TripalFields/sbo__phenotype/sbo__phenotype.inc
  89. 22 5
      tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship.inc
  90. 39 38
      tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship_formatter.inc
  91. 2 2
      tripal_chado/includes/TripalFields/schema__additional_type/schema__additional_type.inc
  92. 2 2
      tripal_chado/includes/TripalFields/schema__alternate_name/schema__alternate_name.inc
  93. 2 2
      tripal_chado/includes/TripalFields/schema__publication/schema__publication.inc
  94. 6 2
      tripal_chado/includes/TripalFields/schema__publication/schema__publication_formatter.inc
  95. 2 4
      tripal_chado/includes/TripalFields/schema__publication/schema__publication_widget.inc
  96. 2 1
      tripal_chado/includes/TripalFields/sio__references/sio__references.inc
  97. 112 0
      tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary.inc
  98. 24 0
      tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary_formatter.inc
  99. 54 0
      tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary_widget.inc
  100. 2 2
      tripal_chado/includes/TripalFields/so__cds/so__cds.inc

+ 1 - 1
docs/tripal_doxygen.config

@@ -31,7 +31,7 @@ PROJECT_NAME           = Tripal
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = "v1.1 (6.x-1.1)"
+PROJECT_NUMBER         = "v3.0 (7.x-3.0)"
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer

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

@@ -215,7 +215,7 @@ function chado_analysis_form($node, &$form_state) {
   $day = preg_replace("/^\d+-\d+-0?(\d+) .*/", "$1", $default_time);
   // If the time is not set, use current time
   if (!$default_time) {
-    $default_time = time();
+    $default_time = REQUEST_TIME;
     $year  = format_date($default_time, 'custom', 'Y');
     $month = format_date($default_time, 'custom', 'n');
     $day   = format_date($default_time, 'custom', 'j');
@@ -267,7 +267,7 @@ function chado_analysis_form($node, &$form_state) {
 
   // Properties Form
   // ----------------------------------
-  $instructions = t('To add additional properties to the drop down. ' . l("Add terms to the analysis_property vocabulary", "admin/tripal/vocab/cvterm/add") . ".");
+  $instructions = t('To add additional properties to the drop down. ' . l("Add terms to the analysis_property vocabulary", "admin/tripal/loaders/chado_cv/cvterm/add") . ".");
   $prop_cv = tripal_get_default_cv('analysisprop', 'type_id');
   $cv_id = $prop_cv ? $prop_cv->cv_id : NULL;
   $details = array(

+ 2 - 2
legacy/tripal_analysis/tripal_analysis.install

@@ -81,7 +81,7 @@ function tripal_analysis_uninstall() {
  *
  * @ingroup tripal_analysis
  */
-// This function was moved to tripal_chado/includes/tripal_chado.setup.inc
+// This function was moved to tripal_chado/includes/setup/tripal_chado.setup.inc
 /* function tripal_analysis_create_analysisfeatureprop() {
 
   // Create analysisfeatureprop table in chado.  This is needed for Chado
@@ -237,7 +237,7 @@ function tripal_analysis_schema() {
  *
  * @ingroup tripal_analysis
  */
-// This function was moved to tripal_chado/includes/tripal_chado.setup.inc
+// This function was moved to tripal_chado/includes/setup/tripal_chado.setup.inc
 /* function tripal_analysis_add_mview_analysis_organism() {
   $view_name = 'analysis_organism';
   $comment = t('This view is for associating an organism (via it\'s associated features) to an analysis.');

+ 1 - 1
legacy/tripal_contact/tripal_contact.install

@@ -172,7 +172,7 @@ function tripal_contact_schema() {
  *
  * @ingroup tripal_contact
  */
-// This function was moved to tripal_chado/includes/tripal_chado.setup.inc
+// This function was moved to tripal_chado/includes/setup/tripal_chado.setup.inc
 /* function tripal_contact_add_custom_tables(){
   $schema = array (
     'table' => 'contactprop',

+ 9 - 9
legacy/tripal_core/api/tripal_core.chado_nodes.properties.api.inc

@@ -293,7 +293,7 @@ function chado_add_node_form_properties(&$form, &$form_state, $details) {
         to the %cv_name controlled vocabulary.',
         array(
           '%cv_name' => $details['cv_name'],
-          '@cvtermlink' => url('admin/tripal/vocab/cv/' . $details['cv_id'] . '/cvterm/add')
+          '@cvtermlink' => url('admin/tripal/loaders/chado_cv/' . $details['cv_id'] . '/cvterm/add')
         )
       ),
       TRIPAL_NOTICE,
@@ -306,7 +306,7 @@ function chado_add_node_form_properties(&$form, &$form_state, $details) {
         a controlled vocabulary term</a> to the %cv_name controlled vocabulary.',
         array(
           '%cv_name' => $details['cv_name'],
-          '@cvtermlink' => url('admin/tripal/vocab/cv/' . $details['cv_id'] . '/cvterm/add')
+          '@cvtermlink' => url('admin/tripal/loaders/chado_cv/' . $details['cv_id'] . '/cvterm/add')
         )
       ),
       TRIPAL_INFO,
@@ -325,15 +325,15 @@ function chado_add_node_form_properties(&$form, &$form_state, $details) {
   );
 
   // the fieldset of the property elements
-  $instructions = 'To add properties of the current %nodetype, select the type of 
-      information from the drop-down below and enter the information in the text box before 
-      clicking "Add". To remove incorrect information, click the "Remove" button. 
-      Note: you cannot edit previously added information but instead need to 
+  $instructions = 'To add properties of the current %nodetype, select the type of
+      information from the drop-down below and enter the information in the text box before
+      clicking "Add". To remove incorrect information, click the "Remove" button.
+      Note: you cannot edit previously added information but instead need to
       remove and re-add it.';
   $form['properties'] = array(
     '#type' => 'fieldset',
     '#title' => t($details['fieldset_title']),
-    '#description' => t('<p><strong>Additional information about a 
+    '#description' => t('<p><strong>Additional information about a
       %nodetype.</strong></p><p>'. $instructions . $details['additional_instructions'] . '</p>', array('%nodetype' => $details['nodetype'])) ,
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
@@ -363,7 +363,7 @@ function chado_add_node_form_properties(&$form, &$form_state, $details) {
     '#type' => 'markup',
     '#prefix' => '<div id="property-save-warning" class="messages warning" style="display:none;">',
     '#suffix' => '</div>',
-    '#markup' => '* The changes to these properties will not be saved until the 
+    '#markup' => '* The changes to these properties will not be saved until the
       "Save" button at the bottom of this form is clicked. <span class="specific-changes"></span>',
     '#attached' => array(
       'js' => array(
@@ -649,7 +649,7 @@ function chado_add_node_form_properties(&$form, &$form_state, $details) {
  * @ingroup tripal_core
  */
 function chado_add_node_form_properties_add_button_validate($form, &$form_state) {
-  
+
   // Ensure the type_id is supplied & Valid
   $cvterm = chado_select_record(
     'cvterm',

+ 2 - 2
legacy/tripal_core/api/tripal_core.chado_nodes.relationships.api.inc

@@ -254,7 +254,7 @@ function chado_add_node_form_relationships(&$form, &$form_state, $details) {
         to the %cv_name controlled vocabulary.',
         array(
           '%cv_name' => $details['cv_name'],
-          '@cvtermlink' => url('admin/tripal/vocab/cv/'.$details['cv_id'].'/cvterm/add')
+          '@cvtermlink' => url('admin/tripal/loaders/chado_cv/'.$details['cv_id'].'/cvterm/add')
         )
       ),
       TRIPAL_WARNING,
@@ -267,7 +267,7 @@ function chado_add_node_form_relationships(&$form, &$form_state, $details) {
         a controlled vocabulary term</a> to the %cv_name controlled vocabulary.',
         array(
           '%cv_name' => $details['cv_name'],
-          '@cvtermlink' => url('admin/tripal/vocab/cv/' . $details['cv_id'] . '/cvterm/add')
+          '@cvtermlink' => url('admin/tripal/loaders/chado_cv/' . $details['cv_id'] . '/cvterm/add')
         )
       ),
       TRIPAL_INFO,

+ 1 - 1
legacy/tripal_cv/api/tripal_cv.api.inc

@@ -97,7 +97,7 @@ function tripal_get_cvterm_default_select_options($table, $field, $field_desc) {
     if (count($options) == 0) {
       tripal_set_message('There are no ' . $field_desc . '. Please ' .
           l('add terms',
-              'admin/tripal/vocab/cv/' .$default_cv->cv_id. '/cvterm/add',
+              'admin/tripal/loaders/chado_cv/' .$default_cv->cv_id. '/cvterm/add',
               array('attributes' => array('target' => '_blank'))) . ' to the ' .
           $default_cv->name .' vocabulary.',
           TRIPAL_WARNING);

+ 3 - 42
legacy/tripal_cv/includes/tripal_cv.cv_defaults.inc

@@ -1,44 +1,5 @@
 <?php
-/**
- * Provide landing page to the new admin pages
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_admin_cv_listing() {
-  $output = '';
-
-  // set the breadcrumb
-  $breadcrumb = array();
-  $breadcrumb[] = l('Home', '<front>');
-  $breadcrumb[] = l('Administration', 'admin');
-  $breadcrumb[] = l('Tripal', 'admin/tripal');
-  $breadcrumb[] = l('Chado Modules', 'admin/tripal/legacy');
-  $breadcrumb[] = l('Vocabularies', 'admin/tripal/legacy/vocab');
-  drupal_set_breadcrumb($breadcrumb);
-
-  // Add the view
-  $cvs_view = views_embed_view('tripal_cv_admin_cvs','default');
-  $cvterms_view = views_embed_view('tripal_cv_admin_cvterms','default');
-  if (isset($cvs_view) && isset($cvterms_view)) {
-    $output .= $cvs_view;
-  }
-  else {
-    $output .= '<p>The Tripal Controlled Vocabulary module uses primarily views to provide an '
-        . 'administrative interface. Currently one or more views needed for this '
-            . 'administrative interface are disabled. <strong>Click each of the following links to '
-                . 'enable the pertinent views</strong>:</p>';
-    $output .= '<ul>';
-    if (!isset($cvs_view)) {
-      $output .= '<li>'.l('Tripal Vocabularies', 'admin/tripal/vocab/views/cvs/enable').'</li>';
-    }
-    if (!isset($cvterm_view)) {
-      $output .= '<li>'.l('Tripal Vocabulary Terms', 'admin/tripal/vocab/views/cvterms/enable').'</li>';
-    }
-    $output .= '</ul>';
-  }
 
-  return $output;
-}
 
 /**
  *
@@ -118,18 +79,18 @@ function tripal_cv_admin_set_defaults_form($form, &$form_state) {
     );
 
     // Actions
-    $view_terms = l('New Vocabulary', 'admin/tripal/vocab/cv/add');
+    $view_terms = l('New Vocabulary', 'admin/tripal/loaders/chado_cv/add');
     $add_term = '';
     if (!empty($cv)) {
       $view_terms = l(
           'View Terms',
-          'admin/tripal/vocab/cvterms',
+          'admin/tripal/loaders/chado_cvterms',
           array('query' => array('cv' => $cv->name))
       );
 
       $add_term = l(
           'Add Term',
-          'admin/tripal/vocab/cv/' . $cv->cv_id . '/cvterm/add'
+          'admin/tripal/loaders/chado_cv/' . $cv->cv_id . '/cvterm/add'
       );
     }
     $form['settings']['existing'][$cv_default_id]["view-terms"] = array(

+ 0 - 256
legacy/tripal_cv/includes/tripal_cv.cv_form.inc

@@ -4,260 +4,4 @@
  * Provides a form for creating & editing chado controlled vocabularies
  */
 
-/**
- * Provides the actual "Select CV" form on the Update/Delete Controlled
- *   Vocabulary page. This form also triggers the edit javascript
- * @todo Modify this form to use Drupal AJAX
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cv_edit_form($form, &$form_state) {
-
-  // get the cv_d if form was submitted via AJAX
-  $cv_id = 0;
-  if (array_key_exists('values', $form_state)) {
-    $cv_id = $form_state['values']['cv_id'];
-  }
-  elseif (isset($form_state['build_info']['args'][0])) {
-    $cv_id = $form_state['build_info']['args'][0];
-  }
-
-  // get a list of db from chado for user to choose
-  $sql = "SELECT * FROM {cv} WHERE NOT name = 'tripal' ORDER BY name ";
-  $results = chado_query($sql);
-
-  $cvs = array();
-  $cvs[] = 'Select a vocabulary';
-  foreach ($results as $cv) {
-    $cvs[$cv->cv_id] = $cv->name;
-  }
-
-  $form['cv_id'] = array(
-    '#title' => t('Controlled Vocabulary Name'),
-    '#type' => 'select',
-    '#options' => $cvs,
-    '#ajax' => array(
-      'callback' => 'tripal_cv_edit_form_ajax',
-      'wrapper'  => 'cv-edit-div',
-      'effect'   => 'fade',
-      'event'    => 'change',
-      'method'   => 'replace',
-    ),
-    '#default_value' => $cv_id,
-  );
-
-
-  // if we don't have a db_id then we can  return the form, otherwise
-  // add in the other fields
-  if ($cv_id) {
-    tripal_cv_add_cv_form_fields($form, $form_state, $cv_id);
-
-    $form['update'] = array(
-      '#type'         => 'submit',
-      '#value'        => t('Update'),
-    );
-    $form['delete'] = array(
-      '#type'         => 'submit',
-      '#value'        => t('Delete'),
-      '#attributes'   => array('onclick' => 'if(!confirm("Really Delete?")){return false;}'),
-    );
-  }
-  else {
-    // if we don't have a dbid then this is the first time the form has
-    // benn loaded and we need to create the div where ajax replacement elements get stored
-    $form['div_replace'] = array(
-      '#type' => 'item',
-      '#prefix' => '<div id="cv-edit-div">',
-      '#suffix' => '</div>',
-    );
-  }
-  return $form;
-}
-
-/**
- * Form to add contolled vocabularies
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cv_add_form($form, &$form_state) {
-
-  // add in the form fields to this form
-  tripal_cv_add_cv_form_fields($form, $form_state);
-
-  $form['add'] = array(
-    '#type'         => 'submit',
-    '#value'        => t('Add'),
-    '#weight'       => 5,
-  );
-  return $form;
-}
-
-/**
- * Form fields in common between the cv add & edit form.
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_add_cv_form_fields(&$form, $form_state, $cv_id = NULL) {
-
-  $default_name = '';
-  $default_desc = '';
-
-  if ($cv_id) {
-    $values = array('cv_id' => $cv_id);
-    $result = chado_select_record('cv', array('*'), $values);
-    $cv = $result[0];
-    $default_name = $cv->name;
-    $default_desc = $cv->definition;
-  }
-
-  // add a fieldset for the Drupal Schema API
-  $form['fields'] = array(
-    '#type' => 'fieldset',
-    '#title' => 'Controlled Vocabulary Details',
-    '#collapsible' => 0,
-  );
-
-  $form['fields']['name']= array(
-    '#type'          => 'textfield',
-    '#title'         => t("Controlled Vocabulary name"),
-    '#description'   => t('Please enter the name for this vocabulary.'),
-    '#required'      => TRUE,
-    '#default_value' => $default_name,
-    '#maxlength'     => 255,
-  );
-
-  $form['fields']['definition']= array(
-    '#type'          => 'textarea',
-    '#title'         => t('Description'),
-    '#description'   => t('Please enter a definition for this vocabulary'),
-    '#default_value' => $default_desc,
-  );
-
-  return $form;
-}
-
-/**
- * Validation fucntion for tripal_cv_cv_add_form
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cv_add_form_validate($form, &$form_state) {
-  tripal_cv_form_fields_validate($form, $form_state);
-}
-
-/**
- * Validation fucntion for tripal_cv_cv_edit_form
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cv_edit_form_validate($form, &$form_state) {
-  tripal_cv_form_fields_validate($form, $form_state);
-}
-
-/**
- * Generic validation form for shared fields of both the edit and add forms
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_form_fields_validate($form, &$form_state) {
-  $name =  array_key_exists('name', $form_state['values'])       ? trim($form_state['values']['name']) : '';
-  $desc =  array_key_exists('definition', $form_state['values']) ? trim($form_state['values']['definition']) : '';
-  $cv_id = array_key_exists('cv_id', $form_state['values'])      ? trim($form_state['values']['cv_id']) : '';
-
-
-  // make sure the cv name is unique
-  $values = array('name' => $name);
-  $results = chado_select_record('cv', array('cv_id'), $values);
-  if (count($results) > 0 and $results[0]->cv_id != $cv_id) {
-    form_set_error('name', 'The vocabulary name must be unique');
-  }
-}
-
-/**
- * Submit cv add form
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cv_add_form_submit($form, &$form_state) {
-
-  $name =  array_key_exists('name', $form_state['values'])       ? trim($form_state['values']['name']) : '';
-  $desc =  array_key_exists('definition', $form_state['values']) ? trim($form_state['values']['definition']) : '';
-
-  $values = array(
-    'name' => $name,
-    'definition' => $desc,
-  );
-  $success = chado_insert_record('cv', $values);
-  if ($success) {
-    drupal_set_message(t("Controlled vocabulary added"));
-  }
-  else {
-    drupal_set_message(t("Failed to add controlled vocabulary."));
-  }
-}
-
-/**
- * Submit cv edit form
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cv_edit_form_submit($form, &$form_state) {
-  $name  = array_key_exists('name', $form_state['values'])       ? trim($form_state['values']['name']) : '';
-  $desc  = array_key_exists('definition', $form_state['values']) ? trim($form_state['values']['definition']) : '';
-  $cv_id = array_key_exists('cv_id', $form_state['values'])      ? trim($form_state['values']['cv_id']) : '';
-  $op    = array_key_exists('op', $form_state['values'])         ? trim($form_state['values']['op']) : '';
-
-  $values = array(
-    'name' => $name,
-    'definition' => $desc,
-  );
-  if (strcmp($op, 'Update')==0) {
-    $match = array('cv_id' => $cv_id);
-    $success = chado_update_record('cv', $match, $values);
-    if ($success) {
-      drupal_set_message(t("Controlled vocabulary updated"));
-    }
-    else {
-      drupal_set_message(t("Failed to update controlled vocabulary."));
-    }
-  }
-  if (strcmp($op, 'Delete')==0) {
-    $match = array('cv_id' => $cv_id);
-    $success = chado_delete_record('cv', $match);
-    if ($success) {
-      drupal_set_message(t("Controlled vocabulary deleted"));
-    }
-    else {
-      drupal_set_message(t("Failed to delete controlled vocabulary."));
-    }
-  }
-}
-
-/**
- * Ajax callback for the tripal_cv_form
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_edit_form_ajax($form, $form_state) {
-
-  $elements = array();
-
-  // add in the form fields and the buttons
-  if (array_key_exists('cv_id', $form_state['values'])) {
-    $elements['fields'] = $form['fields'];
-    $elements['update'] = $form['update'];
-    $elements['delete'] = $form['delete'];
-  }
-
-   // add back in the cv-edit-div that is used for the next round of AJAX
-  $elements['fields']['#prefix'] =  '<div id="cv-edit-div">';
-  $elements['fields']['#suffix'] =  '</div">';
-
-  // reset the values for the fields to the defaults
-  $elements['fields']['name']['#value']        = $elements['fields']['name']['#default_value'];
-  $elements['fields']['definition']['#value']  = $elements['fields']['definition']['#default_value'];
-
-  //drupal_set_message('<pre>' . print_r($elements, TRUE) . '</pre>', "status");
 
-  return $elements;
-}

+ 0 - 474
legacy/tripal_cv/includes/tripal_cv.cvterm_form.inc

@@ -3,477 +3,3 @@
  * @file
  * Provides a form for creating & editing chado controlled vocabularies
  */
-
-/**
- * Form for editing cvterms
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cvterm_edit_form($form, &$form_state) {
-
-  $step = 0;
-  if (empty($form_state['storage']['step'])) {
-    $form_state['storage']['step'] = 0;
-  }
-  else {
-    $step = $form_state['storage']['step'];
-  }
-
-  $cv_id = 0;
-  if ($step == 1) {
-    $cv_id = $form_state['storage']['cv_id'];
-    $cvterm_name = $form_state['storage']['name'];
-    $cvterm_id = $form_state['storage']['cvterm_id'];
-  }
-  // get the cv if form was submitted via AJAX
-  $cvterm = '';
-  if (array_key_exists('values', $form_state)) {
-    $cv_id = $form_state['values']['cv_id'];
-    if (array_key_exists('cvterm', $form_state['values'])) {
-      $cvterm = $form_state['values']['cvterm'];
-    }
-  }
-  elseif (isset($form_state['build_info']['args'][0])) {
-    $cv_id = $form_state['build_info']['args'][0];
-    $cvterm_id = $form_state['build_info']['args'][1];
-    if ($form_state['build_info']['args'][1]) {
-      $result = db_select('chado.cvterm','c')
-        ->fields('c', array('name'))
-        ->condition('c.cvterm_id',$cvterm_id)
-        ->execute();
-      $cvterm_name = $result->fetchObject()->name;
-      $step = 1;
-    }
-  }
-
-  // get a list of CVs
-  $cvs = array();
-  $sql = "SELECT * FROM {cv} WHERE NOT name = 'tripal' ORDER BY name ";
-  $results = chado_query($sql);
-  $cvs[] = 'Select a vocabulary';
-  foreach ($results as $cv) {
-    $cvs[$cv->cv_id] = $cv->name;
-  }
-  $form['cv_id'] = array(
-    '#title' => t('Controlled Vocabulary (Ontology) Name'),
-    '#type' => 'select',
-    '#options' => $cvs,
-    '#required' => TRUE,
-    '#default_value' => $cv_id,
-    '#ajax' => array(
-       'callback'    => 'tripal_cv_cvterm_edit_form_ajax',
-       'wrapper' => 'cvterm-edit-div',
-       'event'   => 'change',
-       'method'  => 'replace',
-       'event'    => 'change',
-    ),
-  );
-
-  if ($cv_id and $step == 0) {
-
-    $form['name']= array(
-      '#type'          => 'textfield',
-      '#title'         => t("Term Name"),
-      '#default_value' => $cvterm,
-      '#required'      => TRUE,
-      '#autocomplete_path' => "admin/tripal/tripal_cv/cvterm/auto_name/$cv_id",
-      '#description'   => t('Enter the term to edit.')
-    );
-    $form['continue']= array(
-      '#type'          => 'submit',
-      '#value'         => 'continue',
-    );
-  }
-  elseif ($step == 1) {
-
-    tripal_cv_add_cvterm_form_fields($form, $form_state, $cv_id, $cvterm_name);
-
-    // when editing there are certain fields the user should not change for a term
-    // let's mark those as disabled
-    $form['cv_id']['#disabled'] = TRUE;
-    $form['fields']['db_id']['#disabled'] = TRUE;
-    $form['fields']['accession']['#disabled'] = TRUE;
-
-    // add in the div for replacing the fields if needed
-    $form['fields']['#prefix'] = '<div id="cvterm-edit-div">';
-    $form['fields']['#suffix'] = '</div>';
-
-    // add in the cvterm id
-    $form['fields']['cvterm_id'] = array(
-      '#type' => 'hidden',
-      '#value' =>  $cvterm_id,
-    );
-
-    $form['update'] = array(
-      '#type'         => 'submit',
-      '#value'        => t('Update'),
-    );
-    $form['delete'] = array(
-      '#type'         => 'submit',
-      '#value'        => t('Delete'),
-      '#attributes'   => array('onclick' => 'if(!confirm("Really Delete?")){return false;}'),
-    );
-  }
-
-  if ($step == 0) {
-    // if we don't have a cv_id then this is the first time the form has
-    // benn loaded and we need to create the div where ajax replacement elements get stored
-    $form['div_replace'] = array(
-      '#type' => 'item',
-      '#prefix' => '<div id="cvterm-edit-div">',
-      '#suffix' => '</div>',
-    );
-  }
-  return $form;
-}
-
-/**
- * Form for adding cvterms
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cvterm_add_form($form, &$form_state) {
-  $cv_id = 0;
-  if (array_key_exists('values', $form_state)) {
-    $cv_id = $form_state['values']['cv_id'];
-  }
-  elseif (isset($form_state['build_info']['args'][0])) {
-    $cv_id = $form_state['build_info']['args'][0];
-  }
-
-  // get a list of CVs
-  $cvs = array();
-  $sql = "SELECT * FROM {cv} WHERE NOT name = 'tripal' ORDER BY name ";
-  $results = chado_query($sql);
-  $cvs[] = 'Select a vocabulary';
-  foreach ($results as $cv) {
-    $cvs[$cv->cv_id] = $cv->name;
-  }
-  $form['cv_id'] = array(
-    '#title' => t('Controlled Vocabulary (Ontology) Name'),
-    '#type' => 'select',
-    '#options' => $cvs,
-    '#required' => TRUE,
-    '#default_value' => $cv_id,
-  );
-  tripal_cv_add_cvterm_form_fields($form, $form_state);
-
-  $form['add'] = array(
-    '#type'         => 'submit',
-    '#value'        => t('Add Term'),
-  );
-
-  return $form;
-}
-
-/**
- * Form fields in common between add/edit forms
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_add_cvterm_form_fields(&$form, $form_state, $cv_id = 0, $cvterm_name = '') {
-
-  $name = '';
-  $definition = '';
-  $is_relationship = '';
-  $is_obsolete = '';
-  $db_id = '';
-  $accession = '';
-
-  // get default values
-  if ($cvterm_name) {
-    $values = array('cv_id' => $cv_id, 'name' => $cvterm_name);
-    $cvterm = chado_generate_var('cvterm', $values);
-    $name = $cvterm->name;
-    $definition = $cvterm->definition;
-    $is_relationship = $cvterm->is_relationshiptype;
-    $is_obsolete = $cvterm->is_obsolete;
-    $db_id = $cvterm->dbxref_id->db_id->db_id;
-    $accession = $cvterm->dbxref_id->accession;
-  }
-
-  // add a fieldset for the Drupal Schema API
-  $form['fields'] = array(
-    '#type' => 'fieldset',
-    '#title' => 'Term Details',
-    '#collapsible' => 0,
-  );
-
-  $form['fields']['name']= array(
-    '#type'          => 'textfield',
-    '#title'         => t("Term Name"),
-    '#default_value' => $name,
-    '#description'   => t('The term must be unique within the database selected below.'),
-    '#required'      => TRUE,
-  );
-
-  $form['fields']['internal_id']= array(
-    '#type'          => 'item',
-    '#title'         => t("Internal ID"),
-    '#markup'        => $cvterm->cvterm_id,
-  );
-
-  $form['fields']['definition']= array(
-    '#type'          => 'textarea',
-    '#title'         => t('Description'),
-    '#description'   => t('Please enter a description for this term'),
-    '#default_value' => $definition,
-  );
-
-  $form['fields']['is_relationship'] = array(
-    '#type'          => 'checkbox',
-    '#title'         => t('This term describes a relationship?'),
-    '#default_value' => $is_relationship,
-  );
-
-  $form['fields']['is_obsolete'] = array(
-    '#type'          => 'checkbox',
-    '#title'         => t('This term is obsolete?'),
-    '#default_value' => $is_obsolete,
-  );
-
-  $values = array();
-  $columns = array('db_id', 'name');
-  $options = array('order_by' => array('name' => 'ASC'));
-  $results = chado_select_record('db', $columns, $values, $options);
-  $dbs = array();
-  $dbs[] = '';
-  foreach ($results as $db) {
-    $dbs[$db->db_id] = $db->name;
-  }
-  $form['fields']['db_id'] = array(
-    '#type'         => 'select',
-    '#title'         => t('Database'),
-    '#description'   => t('All terms must be assocated with a database. If there is no database for this term (e.g. it is a custom term specific to this site) then select the database \'null\' or consider creating a database specific for your site and use that anytime you would like to add terms.'),
-    '#options'      => $dbs,
-    '#default_value' => $db_id,
-    '#required' => TRUE,
-  );
-
-  $form['fields']['accession']= array(
-    '#type'          => 'textfield',
-    '#title'         => t("Accession"),
-    '#description'   => t('If this term has an existing accession (unique identifier) in the database
-       please enter that here.  If the accession is numeric with a database prefix (e.g. GO:003023), please
-       enter just the numeric value.  The database prefix will be appended whenever the term is displayed.
-       If you do not have a numeric value consider entering the term name as the accession.'),
-    '#required'      => TRUE,
-    '#default_value' => $accession,
-  );
-}
-
-/**
- * Validate cvterm edit form
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cvterm_edit_form_validate($form, &$form_state) {
-  $cv_id = array_key_exists('cv_id', $form_state['values']) ? $form_state['values']['cv_id'] : '';
-  $db_id = array_key_exists('db_id', $form_state['values']) ? $form_state['values']['db_id'] : '';
-  $name = array_key_exists('name', $form_state['values']) ? $form_state['values']['name'] : '';
-  $cvterm_id = array_key_exists('cvterm_id', $form_state['values']) ? $form_state['values']['cvterm_id'] : '';
-  $accession = array_key_exists('accession', $form_state['values']) ? $form_state['values']['accession'] : '';
-
-  $step = $form_state['storage']['step'];
-
-  // make sure the cv term name is unique for this vocabulary
-  if ($step == 1) {
-    $values = array('name' => $name, 'cv_id' => $cv_id);
-    $results = chado_select_record('cvterm', array('cvterm_id'), $values);
-    foreach ($results as $r) {
-      if ($r->cvterm_id != $cvterm_id) {
-        form_set_error('name', 'The term name must be unique for this vocabulary. Another term with this name already exists.');
-      }
-    }
-  }
-}
-
-/**
- * Validate cv add form
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cvterm_add_form_validate($form, &$form_state) {
-  $cv_id = array_key_exists('cv_id', $form_state['values']) ? $form_state['values']['cv_id'] : '';
-  $db_id = array_key_exists('db_id', $form_state['values']) ? $form_state['values']['db_id'] : '';
-  $name = array_key_exists('name', $form_state['values']) ? $form_state['values']['name'] : '';
-  $accession = array_key_exists('accession', $form_state['values']) ? $form_state['values']['accession'] : '';
-
-  $values = array('cv_id' => $cv_id);
-  $results = chado_select_record('cv', array('name'), $values);
-  if (!$results or count($results) == 0) {
-    form_set_error('cv_id', 'The controlled vocabulary does not exist');
-  }
-
-  // make sure the DB exists
-  $values = array('db_id' => $db_id);
-  $results = chado_select_record('db', array('name'), $values);
-  if (!$results or count($results) == 0) {
-    form_set_error('db_id', 'The database name does not exist');
-  }
-
-  // make sure the cv term name is unique for this vocabulary
-  $values = array('name' => $name, 'cv_id' => $cv_id);
-  $results = chado_select_record('cvterm', array('cvterm_id'), $values);
-  if (count($results) > 0) {
-    form_set_error('name', 'The term name must be unique for this vocabulary. Another term with this name already exists.');
-  }
-
-  // make sure this accession is unique for the database
-  $values = array('accession' => $accession, 'db_id' => $db_id);
-  $results = chado_select_record('dbxref', array('dbxref_id'), $values);
-  if (count($results) > 0 ) {
-    form_set_error('accession', 'The accession is not uniuqe for this vocabulary\'s database.');
-  }
-
-}
-
-/**
- * Edits existing controlled vocabulary terms
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cvterm_edit_form_submit($form, &$form_state) {
-
-  $cv_id           = array_key_exists('cv_id', $form_state['values'])           ? trim($form_state['values']['cv_id']) : '';
-  $name            = array_key_exists('name', $form_state['values'])            ? trim($form_state['values']['name']) : '';
-  $definition      = array_key_exists('definition', $form_state['values'])      ? trim($form_state['values']['definition']) : '';
-  $is_relationship = array_key_exists('is_relationship', $form_state['values']) ? trim($form_state['values']['is_relationship']) : '';
-  $is_obsolete     = array_key_exists('is_obsolete', $form_state['values'])     ? trim($form_state['values']['is_obsolete']) : '';
-  $cvterm_id       = array_key_exists('cvterm_id', $form_state['values'])       ? trim($form_state['values']['cvterm_id']) : '';
-  $db_id           = array_key_exists('db_id', $form_state['values'])           ? trim($form_state['values']['db_id']) : '';
-  $accession       = array_key_exists('accession', $form_state['values'])       ? trim($form_state['values']['accession']) : '';
-  $op              = array_key_exists('op', $form_state['values'])              ? trim($form_state['values']['op']) : '';
-
-
-  $step = $form_state['storage']['step'];
-
-  switch ($step) {
-    case 0:  // a cvterm name has been selected
-      $cv_id = array_key_exists('cv_id', $form_state['values']) ? trim($form_state['values']['cv_id']) : '';
-      $name  = array_key_exists('name', $form_state['values'])  ? trim($form_state['values']['name'])  : '';
-
-      // get the original cvterm_id
-      $values = array('name' => $name, 'cv_id' => $cv_id);
-      $results = chado_select_record('cvterm', array('cvterm_id'), $values);
-      $cvterm = $results[0];
-
-      $form_state['storage']['cv_id'] = $cv_id;
-      $form_state['storage']['name'] = $name;
-      $form_state['storage']['step'] = 1;
-      $form_state['storage']['cvterm_id'] = $cvterm->cvterm_id;
-      $form_state['rebuild'] = TRUE;
-      break;
-
-    case 1:  // update/delete button has been clicked
-
-      if ($op == 'Update') {
-        // get the cv
-        $values = array('cv_id' => $cv_id);
-        $results = chado_select_record('cv', array('name'), $values);
-        $cv = $results[0];
-
-        // get the db
-        $values = array('db_id' => $db_id);
-        $results = chado_select_record('db', array('name'), $values);
-        $db = $results[0];
-
-        // now add the term
-        $term = array(
-          'name' => $name,
-          'namespace' => $cv->name,
-          'id' => $accession,
-          'definition' => $definition,
-          'is_obsolete' => $is_obsolete,
-          'cv_name' => $cv->name,
-          'is_relationship' => $is_relationship,
-          'db_name' => $db_name
-        );
-
-        $cvterm = tripal_insert_cvterm($term, array('update_existing' => TRUE));
-        if ($cvterm) {
-          drupal_set_message('Term updated successfully.');
-        }
-        else {
-          drupal_set_message('Could not add term. Check Drupal recent logs for error messages.', 'error');
-        }
-      }
-      if ($op == 'Delete') {
-        $values = array('cvterm_id' => $cvterm_id);
-        $success = chado_delete_record('cvterm', $values);
-        if ($success) {
-          drupal_set_message('Term deleted successfully.');
-        }
-        else {
-          drupal_set_message('Could not delete term term. Check Drupal recent logs for error messages.', 'error');
-        }
-      }
-      break;
-  }
-}
-
-/**
- * Adds new terms to an existing cv
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cvterm_add_form_submit($form, &$form_state) {
-  $cv_id = array_key_exists('cv_id', $form_state['values']) ? $form_state['values']['cv_id'] : '';
-  $name = array_key_exists('name', $form_state['values']) ? $form_state['values']['name'] : '';
-  $definition = array_key_exists('definition', $form_state['values']) ? $form_state['values']['definition'] : '';
-  $is_relationship = array_key_exists('is_relationship', $form_state['values']) ? $form_state['values']['is_relationship'] : '';
-  $is_obsolete = array_key_exists('is_obsolete', $form_state['values']) ? $form_state['values']['is_obsolete'] : '';
-
-  $db_id = array_key_exists('db_id', $form_state['values']) ? $form_state['values']['db_id'] : '';
-  $accession = array_key_exists('accession', $form_state['values']) ? $form_state['values']['accession'] : '';
-
-  // get the database
-  $values = array('db_id' => $db_id);
-  $results = chado_select_record('db', array('name'), $values);
-  $db = $results[0];
-
-  // get the cv
-  $values = array('cv_id' => $cv_id);
-  $results = chado_select_record('cv', array('name'), $values);
-  $cv = $results[0];
-
-  // now add the term
-  $term = array(
-    'name' => $name,
-    'namespace' => $cv->name,
-    'id' => $accession,
-    'definition' => $definition,
-    'is_obsolete' => $is_obsolete,
-    'cv_name' => $cv->name,
-    'is_relationship' => $is_relationship,
-    'db_name' => $db->name
-  );
-
-  $cvterm = tripal_insert_cvterm($term, array('update_existing' => TRUE));
-  if ($cvterm) {
-    drupal_set_message('Term added successfully.');
-  }
-  else {
-    drupal_set_message('Could not add term. Check Drupal recent logs for error messages.', 'error');
-  }
-}
-
-/**
- * Ajax callback for the tripal_cv_form
- *
- * @ingroup tripal_cv
- */
-function tripal_cv_cvterm_edit_form_ajax($form, $form_state) {
-
-  $elements = array();
-
-  $elements['name'] = $form['name'];
-  $elements['continue'] = $form['continue'];
-
-  // add back in the cv-edit-div that is used for the next round of AJAX
-  $elements['name']['#prefix'] =  '<div id="cvterm-edit-div">';
-  $elements['name']['#suffix'] =  '</div">';
-
-
-  return $elements;
-}

+ 0 - 110
legacy/tripal_example/README.txt

@@ -1,110 +0,0 @@
-This module is provided as a template for creating a custom Tripal Extension
-Module for Drupal 7 and Tripal 2.x.
-
-Drupal does provide quite a bit of documentation on its website at
-http://www.drupal.org but the easiest way to learn to program a Drupal module
-is to purchase the following book:
-
-  Tomlinson, VanDyk.  Pro Drupal Development. 2010. ISBN-13: 978-1430228387
-
-But this quick link can help get you started:
-
-  https://drupal.org/developing/modules/7
-
-Briefly, to create a Drupal module you must
-
-1) Create a directory to house all of your module's files
-2) Create a .info inside of the directory which provides information about your
-   module to Drupal
-3) Create a .module file which contains the functions used by your module
-4) Create a .install file which contains the functions used for installation,
-   enabling, disabling and uninstallation of your module.
-
-Examine the example functions and documentation in each of the files in this
-example module to learn how Tripal uses the Drupal API.
-
--------------------------
-DIRECTORY AND FILE NAMING
--------------------------
-When creating your Tripal Extension module, the following directory structure
-and file naming is suggested:
-
-For the required files:
-[module dir]/[module name].info
-[module dir]/[module name].module
-[module dir]/[module name].install
-
-If you want to include Drush commands for your module
-[module dir]/[module name].drush.inc
-
-If you want to integrate with Drupal Views 3.x:
-[module dir]/[module name].views.inc
-[module dir]/[module name].views_default.inc
-
-
-Include Files
--------------
-To limit the size of files, some functionality can be placed inside of
-"include" files. Include files are placed inside of an 'includes' directory.
-[module dir]/includes
-
-If your module creates a node type that uses data housed in Chado, you should
-place all of the Drupal hooks for nodes inside of an include named:
-[module dir]/includes/[module name].chado_node.inc
-
-If your module has an administrative interface, all of the functions related to
-administration should go in an include file named:
-[module dir]/includes/[module name].admin.inc
-
-All other include files should be named in the following way:
-[module dir]/includes/[module name].[function].inc
-
-where [function] is a brief description of the functionality provided by the
-include file. Please only use underscores inside of the [function] (no dashes
-or periods).
-
-
-Theme Files
--------------
-Tripal primarily uses template files for displaying content from Chado. This
-allows anyone to easily change the way data is displayed without needing to
-delve into the module's source code. A template typically provides data for
-a single data type (e.g. feature) or association (e.g. properties associated to
-features, or publications associated with featurmaps, etc.). These template
-files and any JavaScript, CSS or images needed to support them are all
-housed inside of a 'theme' directory with the following structure:
-[module dir]/theme
-[module dir]/theme/css       (for CSS files)
-[module dir]/theme/js        (for JS files)
-[module dir]/theme/images    (for images)
-[module dir]/theme/templates (for all Drupal template files)
-
-All Drupal hooks and functions related to theming of content should go in the
-file named:
-[module dir]/theme/[module name].theme.inc
-
-The functions in that file will typically be functions which directly
-generate content for a page or "preprocess" hooks that prepare variables that
-are passed to templates.
-
-Template files are named in the following way
-[module dir]/theme/templates/[module name]_[function].tpl.php.
-
-Notice that templates have an underscore separating the [module name] from the
-[function]. Typically a period is used (as with include files) but for
-backwards compatibility the underscores are kept.
-
-API Files
----------
-If your module will provide a set of functions that can be used as an
-Application Programming Interface (API), then those functions should be placed
-in files housed in the 'api' directory:
-[module dir]/api
-
-When creating API functions try to organize them into groups of related function
-and separate them into files by function with the following naming:
-[module dir]/api/[module name].[function].api.inc
-
-
-
-

+ 0 - 35
legacy/tripal_example/api/tripal_example.api.inc

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

+ 0 - 96
legacy/tripal_example/includes/tripal_example.admin.inc

@@ -1,96 +0,0 @@
-<?php
-/**
- * @file
- * This file contains the functions used for administration of the module
- *
- */
-
-function tripal_example_admin_examples_listing() {
-  $output = '';
-
-  // set the breadcrumb
-  $breadcrumb = array();
-  $breadcrumb[] = l('Home', '<front>');
-  $breadcrumb[] = l('Administration', 'admin');
-  $breadcrumb[] = l('Tripal', 'admin/tripal');
-  $breadcrumb[] = l('Chado', 'admin/tripal/legacy');
-  $breadcrumb[] = l('Examples', 'admin/tripal/legacy/tripal_example');
-  drupal_set_breadcrumb($breadcrumb);
-
-
-  // EXPLANATION:  Typically for all Tripal modules the home administrative page
-  // for the module contains a search form to help the adminstrator locate
-  // records. The following example code adds a default View to the page
-  /*
-  // Add the view
-  $view = views_embed_view('tripal_example_admin_examples','default');
-  if (isset($view)) {
-    $output .= $view;
-  }
-  else {
-    $output .= '<p>The Tripal Example Module uses primarily views to provide an '
-      . 'administrative interface. Currently one or more views needed for this '
-      . 'administrative interface are disabled. <strong>Click each of the following links to '
-      . 'enable the pertinent views</strong>:</p>';
-    $output .= '<ul>';
-      $output .= '<li>'.l('Example Admin', 'admin/tripal/legacy/tripal_example/views/examples/enable').'</li>';
-    $output .= '</ul>';
-  }
-  */
-  $output = 'Typically a search view goes here';
-
-  return $output;
-}
-
-/**
- * Administrative settings form
- *
- * @ingroup tripal_example
- */
-function tripal_example_admin() {
-  $form = array();
-
-  $form['nothing'] = array(
-    '#markup' => t('There are currently no settings to configure.')
-  );
-
-  // If your module is using the Chado Node: Title & Path API to allow custom
-  // titles for your node type then you need to add the configuration form for
-  // this functionality. To do so, we first have to preapre a $details array
-  // the describe our node type.  Then we call the function to create the form
-  // elements.
-  $details = array(
-      // the name of the MODULE implementing the content type
-    'module' => 'tripal_example',
-    'content_type' => 'chado_example',
-      // An array of options to use under "Page Titles"
-      // the key should be the token and the value should be the human-readable
-      // option
-    'options' => array(
-      '[example.name]' => 'Germplasm Name Only',
-      '[example.uniquename]' => 'Germplasm Unique Name Only',
-        // there should always be one options matching the unique constraint.
-        // If you have a more human-readable constraint, then that is
-        // preferable.
-        // See the tripal feature module for a good example of this.
-      '[example.example_id]' => 'Unique Constraint: The Chado ID for Examples'
-    ),
-    // the token indicating the unique constraint in the options array
-    'unique_option' => '[example.example_id]'
-  );
-  // This call adds the configuration form to your current form
-  // This sub-form handles it's own validation & submit
-  chado_add_admin_form_set_title($form, $form_state, $details);
-
-  return system_settings_form($form);
-}
-
-
-
-/**
- *
- * @ingroup tripal_example
- */
-function tripal_example_admin_validate($form, &$form_state) {
-
-}

+ 0 - 880
legacy/tripal_example/includes/tripal_example.chado_node.inc

@@ -1,880 +0,0 @@
-<?php
-
-/**
- * @file
- * This file should contain all Drupal hooks for interacting with nodes.
- *
- */
-
-/**
- *  Implementation of hook_node_info().
- *
- *  This hook provides information to Drupal about any node types that are being
- *  created by this module. If your module does not create any node types then
- *  this function is not required.
- *
- * @ingroup tripal_example
- */
-function tripal_example_node_info() {
-  $nodes = array();
-
-  // EXPLANATION: this array describes all of the node types that are created
-  // by this module. For many Tripal modules (e.g. tripal_example, tripal_stock,
-  // tripal_library, tripal_pub, etc.) new node types are created. It is
-  // customary to name all new node types that interact with data in Chado
-  // with a 'chado_' prefix.
-
-  $nodes['chado_example'] = array(
-    'name'        => t('Example'),
-    'base'        => 'chado_example',
-    'description' => t('A record from the fake chado example table'),
-    'has_title'   => TRUE,
-    'locked'      => TRUE,
-    // EXPLANATION: This section of the node type array specifies how Tripal
-    // will sync the node types with data in Chado. When Drupal creates a node
-    // it has no way of coordinating which node belongs to which record in
-    // Chado. Therefore, Tripal maintains tables in the Drupal schema that maps
-    // Drupal nodes to records in Chado. Syncing is the process of creating
-    // Drupal nodes and linking them to the appropriate record.
-    'chado_node_api' => array(
-      // the base table name (e.g. example, example, contact)
-      'base_table' => 'example',
-      // the node type hook prefix
-      'hook_prefix' => 'chado_example',
-      'record_type_title' => array(
-        // how to refer to the record
-        'singular' => t('Example'),
-        // how to refer to the record in plurals
-        'plural' => t('Examples')
-      ),
-      'sync_filters' => array(
-        'type_id' => TRUE,     // if the record has a type_id set to TRUE
-        'organism_id' => TRUE  // if the record has an organism_id set to TRUE
-      ),
-    )
-  );
-
-  return $nodes;
-}
-
-/**
- * Implement hook_access(). This hook provides instructions to Drupal for which
- * users can access the custom content types created in the function above. The
- * available permissions are set in the chado_example_permissions() hook in the
- * tripal_example.module file. This hook is not needed if no node types were
- * defined in the hook_node_info() hook.
- *
- * @return
- * This function should return null if it does not specifically deny access.
- * This allows for other mechanisms to to deny or reject access. If the return
- * value is TRUE then access is granted regardless of any other rules that might
- * be implemented by other modules.
- */
-function tripal_example_node_access($node, $op, $account) {
-  $node_type = $node;
-  if (is_object($node)) {
-    $node_type = $node->type;
-  }
-  // EXPLANATION:  in the tripal_example_permissions() function we created the
-  // permission types that are used here to check for access permissions to the
-  // 'chado_exmaple' node type.
-  if($node_type == 'chado_example') {
-    if ($op == 'create') {
-      if (!user_access('create chado_example content', $account)) {
-        return NODE_ACCESS_DENY;
-      }
-      return NODE_ACCESS_ALLOW;
-    }
-    if ($op == 'update') {
-      if (!user_access('edit chado_example content', $account)) {
-        return NODE_ACCESS_DENY;
-      }
-    }
-    if ($op == 'delete') {
-      if (!user_access('delete chado_example content', $account)) {
-        return NODE_ACCESS_DENY;
-      }
-    }
-    if ($op == 'view') {
-      if (!user_access('access chado_example content', $account)) {
-        return NODE_ACCESS_DENY;
-      }
-    }
-  }
-  return NODE_ACCESS_IGNORE;
-}
-
-/**
- * Implementation of hook_form()
- *
- * Creates the form for editing or inserting a record
- *
- * @ingroup tripal_example
- */
-function chado_example_form($node, &$form_state) {
-
-  // EXPLANATION: This function should construct a form array that is used by
-  // Drupal to construct a form for inserting or editing our new node type.
-  // See this page for information about the Form API:
-  // https://api.drupal.org/api/drupal/includes!form.inc/group/form_api/7
-  //
-  // The code below is laid out in the following order
-  // 1) Set default values
-  // 2) Add form elements used by this node type
-  // 3) Use the Tripal API to add form elements for properties,
-  //    dbxref's and relationships
-  //
-  // For the example code below we assume that the fake 'example' table only has
-  // a uniquename, organism_id, type_id and example_id.
-
-  $form = array();
-
-  // Default values can come in the following ways:
-  //
-  // 1) as elements of the $node object. This occurs when editing an existing
-  //    example
-  // 2) in the $form_state['values'] array which occurs on a failed validation
-  //    or ajax callbacks from non submit form elements
-  // 3) in the $form_state['input'[ array which occurs on ajax callbacks from
-  //    submit form elements and the form is being rebuilt
-  //
-  // set form field defaults
-
-
-  // SET FORM DEFAULTS
-  //---------------------------------------------
-  $example      = null; // holds the example object record
-  $example_id   = null; // when editing an example record we'll have an example_id
-
-  // initialize the defaults for the form fields
-  $uniquename   = '';
-  $example_type = '';
-  $organism_id  = '';
-  $description  = '';
-
-  // if we are editing an existing node then the 'example' record from Chado
-  // is already part of the node, so we set the defaults from that object
-  if (property_exists($node, 'example')) {
-    $example = $node->example;
-    $example_id   = $example->example_id;
-    $uniquename   = $example->uniquename;
-    $description  = $example->description;
-    $organism_id  = $example->organism_id;
-
-    // keep track of the example id
-    $form['example_id'] = array(
-      '#type' => 'value',
-      '#value' => $example_id,
-    );
-  }
-  // if we are re constructing the form from a failed validation or ajax
-  // callback then use the $form_state['values'] values
-  if (array_key_exists('values', $form_state)) {
-     $uniquename   = $form_state['values']['uniquename'];
-     $example_type = $form_state['values']['example_type'];
-     $description  = $form_state['values']['description'];
-     $organism_id  = $form_state['values']['organism_id'];
-  }
-  // if we are re building the form from after submission (from ajax call) then
-  // the values are in the $form_state['input'] array
-  if (array_key_exists('input', $form_state) and !empty($form_state['input'])) {
-     $uniquename   = $form_state['input']['uniquename'];
-     $example_type = $form_state['input']['example_type'];
-     $organism_id  = $form_state['input']['organism_id'];
-  }
-
-
-  // FORM ELEMENTS
-  //---------------------------------------------
-  $form['uniquename'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Unique Name'),
-    '#required' => TRUE,
-    '#default_value' => $uniquename,
-    '#description' => t('Enter a unique name for this example. This name must be unique.'),
-    '#maxlength' => 255
-  );
-
-  // for the type_id we want to use the default vocabulary so that this field
-  // can have auto-complete functionality
-  $type_cv = tripal_get_default_cv('example', 'type_id');
-  $cv_id = $type_cv->cv_id;
-  $form['example_type'] = array(
-    '#title'       => t('Example Type'),
-    '#type'        => 'textfield',
-    '#description' => t("Choose the example type (e.g. Test Type)."),
-    '#required'    => TRUE,
-    '#default_value' => $example_type,
-    '#autocomplete_path' => "admin/tripal/vocab/cvterm/auto_name/$cv_id",
-  );
-
-  // add a select box of organisms
-  $organisms = tripal_get_organism_select_options();
-  $form['organism_id'] = array(
-    '#title'       => t('Organism'),
-    '#type'        => t('select'),
-    '#description' => t("Choose the organism with which this example is associated"),
-    '#required'    => TRUE,
-    '#default_value' => $organism_id,
-    '#options'     => $organisms,
-  );
-
-  $form['description'] = array(
-    '#type' => 'text_format',
-    '#title' => t('Description'),
-    '#required' => TRUE,
-    '#default_value' => $description,
-    '#description' => t('Enter a description for this example.'),
-  );
-
-  // PROPERTIES FORM
-  //---------------------------------------------
-  // If there is a exampleprop table and you want to allow users to add/remove
-  // entries from it through your node form then add this section to your own
-  // node form
-  $prop_cv = tripal_get_default_cv('exampleprop', 'type_id');
-  $cv_id = $prop_cv ? $prop_cv->cv_id : NULL;
-  $details = array(
-    // the name of the prop table
-    'property_table' => 'exampleprop',
-    // the value of example_id for this record
-    'chado_id' => $example_id,
-    // the cv.cv_id of the cv governing exampleprop.type_id
-    'cv_id' => $cv_id
-  );
-  // Adds the form elements to your current form
-  chado_add_node_form_properties($form, $form_state, $details);
-
-  // ADDITIONAL DBXREFS FORM
-  //---------------------------------------------
-  // If there is a example_dbxref table and you want to allow users to
-  // add/remove entries from it through your node form then add this section to
-  // your own node form
-  $details = array(
-    // the name of the _dbxref table
-    'linking_table' => 'example_dbxref',
-    // the name of the key in your base chado table
-    'base_foreign_key' => 'example_id',
-    // the value of example_id for this record
-    'base_key_value' => $example_id
-  );
-  // Adds the form elements to your current form
-  chado_add_node_form_dbxrefs($form, $form_state, $details);
-
-  // RELATIONSHIPS FORM
-  //---------------------------------------------
-  // If there is a example_relationship table and you want to allow users to
-  // add/remove entries from it through your node form then add this section to
-  // your own node form
-  $rels_cv = tripal_get_default_cv('example_relationship', 'type_id');
-  $cv_id = $rels_cv ? $rels_cv->cv_id : NULL;
-  $details = array(
-    // the name of the _relationship table
-    'relationship_table' => 'example_relationship',
-    // the name of your chado base table
-    'base_table' => 'example',
-    // the name of the key in your base chado table
-    'base_foreign_key' => 'example_id',
-    // the value of example_id for this record
-    'base_key_value' => $example_id,
-    // the human-readable name of your node type
-    'nodetype' => 'example',
-    // the cv.cv_id of the cv governing example_relationship.type_id
-    'cv_id' => $cv_id
-  );
-  // Adds the form elements to your current form
-  chado_add_node_form_relationships($form, $form_state, $details);
-
-  // return the form
-  return $form;
-}
-
-/**
- * Implementation of hook_validate
- *
- * This function validates a form prior to insert or update. If an error is
- * detected, it sets the error using form_set_error() which takes the user back
- * to the form to make corrections.
- *
- * This validation is being used for three activities:
- *   CASE A: Update a node that exists in both Drupal and Chado
- *   CASE B: Synchronizing a node from Chado to Drupal
- *   CASE C: Inserting a new node that exists in neither Drupal nor Chado
- *
- * @param $node
- *
- *
- * @ingroup tripal_example
- */
-function chado_example_validate($node, $form, &$form_state) {
-
-  // We only want to validate when the node is saved.
-  // Since this validate can be called on AJAX and Deletion of the node
-  // we need to make this check to ensure queries are not executed
-  // without the proper values.
-  if(property_exists($node, "op") and $node->op != 'Save') {
-    return;
-  }
-
-  // we are syncing if we do not have a node ID but we do have a example_id. We
-  // don't need to validate during syncing so just skip it.
-  if (!property_exists($node, 'nid') and property_exists($node, 'example_id') and $node->example_id != 0) {
-    return;
-  }
-
-  // be sure to always trim text fields
-  $node->uniquename   = property_exists($node, 'uniquename') ? trim($node->uniquename) : '';
-
-  // Validating for an update. If the 'nid' property is present in the node then
-  // this is an update and validation can be different for updates
-  if (property_exists($node, 'nid')) {
-
-    // make sure the example type is an allowed term
-    $type_cv = tripal_get_default_cv('example', 'type_id');
-    $type = tripal_get_cvterm(array(
-      'name' => $node->example_type,
-      'cv_id' => $type_cv->cv_id,
-    ));
-    if (!$type) {
-      form_set_error('example_type', t("The example type is not a valid name from the Sequence Ontology."));
-    }
-
-    // TODO: also we should check that the unique constraint is not invalidated
-    // by changing either the type_id, organism_id or uniquename.
-  }
-  // Validating for an insert
-  else {
-    // make sure the example type is an allowed term
-    $type_cv = tripal_get_default_cv('example', 'type_id');
-    $type = tripal_get_cvterm(array(
-      'name' => $node->example_type,
-      'cv_id' => $type_cv->cv_id,
-    ));
-    if (!$type) {
-      form_set_error('example_type', t("The example type is not a valid name from the Sequence Ontology."));
-    }
-
-    // TODO: also we should check that the unique constraint doesn't already exist
-  }
-}
-
-/**
- *  Implementation of hook_insert(). This function is called after the node is
- * inserted into the database. We need it so that we can insert appropriate
- * fields as provided by the user into the database. And so that we can link the
- * new Drupal node to the data in Chado via the chado_example linking table. We
- * can get to this function also during "syncing".
- * With syncing, however, the data already exists in Chado and we do not want
- * to try to re-add it. But we do need to add an entry to the chado_example
- * table to link the Drupal node with the data in the 'example' table of Chado.
- *
- *  This function is not required if the hook_node_info() does not define
- *  any custom node types.
- *
- * @ingroup tripal_example
- */
-function chado_example_insert($node) {
-
-  $example_id = '';
-
-  // if there is an example_id in the $node object then this must be a sync so
-  // we can skip adding the example as it is already there, although we do need
-  // to proceed with insertion into the chado/drupal linking table.
-  if (!property_exists($node, 'example_id')) {
-
-    // be sure to always trim text fields
-    $node->uniquename   = trim($node->uniquename);
-    $node->description  = trim($node->description['value']);
-
-    // get the example type record
-    $type_cv = tripal_get_default_cv('example', 'type_id');
-    $type = tripal_get_cvterm(array(
-        'name' => $node->example_type,
-        'cv_id' => $type_cv->cv_id,
-    ));
-
-    // perform the insert using the chado_insert_record function();
-    $values = array(
-      'uniquename' => $node->uniquename,
-      'description' => $node->description,
-      'type_id' => $type->cvterm_id,
-      'organism_id' => $node->organism_id,
-    );
-    $example = chado_insert_record('example', $values);
-    if (!$example) {
-      drupal_set_message(t('Unable to add example.'), 'warning');
-      tripal_report_error('tripal_example', TRIPAL_WARNING, 'Insert example: Unable to create example where values: %values',
-        array('%values' => print_r($values, TRUE)));
-      return;
-    }
-
-    // get the example_id for linking Drupal node with Chado data
-    $example_id = $example['example_id'];
-
-    // Only add to other Chado tables if the base record was inserted properly
-    if ($example_id > 0) {
-
-      // If you implemented the properties form in chado_example_form then you
-      // need to handle inserting these properties into your Chado prop table.
-      $details = array(
-        // the name of the prop table
-        'property_table'   => 'exampleprop',
-        // the name of your Chado base table
-        'base_table'       => 'example',
-        // the name of the key in your base table
-        'foreignkey_name'  => 'example_id',
-        // the value of the example_id key
-        'foreignkey_value' => $example_id
-      );
-      chado_update_node_form_properties($node, $details);
-
-      // If you implemented the dbxrefs form in chado_example_form then you need
-      // to handle inserting these database references into your Chado _dbxref
-      // table.
-      $details = array(
-        // the name of your _dbxref table
-        'linking_table'    => 'example_dbxref',
-        // the name of the key in your base table
-        'foreignkey_name'  => 'example_id',
-        // the value of the example_id key
-        'foreignkey_value' => $example_id
-      );
-      chado_update_node_form_dbxrefs($node, $details);
-
-      // If you implemented the relationships form in chado_example_form then
-      // you need to handle inserting these relationships into your Chado
-      // _relationship table.
-      $details = array(
-        // name of the _relationship table
-        'relationship_table' => 'example_relationship',
-        // value of the example_id key
-        'foreignkey_value' => $example_id
-      );
-      chado_update_node_form_relationships($node, $details);
-    }
-  }
-  else {
-    // the node has an example_id so get it for linking Drupal node with Chado
-    // data
-    $example_id = $node->example_id;
-  }
-
-  // Make sure the entry for this example doesn't already exist in the
-  // chado_example table if it doesn't exist then we want to add it.
-   $check_org_id = chado_get_id_from_nid('example', $node->nid);
-  if (!$check_org_id) {
-    $record = new stdClass();
-    $record->nid = $node->nid;
-    $record->vid = $node->vid;
-    $record->example_id = $example_id;
-    drupal_write_record('chado_example', $record);
-  }
-}
-
-/**
- * Implementation of hook_update(). This function runs after the node has been
- * inserted into the Drupal schema and allows us to update the record in Chado.
- *
- * This function is not required if the hook_node_info() does not define any
- * custom node types.
- *
- * @ingroup tripal_example
- */
-function chado_example_update($node) {
-  // be sure to always trim text fields
-  $node->uniquename   = trim($node->uniquename);
-  $node->description  = trim($node->description['value']);
-
-  // use the chado_update_record() function to update the record
-  $match = array(
-    'example_id' => $example_id,
-  );
-  $values = array(
-    'uniquename' => $node->uniquename,
-  );
-  $options = array('return_record' => TRUE);
-  $status = chado_update_record('example', $match, $values, $options);
-
-  if (!$status) {
-    drupal_set_message(t('Unable to update example.'), 'warning');
-    tripal_report_error('tripal_example', TRIPAL_WARNING, 'Update example: Unable to update example where values: %values',
-      array('%values' => print_r($values, TRUE)));
-  }
-
-  // If you implemented the properties form in chado_example_form then you need
-  // to handle updating these properties into your Chado prop table.
-  $details = array(
-    'property_table' => 'exampleprop', // the name of the prop table
-    'base_table' => 'example',         // the name of your Chado base table
-    'foreignkey_name' => 'example_id', // the name of the key in your base table
-    'foreignkey_value' => $example_id  // the value of the example_id key
-  );
-  chado_update_node_form_properties($node, $details);
-
-  // If you implemented the dbxrefs form in chado_example_form then you need to
-  // handle updating these database references into your Chado _dbxref table.
-  $details = array(
-    'linking_table' => 'example_dbxref', // the name of your _dbxref table
-    'foreignkey_name' => 'example_id',   // the name of the key in your base table
-    'foreignkey_value' => $example_id    // the value of the example_id key
-  );
-  chado_update_node_form_dbxrefs($node, $details);
-
-  // If you implemented the relationships form in chado_example_form then you
-  // need to handle updating these relationships into your Chado _relationship
-  // table.
-  $details = array(
-    // name of the _relationship table
-    'relationship_table' => 'example_relationship',
-    // value of the example_id key
-    'foreignkey_value' => $example_id
-  );
-  chado_update_node_form_relationships($node, $details);
-
-}
-/**
- * Implementation of hook_delete(). This function runs after the node has been
- * deleted from the Drupal schema and allows us to delete the corresponding
- * record in Chado.
- *
- * This function is not required if the hook_node_info() does not define any
- * custom node types.
- *
- * @ingroup tripal_example
- */
-function chado_example_delete($node) {
-
-  // get the example id from the node
-  $example_id  = chado_get_id_from_nid('example', $node->nid);
-
-  // if we don't have a example id for this node then this isn't a node of type
-  // chado_example or the entry in the chado_example table was lost.
-  if (!$example_id) {
-    return;
-  }
-
-  // remove the entry in the chado_exapmle table linking the deleted
-  // Drupal node with the data in Chado
-  $sql_del = "DELETE FROM {chado_example} WHERE nid = :nid AND vid = :vid";
-  db_query($sql_del, array(':nid' => $node->nid, ':vid' => $node->vid));
-
-  // Remove data from example tables of Chado database. This will
-  // cause a cascade delete and remove all data in referencing tables
-  // for this example
-  chado_query("DELETE FROM {example} WHERE example_id = :example_id", array(':example_id' => $example_id));
-
-  // inform the user that the data was deleted
-  drupal_set_message(t("The example and all associated data were removed from Chado"));
-
-}
-
-/**
- * Implementation of hook_load(). This function is necessary to load into the
- * $node object the fields of the table form Chado. For example for the example
- * table, the chado_example_load() function adds in a example object which
- * contains all of the fields and sub objects for data in tables with foreign
- * key relationships.
- *
- * This function is not required if the hook_node_info() does not define any
- * custom node types.
- *
- * @ingroup tripal_example
- */
-function chado_example_load($nodes) {
-
-  // EXPLANATION: when displaying or node or accessing the node in a template
-  // we need the data from Chado. This function finds the record in Chado that
-  // this node belongs to and adds the record.
-
-  // there may be multiple nodes that get passed in so we have to iterate
-  // through them all
-  foreach ($nodes as $nid => $node) {
-    // find the example and add in the details
-    $example_id = chado_get_id_from_nid('example', $nid);
-
-    // if the nid does not have a matching record then skip this node.
-    // this can happen with orphaned nodes.
-    if (!$example_id) {
-      continue;
-    }
-
-    // build the example variable by using the chado_generate_var() function
-    $values = array('example_id' => $example_id);
-    $example = chado_generate_var('example', $values);
-
-    // for fields in the table that are of type 'text' you may want to include
-    // those by default, the chado_generate_var does not include text fields as
-    // they may be very large and including a large text field can slow the page
-    // load.
-    // If you know a text field will never be large and it is important for the
-    // other functions that will see the node to have access to a field you can
-    // include it here using the chado_expand_var() function. In most
-    // cases it is probably best to let the end-user decide if text fields
-    // should be included by using this function in the templates.
-    $example = chado_expand_var($example, 'field', 'example.description');
-
-    // add the new example object to this node.
-    $nodes[$nid]->example = $example;
-
-    // If your module is using the Chado Node: Title & Path API to allow custom
-    // titles for your node type. Every time you want the title of the node, you
-    // need to use the following API function:
-    $node->title = chado_get_node_title($node);
-
-  }
-}
-
-/**
- * Implementation of hook_node_presave().
- *
- * Performs actions on a node object prior to it being saved
- *
- * @ingroup tripal_example
- */
-function tripal_example_node_presave($node) {
-
-  // EXPLANATION: This node is useful for making changes to the node prior to it
-  // being saved to the database.
-  // One useful case for this is to set the title of a node using values
-  // supplied by the user.
-  //
-  // This function is not required. You probably won't need it if you don't
-  // define a custom node type in the hook_node_info() function. But it is node
-  // type agnostic, so you can use this function to change the contents of any
-  // node regardless of it's type.
-
-  // set the node title
-  switch ($node->type) {
-    // This step is for setting the title for the Drupal node. This title is
-    // permanent and thus is created to be unique. Title changes provided by
-    // tokens are generated on the fly dynamically, but the node title seen in
-    // the content listing needs to be set here. Do not call the
-    // chado_get_node_title() function here to set the title as the node object
-    // isn't properly filled out and the function will fail.
-    case 'chado_example':
-      // for a form submission the 'uniquename' field will be set,
-      // for a sync, we must pull from the example object
-      if (property_exists($node, 'uniquename')) {
-        // set the title
-        $node->title = $node->uniquename;
-      }
-      else if (property_exists($node, 'example')) {
-        $node->title = $node->example->uniquename;
-      }
-      break;
-  }
-}
-
-/**
- * Implementation of hook node_insert().
- *
- * Performs actions after any node has been inserted.
- *
- * @ingroup tripal_example
- */
-function tripal_example_node_insert($node) {
-
-  // EXPLANATION: This function is used after any a node is inserted into the
-  // database. It is different from the hook_insert() function above in that it
-  // is called after any node is saved, regardless of it's type. This function
-  // is useful for making changes to the database after a node is inserted.
-  // An example comes from the tripal_feature module where the URL alias of a
-  // node cannot be set in the hook_insert() function. Therefore the
-  // tripal_feature module uses this function to set the URL path of a newly
-  // inserted example node.
-  //
-  // This function is not required. You probably won't need it if you don't
-  // define a custom node type in the hook_node_info() function. But it is node
-  // type agnostic, so you can use this function to do any activity after insert
-  // of any node.
-
-  // the Example code below will set the URL path after inserting. We do it here
-  // because we do not know the example_id in the pre-save and cannot do it in
-  // the hook_insert()
-  switch ($node->type) {
-    case 'chado_example':
-
-      // find the example and add in the details
-      $example_id = chado_get_id_from_nid('example', $nid);
-
-      // build the example variable by using the chado_generate_var() function
-      $values = array('example_id' => $example_id);
-      $example = chado_generate_var('example', $values);
-      $node->example = $example;
-
-
-      // EXPLANATION: You can allow the site admin to customize the
-      // title and URL of your node.  The 'Chado Node: Title & Path API'
-      // contains two functions that can be called to generate the title and
-      // URL based a schema provided by the site admin. These functions are
-      // named chado_get_node_title() and chado_set_node_url().  These
-      // functions use a string of tokens to build the URL and titles and the
-      // site admin has the ability to set these tokens.  There are
-      // form elements made available in the tripal_example_admin() function
-      // that allow the admin to set these tokens.  The default token string
-      // is provided to Tripal using two hook functions, and are found below.
-      // These are: chado_exmaple_chado_node_default_title() and
-      // chado_example_chdo_node_default_url().
-
-      // Set the Title and URL for this node.
-      $example->title = chado_get_node_title($node);
-      chado_set_node_url($node);
-      break;
-  }
-}
-
-/**
- * Implementation of hook node_update().
- *
- * Performs actions after any node has been updated.
- *
- */
-function tripal_example_node_update($node) {
-
-  // EXPLANATION: This function is used after any a node is updated in the
-  // database. It is different from the hook_update() function above in that it
-  // is called after any node is updated, regardless of it's type.
-  // An example comes from the tripal_feature module where the URL alias of a
-  // node cannot be set in the hook_update() function. Therefore the
-  // tripal_feature module uses this function to reset the URL path of an
-  // updated feature node.
-  //
-  // This function is not required. You probably won't need it if you don't
-  // define a custom node type in the hook_node_info() function. But it is node
-  // type agnostic, so you can use this function to do any activity after insert
-  // of a node.
-
-  // add items to other nodes, build index and search results
-  switch ($node->type) {
-    case 'chado_example':
-
-      // If your module is using the Chado Node: Title & Path API to allow
-      // custom titles for your node type. Every time you want the title of the
-      // node, you need to use the following API function:
-      $example->title = chado_get_node_title($node);
-
-      // set the URL for this example page
-      // see the code in the tripal_feature/includes/tripal_feature.chado_node.inc
-      // file in the function tripal_feature_node_insert for an example of how
-      // that module sets the URL. It uses a configuration file to allow the
-      // user to dynamically build a URL schema and then uses that schema to
-      // generate a URL string.
-      break;
-  }
-}
-/**
- * Implementation of hook_node_view().
- *
- * @ingroup tripal_example
- */
-function tripal_example_node_view($node, $view_mode, $langcode) {
-
-  // EXPLANATION: This function defines the content "blocks" that appear when
-  // the node is displayed. It is node type agnostic so we can add content to
-  // any node type. So, we use this function to add the content from all of our
-  // theme templates onto our new node type. We will also use this function to
-  // add content to other node types.
-
-  switch ($node->type) {
-    case 'chado_example':
-      // there are different ways a node can be viewed. Primarily Tripal
-      // supports full page view and teaser view.
-      if ($view_mode == 'full') {
-
-        // If you want to use the default Tripal node template then you need to
-        // tell Tripal to generate the Table of Contents. This is done by
-        // setting the following to TRUE. If your content type follows the
-        // chado_<base table> convention then this is the default. In this case
-        // if you don't want to use the default template then you need to set
-        // the following to FALSE.
-        $node->content['#tripal_generic_node_template'] = TRUE;
-
-        // There is always a base template. This is the template that is first
-        // shown when the example node type is first displayed.
-        // If you are using the default Tripal node template, then you should
-        // also set two additional items in each array:  tripal_toc_id and
-        // tripal_toc_title. The tripal_tock_id should be a single unique
-        // world that is used to reference the template. This ID is used for
-        // constructing URLs for the content. The tripal_toc_title contains
-        // the title that should appear in the table of contents for this
-        // content. You should only set the '#weight' element for the base
-        // template (or Overview) to ensure that it appears at the top of the
-        // list. Otherwise items are sorted alphabetically.
-        $node->content['tripal_example_base'] = array(
-          '#theme' => 'tripal_example_base',
-          '#node' => $node,
-          '#tripal_toc_id'    => 'base',
-          '#tripal_toc_title' => 'Overview',
-          '#weight' => -100,
-        );
-        // we can add other templates as well for properties, publications,
-        // dbxrefs, etc...
-        $node->content['tripal_example_properties'] = array(
-          '#theme' => 'tripal_example_properties',
-          '#node' => $node,
-          '#tripal_toc_id'    => 'properties',
-          '#tripal_toc_title' => 'Properties',
-        );
-        $node->content['tripal_example_references'] = array(
-          '#theme' => 'tripal_example_references',
-          '#node' => $node,
-          '#tripal_toc_id'    => 'references',
-          '#tripal_toc_title' => 'Cross References',
-        );
-        $node->content['tripal_example_relationships'] = array(
-          '#theme' => 'tripal_example_relationships',
-          '#node' => $node,
-          '#tripal_toc_id'    => 'relationships',
-          '#tripal_toc_title' => 'Relationships',
-        );
-
-        // Note: if you create a template that you do not want a user to know
-        // where it is (discourage editing of it), you can add the following
-        // key:  '#tripal_template_show' => FALSE. If this key/value is set the
-        // administrator message that Tripal provides indicating where the
-        // template is housed will not be shown.
-      }
-      // set the content for the teaser view
-      if ($view_mode == 'teaser') {
-        // The teaser is also a required template
-        $node->content['tripal_example_teaser'] = array(
-          '#theme' => 'tripal_example_teaser',
-          '#node' => $node,
-        );
-      }
-      break;
-    // you can add custom content to any node type by adding content to the node
-    // in the same way as above.
-    case 'chado_organism':
-      if ($view_mode == 'full') {
-        $node->content['tripal_organism_examples'] = array(
-          '#theme' => 'tripal_organism_examples',
-          '#node' => $node,
-          '#tripal_toc_id'    => 'examples',
-          '#tripal_toc_title' => 'Examples',
-        );
-      }
-      break;
-    // ... etc
-  }
-}
-
-
-/**
- * Implements [content_type]_chado_node_default_title_format().
- *
- * Defines a default title format for the Chado Node API to set the titles on
- * Chado example nodes based on chado fields.
- */
-function chado_example_chado_node_default_title_format() {
-  return '[example.name], [example.uniquename] ([example.type_id>cvterm.name]) [example.organism_id>organism.genus] [example.organism_id>organism.species]';
-}
-
-/**
- * Implements hook_chado_node_default_url_format().
- *
- * Designates a default URL format for example nodes.
- */
-function chado_example_chado_node_default_url_format() {
-  return '/example/[example.organism_id>organism.genus]/[example.organism_id>organism.species]/[example.type_id>cvterm.name]/[example.uniquename]';
-}

+ 0 - 0
legacy/tripal_example/theme/css/tripal_example.css


+ 0 - 9
legacy/tripal_example/theme/js/tripal_example.js

@@ -1,9 +0,0 @@
-(function($) {
-  Drupal.behaviors.tripal_exampleBehavior = {
-    attach: function (context, settings){
-
-      // Place JavaScript code here
-
-    }
-  };
-})(jQuery);

+ 0 - 85
legacy/tripal_example/theme/templates/tripal_example_base.tpl.php

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

+ 0 - 8
legacy/tripal_example/theme/templates/tripal_example_help.tpl.php

@@ -1,8 +0,0 @@
-<h3>Module Description:</h3>
-<p>Place details about this module here.</p>
-
-<h3>Setup Instructions:</h3>
-<p>Instructions for setup of this module go here.</p>
-
-<h3>Features of this Module:</h3>
-<p>A description of this module's features go here.</p>

+ 0 - 70
legacy/tripal_example/theme/templates/tripal_example_properties.tpl.php

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

+ 0 - 70
legacy/tripal_example/theme/templates/tripal_example_references.tpl.php

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

+ 0 - 151
legacy/tripal_example/theme/templates/tripal_example_relationships.tpl.php

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

+ 0 - 14
legacy/tripal_example/theme/templates/tripal_example_teaser.tpl.php

@@ -1,14 +0,0 @@
-<?php
-$example  = $variables['node']->example; ?>
-
-<div class="tripal_example-teaser tripal-teaser"> 
-  <div class="tripal-example-teaser-title tripal-teaser-title"><?php 
-    print l("<i>$example->uniquename", "node/$node->nid", array('html' => TRUE));?>
-  </div>
-  <div class="tripal-example-teaser-text tripal-teaser-text"> <?php
-    print substr($example->description, 0, 650);
-    if (strlen($example->description) > 650) {
-      print "... " . l("[more]", "node/$node->nid");
-    } ?>
-  </div>
-</div>

+ 0 - 113
legacy/tripal_example/theme/tripal_example.theme.inc

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

+ 0 - 50
legacy/tripal_example/tripal_example.info

@@ -1,50 +0,0 @@
-;
-; Provide details about your module in this file. Instruction for setup of this
-; file can be found here: https://drupal.org/node/542202
-;
-name = Tripal Example
-description = An example module that can be used as a template for anyone wanting to create a custom extension module for Tripal.
-
-;
-; The version of Drupal with which this module is compatible.
-;
-core = 7.x
-
-;
-; The computer-readable name for this module
-;
-project = tripal_example
-
-;
-; In order for this module to appear in the 'Tripal Extensions' section when
-; viewing the module administrative page, the package must be set to
-; 'Tripal Extensions'
-;
-package = Tripal v2 Legacy Extensions
-
-;
-; Follow these instructions when specifying the version:
-; https://drupal.org/node/1015226
-;
-version = 7.x-3.0-beta3
-
-;
-; Style-sheets containing CSS that should always be available for the
-; module should be specified here.
-;
-stylesheets[all][] = theme/css/tripal_example.css
-
-;
-; Javascript files that should always be available for the
-; module should be specified here.
-;
-scripts[]          = theme/js/tripal_example.js
-
-;
-; Add additional dependencies for other modules using the module project name.
-; These modules must be enabled before this module can be enabled
-;
-dependencies[] = tripal_core
-dependencies[] = tripal_chado_views
-dependencies[] = tripal_db
-dependencies[] = tripal_cv

+ 0 - 608
legacy/tripal_example/tripal_example.install

@@ -1,608 +0,0 @@
-<?php
-/**
- * @file
- * Installation of the example module
- */
-
-/**
- * Implements hook_disable().
- *
- * Perform actions when the module is disabled by the site administrator
- *
- * @ingroup tripal_example
- */
-function tripal_example_disable() {
-
-  // EXPLANATION: If you are using Drupal Views you want to ensure that any
-  // default views that your module provides are disabled when the module is
-  // disabled. Default views are specified in the
-  // [module name].views.default.inc file. The following code will disable these
-  // views. If your module does not create any default views you can remove the
-  // following code.
-
-  // Disable all default views provided by this module
-  require_once("tripal_example.views_default.inc");
-  $views = tripal_example_views_default_views();
-  foreach (array_keys($views) as $view_name) {
-    tripal_disable_view($view_name,FALSE,array('suppress_error' => TRUE));
-  }
-
-}
-
-/**
- * Implements hook_requirements().
- *
- * Performs check to see if all required dependencies are met. Drupal will
- * automatically check for module dependencies but here you can check for other
- * requirements.
- *
- * @ingroup tripal_example
- */
-function tripal_example_requirements($phase) {
-
-
-  $requirements = array();
-  if ($phase == 'install') {
-    // EXPLANATION: It is essential that Chado be installed for almost all
-    // Tripal modules. Therefore, the following code checks to ensure Chado is
-    // installed and available. If your module does not require that Chado be
-    // installed, you can remove the following check.
-
-    // make sure chado is installed
-    if (!$GLOBALS["chado_is_installed"]) {
-      $requirements ['tripal_example'] = array(
-          'title' => "tripal_example",
-          'value' => "ERROR: Chado must be installed before this module can be enabled",
-          'severity' => REQUIREMENT_ERROR,
-      );
-    }
-  }
-  return $requirements;
-}
-
-/**
- * Implements hook_install().
- *
- * Performs actions when the modules is first installed.
- *
- * @ingroup tripal_example
- */
-function tripal_example_install() {
-
-  // EXPLANATION: Here is a good place to add any materialized views, controlled
-  // vocabularies CV, databases or CV terms needed by your module.
-  // To keep this module code short, create functions to do each of those tasks
-
-  // add any materialized view
-  tripal_example_add_mviews();
-
-  // add any external databases used by the example module.
-  tripal_example_add_dbs();
-
-  // add any controlled vocabularies used by the example module. You may need
-  // to add a vocabulary if you to set it as default (see next lines of code).
-  // For example, the Sequence Ontology (SO) is used by the feature module as
-  // the default vocabulary for the feature type_id field. But, that vocabulary
-  // does not yet exist in Chado until after the SO is loaded using the Tripal
-  // OBO loader. But, we can add it here as a place-holder so that we can then
-  // set it as a default vocabulary (see below).
-  tripal_example_add_cvs();
-
-
-  // add any controlled vocabulary terms
-  tripal_example_add_cvterms();
-
-  // EXPLANATION: Many tables in Chado have a 'type_id' column which allows for
-  // association of controlled vocabularies to describe the record. Chado places
-  // no restrictions on which vocabularies can be used, but Tripal can be
-  // instructed to provide a default vocabulary for any given field. For
-  // example, the feature.type_id column will typically use the Sequence
-  // Ontology. In that case, we can use the tripal_set_default_cv() function to
-  // specify the Sequence Ontology (sequence) as the default vocabulary.
-  tripal_set_default_cv('example', 'type_id', 'example_type');
-  tripal_set_default_cv('exampleprop', 'type_id', 'example_property');
-  tripal_set_default_cv('example_relationship', 'type_id', 'example_relationship');
-
-  // add any custom tables. For this case we will add an 'example' table to the
-  // chado schema
-  tripal_example_add_custom_tables();
-}
-
-
-/**
- * Implements hook_uninstall().
- *
- * Performs actions when the modules is uninstalled.
- *
- * @ingroup tripal_example
- */
-function tripal_example_uninstall() {
-
-}
-
-/**
- * Implementation of hook_schema().
- *
- * Provides a list of tables to be created inside of the Drupal schema (the
- * 'public' schema by default). It uses the Drupal Schema API array structure to
- * define the table, its indexes and constraints.
- *
- * Schema API documentation is here:
- * https://api.drupal.org/api/drupal/includes%21database%21schema.inc/group/schemaapi/7
- *
- * @ingroup tripal_example
- */
-function tripal_example_schema() {
-
-  // EXPLANATION: If your module creates a node type for data in the Chado
-  // database then you probably need to link Drupal nodes with a respective ID
-  // in the Chado table. The following is an example array for a table that will
-  // link the 'chado_example' node type (created by this example module) with a
-  // record in the fake Chado example table. This table will link the 'nid' of
-  // the node with the 'example_id' of the example record.
-  $schema['chado_example'] = array(
-    'fields' => array(
-      'vid' => array(
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0
-       ),
-      'nid' => array(
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0
-       ),
-      'example_id' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0
-      ),
-      'sync_date' => array(
-        'type' => 'int',
-        'not null' => FALSE,
-        'description' => 'UNIX integer sync date/time'
-      ),
-    ),
-    'indexes' => array(
-      'chado_example_idx1' => array('example_id')
-    ),
-    'unique keys' => array(
-      'chado_example_uq1' => array('nid', 'vid'),
-      'chado_example_uq2' => array('vid')
-    ),
-    'primary key' => array('nid'),
-  );
-
-  return $schema;
-};
-
-/**
- * Creates a materialized view that stores the type & number of examples per
- * organism.
- *
- * @ingroup tripal_example
- */
-function tripal_example_add_mviews() {
-
-  // EXPLANATION: use the tripal_add_mview() function to add a materialized view
-  // needed by your module. If you have more than one materialized view it is
-  // best to create a single function for each one and call each function here.
-  // Otherwise this function can become quite long.
-
-}
-/**
- * Add cvs related to publications
- *
- * @ingroup tripal_example
- */
-function tripal_example_add_dbs() {
-  // EXPLANATION: use the tripal_insert_db() function to add any external
-  // databases needed by your module. If the database already exists then the
-  // function will gracefully return.
-
-  tripal_insert_db(array(
-    'name' => 'example_db',
-    'description' => 'An example database.'
-  ));
-}
-/**
- * Add cvs related to publications
- *
- * @ingroup tripal_example
- */
-function tripal_example_add_cvs() {
-
-  // EXPLANATION: use the tripal_insert_cv() function to add any controlled
-  // vocabularies needed by your module. If the vocabulary already exists then
-  // the function will gracefully return. Chado conventions use a singular name
-  // for CV names (not plural).
-
-  tripal_insert_cv(
-    'example_property',
-    'Contains property terms for examples.'
-  );
-
-  tripal_insert_cv(
-    'example_type',
-    'Contains terms describing types of examples.'
-  );
-
-  tripal_insert_cv(
-   'example_relationship',
-   'Contains terms for describing relationship types between examples.'
-  );
-
-}
-
-/**
- * Adds controlled vocabulary terms needed by this module.
- *
- * @ingroup tripal_example
- */
-function tripal_example_add_cvterms() {
-
-  // EXPLANATION: for our test module to work we need to add some terms to our
-  // example_type controlled vocabulary. Ideally we should have a full OBO file
-  // for loading but sometimes we just have a small list that won't really
-  // change so we can add those terms here.
-  tripal_insert_cvterm(array(
-    'id'         => 'test',         // the term accession
-    'name'       => 'Test type',    // the human readable term name
-    'cv_name'    => 'example_type', // the CV name this term belongs to.
-    'definition' => 'A test type for the example module.',
-    'db_name'    => 'example_db',   // the database in which the term is found.
-  ));
-}
-
-/**
- * Add custom tables to Chado that are required by this module
- *
- * @ingroup tripal_example
- */
-function tripal_example_add_custom_tables() {
-
-  // EXPLANATION: for this example module we will create a set of example tables
-  // that mimic Chado tables. These tables are:
-  //
-  //   1) example     (for storing the primary example records)
-  //   2) exampleprop (for sorting properties about the example)
-  //   3) example_relationship (for storing relationships about examples)
-  //   4) example_dbxref (for storing cross-references about an example)
-  //
-  // To make the code easier to read, each table is created by a separate
-  // function called here:
-
-  tripal_example_add_example_table();
-  tripal_example_add_exampleprop_table();
-  tripal_example_add_example_relationship_table();
-  tripal_example_add_example_dbxref_table();
-}
-
-/**
- * Adds the 'example' custom table to Chado.
- *
- * @ingroup tripal_example
- */
-function tripal_example_add_example_table() {
-  // EXPLANATION: use the Drupal Schema API to describe the custom table. Then
-  // add the table using the chado_create_custom_table() function.
-  $schema = array(
-    'table' => 'example',
-    'fields' => array(
-      'example_id' => array(
-        'type' => 'serial',
-        'not null' => true,
-      ),
-      'uniquename' => array(
-        'type' => 'varchar',
-        'length' => '255',
-        'not null' => TRUE,
-      ),
-      'type_id' => array(
-        'type' => 'int',
-        'not null' => true,
-      ),
-      'organism_id' => array(
-        'type' => 'int',
-        'not null' => true,
-      ),
-      'description' => array(
-        'type' => 'text',
-      ),
-    ),
-    'primary key' => array(
-      0 => 'example_id',
-    ),
-    'unique keys' => array(
-      'example_uq1' => array(
-        0 => 'uniquename',
-        1 => 'type_id',
-        2 => 'organism_id',
-      ),
-    ),
-    'indexes' => array(
-      'example_idx1' => array(
-        0 => 'example_id',
-      ),
-      'example_idx2' => array(
-        0 => 'uniquename',
-      ),
-    ),
-    'foreign keys' => array(
-      'cvterm' => array(
-        'table' => 'cvterm',
-        'columns' => array(
-          'type_id' => 'cvterm_id',
-        ),
-      ),
-      'organism' => array(
-        'table' => 'organism',
-        'columns' => array(
-          'organism_id' => 'organism_id',
-        ),
-      ),
-    ),
-    // EXPLANATION: the 'referring_tables' array is the list of tables that have
-    // a foreign key relationships with this table. This information is required
-    // for the Tripal API to be able to expand tables in templates.
-    'referring_tables' => array(
-      0 => 'example_relationship',
-      1 => 'exampleprop',
-      2 => 'example_dbxref',
-    ),
-  );
-  chado_create_custom_table('example', $schema, TRUE);
-}
-/**
- * Adds the 'example_relationship' custom table to Chado.
- *
- * @ingroup tripal_example
- */
-function tripal_example_add_exampleprop_table() {
-  // EXPLANATION: use the Drupal Schema API to describe the custom table. Then
-  // add the table using the chado_create_custom_table() function.
-
-  // Add the exampleprop table
-  $schema =  array(
-    'table' => 'exampleprop',
-    'fields' => array(
-      'exampleprop_id' => array(
-        'type' => 'serial',
-        'not null' => TRUE,
-      ),
-      'example_id' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-      ),
-      'type_id' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-      ),
-      'value' => array(
-        'type' => 'text',
-        'not null' => FALSE,
-      ),
-      'rank' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-      ),
-    ),
-    'primary key' => array(
-      0 => 'exampleprop_id',
-    ),
-    'unique keys' => array(
-      'example_id_type_id_rank' => array(
-        0 => 'example_id',
-        1 => 'type_id',
-        2 => 'rank',
-      ),
-    ),
-    'foreign keys' => array(
-      'cvterm' => array(
-        'table' => 'cvterm',
-        'columns' => array(
-          'type_id' => 'cvterm_id',
-        ),
-      ),
-      'example' => array(
-        'table' => 'example',
-        'columns' => array(
-          'example_id' => 'example_id',
-        ),
-      ),
-    ),
-  );
-  chado_create_custom_table('exampleprop', $schema, TRUE);
-}
-
-/**
- * Adds the 'example_relationship' custom table to Chado.
- *
- * @ingroup tripal_example
- */
-function tripal_example_add_example_relationship_table() {
-  // EXPLANATION: use the Drupal Schema API to describe the custom table. Then
-  // add the table using the chado_create_custom_table() function.
-
-  $schema =  array(
-    'table' => 'example_relationship',
-    'fields' => array(
-      'example_relationship_id' => array(
-        'type' => 'serial',
-        'not null' => TRUE,
-      ),
-      'subject_id' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-      ),
-      'object_id' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-      ),
-      'type_id' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-      ),
-      'value' => array(
-        'type' => 'text',
-        'not null' => FALSE,
-      ),
-      'rank' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-    ),
-    'primary key' => array(
-      0 => 'example_relationship_id',
-    ),
-    'unique keys' => array(
-      'example_relationship_c1' => array(
-        0 => 'subject_id',
-        1 => 'object_id',
-        2 => 'type_id',
-        3 => 'rank',
-      ),
-    ),
-    'indexes' => array(
-      'example_relationship_idx1' => array(
-        0 => 'subject_id',
-      ),
-      'example_relationship_idx2' => array(
-        0 => 'object_id',
-      ),
-      'example_relationship_idx3' => array(
-        0 => 'type_id',
-      ),
-    ),
-    'foreign keys' => array(
-      'cvterm' => array(
-        'table' => 'cvterm',
-        'columns' => array(
-          'type_id' => 'cvterm_id',
-        ),
-      ),
-      'example' => array(
-        'table' => 'example',
-        'columns' => array(
-          'subject_id' => 'example_id',
-          'object_id' => 'example_id',
-        ),
-      ),
-    ),
-  );
-  chado_create_custom_table('example_relationship', $schema, TRUE);
-}
-
-/**
- * Adds the 'example_dbxref' custom table to Chado.
- *
- * @ingroup tripal_example
- */
-function tripal_example_add_example_dbxref_table() {
-
-  // EXPLANATION: use the Drupal Schema API to describe the custom table. Then
-  // add the table using the chado_create_custom_table() function.
-
-  $schema =  array(
-    'table' => 'example_dbxref',
-    'fields' => array(
-      'example_dbxref_id' => array(
-        'type' => 'serial',
-        'not null' => TRUE,
-      ),
-      'example_id' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-      ),
-      'dbxref_id' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-      ),
-      'is_current' => array(
-        'type' => 'int',
-        'size' => 'tiny',
-        'not null' => TRUE,
-        'default' => 1,
-      ),
-    ),
-    'primary key' => array(
-      0 => 'example_dbxref_id',
-    ),
-    'unique keys' => array(
-      'example_dbxref_unq1' => array(
-        0 => 'example_id',
-        1 => 'dbxref_id',
-      ),
-    ),
-    'indexes' => array(
-      'example_dbxref_idx1' => array(
-        0 => 'example_id',
-      ),
-      'example_dbxref_idx2' => array(
-        0 => 'dbxref_id',
-      ),
-    ),
-    'foreign keys' => array(
-      'dbxref' => array(
-        'table' => 'dbxref',
-        'columns' => array(
-          'dbxref_id' => 'dbxref_id',
-        ),
-      ),
-      'example' => array(
-        'table' => 'example',
-        'columns' => array(
-          'example_id' => 'example_id',
-        ),
-      ),
-    ),
-  );
-  chado_create_custom_table('example_dbxref', $schema, TRUE);
-}
-/**
- * This is the required update for tripal_example.
- */
-function tripal_example_update_7200() {
-  // EXPLANATION: as you create new releases of your module you may find that
-  // tables your module created, or data may need to be adjusted. This function
-  // allows you to do that. This function is executed using the
-  // http://[your site]/update.php  URL or using the drush command 'updatedb'.
-  // This function should be named according to the instructions provided here:
-  // https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_update_N/7
-  //
-  // It is best not to use Tripal API calls inside of this function because an
-  // upgrade from Drupal 6 to Drupal 7 requires that all modules be disabled
-  // which means the Tripal API is not available. This is an unfortunate
-  // requirement, but will prevent errors during a major upgrade.
-
-  // it is good to wrap any database changes inside of a try catch block:
-  try {
-   // perform database changes
-  }
-  catch (\PDOException $e) {
-    $error = $e->getMessage();
-    throw new DrupalUpdateException('Could not apply updates: '. $error);
-  }
-}
-
-/**
- * Implementation of hook_update_dependencies(). It specifies a list of other
- * modules whose updates must be run prior to this one.
- */
-function tripal_example_update_dependencies() {
-  $dependencies = array();
-
-  // EXPLANATION: here we can specify which modules must be updated prior to
-  // applying the updates in this module. This is useful because it prevents
-  // updates from being executed out of order. The following example code shows
-  // that the 'tripal_example' module update number 7200 must be executed after
-  // the 'tripal_cv' module's 7200 update.
-  $dependencies['tripal_example'][7200] = array(
-    'tripal_cv' => 7200
-  );
-
-  return $dependencies;
-}

+ 0 - 365
legacy/tripal_example/tripal_example.module

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

+ 0 - 9
legacy/tripal_example/tripal_example.views.inc

@@ -1,9 +0,0 @@
-<?php
-/**
- *  @file
- *  This file contains the basic functions for views integration of chado/tripal
- *  example tables
- */
-
-// EXPLANATION: see another tripal module (e.g. tripal_feature) for example
-// functions that can be used in this file.

+ 0 - 25
legacy/tripal_example/tripal_example.views_default.inc

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

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

@@ -151,7 +151,7 @@ function chado_feature_form($node, &$form_state) {
    '#description' => t("Choose the feature type."),
    '#required'    => TRUE,
    '#default_value' => $feature_type,
-   '#autocomplete_path' => "admin/tripal/vocab/cvterm/auto_name/$cv_id",
+   '#autocomplete_path' => "aadmin/tripal/storage/chado/auto_name/cvterm/$cv_id",
   );
 
   // get the list of organisms

+ 1 - 1
legacy/tripal_feature/includes/tripal_feature.delete.inc

@@ -32,7 +32,7 @@ function tripal_feature_delete_form() {
    '#title'       => t('Feature Type'),
    '#type'        => 'textfield',
    '#description' => t("Choose the feature type."),
-   '#autocomplete_path' => "admin/tripal/vocab/cvterm/auto_name/$cv->cv_id",
+   '#autocomplete_path' => "admin/tripal/storage/chado/auto_name/cvterm/$cv->cv_id",
   );
 
   $organisms = tripal_get_organism_select_options(FALSE);

+ 5 - 5
legacy/tripal_feature/tripal_feature.install

@@ -82,7 +82,7 @@ function tripal_feature_install() {
 function tripal_feature_uninstall() {
 
 }
-// This function was moved to tripal_chado/includes/tripal_chado.setup.inc
+// This function was moved to tripal_chado/includes/setup/tripal_chado.setup.inc
 /* function tripal_feature_add_tripal_gff_temp_table() {
   $schema = array(
     'table' => 'tripal_gff_temp',
@@ -121,7 +121,7 @@ function tripal_feature_uninstall() {
 /**
  *
  */
-// This function was moved to tripal_chado/includes/tripal_chado.setup.inc
+// This function was moved to tripal_chado/includes/setup/tripal_chado.setup.inc
 /* function tripal_feature_add_tripal_gffcds_temp_table($skip_recreate = TRUE) {
   $schema = array(
     'table' => 'tripal_gffcds_temp',
@@ -136,7 +136,7 @@ function tripal_feature_uninstall() {
       ),
       'phase' => array(
         'type' => 'int',
-        'not null' => TRUE,
+        'not null' => FALSE,
       ),
       'strand' => array(
         'type' => 'int',
@@ -162,7 +162,7 @@ function tripal_feature_uninstall() {
 /**
  *
  */
-// This function was moved to tripal_chado/includes/tripal_chado.setup.inc
+// This function was moved to tripal_chado/includes/setup/tripal_chado.setup.inc
 /* function tripal_feature_add_tripal_gffprotein_temp_table() {
   $schema = array(
     'table' => 'tripal_gffprotein_temp',
@@ -245,7 +245,7 @@ function tripal_feature_schema() {
  *
  * @ingroup tripal_feature
  */
-// This function was moved to tripal_chado/includes/tripal_chado.setup.inc
+// This function was moved to tripal_chado/includes/setup/tripal_chado.setup.inc
 /* function tripal_feature_add_organism_count_mview() {
   $view_name = 'organism_feature_count';
   $comment = 'Stores the type and number of features per organism';

+ 1 - 1
legacy/tripal_featuremap/tripal_featuremap.install

@@ -309,7 +309,7 @@ function tripal_featuremap_add_cvterms() {
  *
  * @ingroup tripal_featuremap
  */
-// This function was moved to tripal_chado/includes/tripal_chado.setup.inc
+// This function was moved to tripal_chado/includes/setup/tripal_chado.setup.inc
 /* function tripal_featuremap_add_custom_tables(){
   // add the featuremaprop table to Chado
   $schema = array (

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

@@ -128,7 +128,7 @@ function chado_library_form($node, &$form_state) {
   $lt_message = tripal_set_message("To add additional items to the library type drop down list,
      add a term to the " .
      l($lt_cv->name . " controlled vocabulary",
-       "admin/tripal/vocab/cv/" . $lt_cv->cv_id . "/cvterm/add",
+       "admin/tripal/loaders/chado_cv/" . $lt_cv->cv_id . "/cvterm/add",
        array('attributes' => array('target' => '_blank'))
       ),
      TRIPAL_INFO, array('return_html' => TRUE)

+ 12 - 2
legacy/tripal_pub/includes/tripal_pub.chado_node.inc

@@ -46,6 +46,16 @@ function tripal_pub_node_info() {
 function chado_pub_form($node, $form_state) {
   $form = array();
 
+  // Check to make sure that the tripal_pub vocabulary is loaded. If not, then
+  // warn the user that they should load it before continuing.
+  $pub_cv = chado_select_record('cv', array('cv_id'), array('name' => 'tripal_pub'));
+  if (count($pub_cv) == 0) {
+    drupal_set_message(t('The Tripal Pub vocabulary is currently not loaded. ' .
+        'This vocabulary is required to be loaded before adding ' .
+        'publications.  <br>Please !import',
+        array('!import' => l('load the Tripal Publication vocabulary', 'admin/tripal/loaders/obo_loader'))), 'warning');
+  }
+
   // Default values can come in the following ways:
   //
   // 1) as elements of the $node object.  This occurs when editing an existing pub
@@ -190,7 +200,7 @@ function chado_pub_form($node, $form_state) {
   );
 
   $type_cv = tripal_get_default_cv('pub', 'type_id');
-  if ($type_cv->name == 'tripal_pub') {
+  if ($type_cv and $type_cv->name == 'tripal_pub') {
 
     // get the list of publication types.  In the Tripal publication
     // ontologies these are all grouped under the term 'Publication Type'
@@ -262,7 +272,7 @@ function chado_pub_form($node, $form_state) {
   $cv_id = $prop_cv ? $prop_cv->cv_id : NULL;
   // if the poperty cv is 'tripal_pub' then we need to pass in our own select_options
   // for only a subset of the vocabulary
-  if ($prop_cv->name == 'tripal_pub') {
+  if ($prop_cv and $prop_cv->name == 'tripal_pub') {
     $select_options[] = 'Select a Property';
     $sql = "
       SELECT

+ 1 - 1
legacy/tripal_pub/tripal_pub.install

@@ -171,7 +171,7 @@ function tripal_pub_schema() {
  *
  * @ingroup tripal_pub
  */
-// This function was moved to tripal_chado/includes/tripal_chado.setup.inc
+// This function was moved to tripal_chado/includes/setup/tripal_chado.setup.inc
 /* function tripal_pub_add_custom_tables() {
   $schema = array (
     'table' => 'pubauthor_contact',

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

@@ -202,7 +202,7 @@ function chado_stock_form($node, $form_state) {
   $st_message = tripal_set_message("To add additional items to the stock type drop down list,
      add a term to the " .
     l($st_cv->name . " controlled vocabulary",
-      "admin/tripal/vocab/cv/" . $st_cv->cv_id . "/cvterm/add",
+      "admin/tripal/loaders/chado_cv/" . $st_cv->cv_id . "/cvterm/add",
       array('attributes' => array('target' => '_blank'))
     ),
     TRIPAL_INFO, array('return_html' => TRUE)

+ 0 - 14
tripal/api/tripal.entities.api.inc

@@ -446,20 +446,6 @@ function tripal_get_content_types() {
     ->fetchAll();
 }
 
-/**
- * Implements hook_cron().
- */
-function tripal_cron() {
-  if (variable_get('tripal_admin_notification_creation_during_cron', TRUE)) {
-    $modules = module_implements('tripal_cron_notification');
-    foreach ($modules as $module) {
-      $function = $module . '_tripal_cron_notification';
-      $function();
-    }
-    watchdog('tripal_cron', 'tripal_cron ran');
-  }
-}
-
 /**
  * Refreshes the bundle such that new fields added by modules will be found during cron.
  *

+ 137 - 0
tripal/api/tripal.importer.api.inc

@@ -0,0 +1,137 @@
+<?php
+/**
+ * Implements hook_handle_uplaoded_file().
+ *
+ * This is a Tripal hook that allows the module to set the proper
+ * parameters for a file uploaded via the Tripal HTML5 uploader.
+ *
+ * @param $filename
+ *   The name of the file uploaded
+ * @param $filepath
+ *   The path to the file
+ * @param $type
+ *   The category or type of file.
+ *
+ * @return
+ *   A Drupal managed file ID.
+ */
+function hook_handle_uploaded_file($filename, $filepath, $type) {
+
+}
+
+/**
+ * Retrieves a list of TripalImporter Importers.
+ *
+ * The TripalImporter classes can be added by a site developer that wishes
+ * to create a new data loader.  The class file should
+ * be placed in the [module]/includes/TripalImporter directory.  Tripal will
+ * support any loader as long as it is in this directory and extends the
+ * TripalImporter class.
+ *
+ * @return
+ *   A list of TripalImporter names.
+ */
+function tripal_get_importers() {
+  $importers = array();
+
+  $modules = module_list(TRUE);
+  foreach ($modules as $module) {
+    // Find all of the files in the tripal_chado/includes/fields directory.
+    $loader_path = drupal_get_path('module', $module) . '/includes/TripalImporter';
+    $loader_files = file_scan_directory($loader_path, '/.inc$/');
+    // Iterate through the fields, include the file and run the info function.
+    foreach ($loader_files as $file) {
+      $class = $file->name;
+      module_load_include('inc', $module, 'includes/TripalImporter/' . $class);
+      if (class_exists($class) and is_subclass_of($class, 'TripalImporter')) {
+        $importers[] = $class;
+      }
+    }
+  }
+  return $importers;
+}
+
+/**
+ * Loads the TripalImporter class file into scope.
+ *
+ * @param $class
+ *   The TripalImporter class to include.
+ *
+ * @return
+ *   TRUE if the field type class file was found, FALSE otherwise.
+ */
+function tripal_load_include_importer_class($class) {
+
+  $modules = module_list(TRUE);
+  foreach ($modules as $module) {
+    $file_path = realpath(".") . '/' . drupal_get_path('module', $module) . '/includes/TripalImporter/' . $class . '.inc';
+    if (file_exists($file_path)) {
+      module_load_include('inc', $module, 'includes/TripalImporter/' . $class);
+      if (class_exists($class)) {
+        return TRUE;
+      }
+    }
+  }
+  return FALSE;
+}
+
+/**
+ * Imports data into the database.
+ *
+ * Tripal provides the TripalImporter class to allow site developers to
+ * create their own data loaders.  Site users can then use any data loader
+ * implemented for the site by submitting the form that comes with the
+ * TripalImporter impelmentation.  This function runs the importer using the
+ * arguments provided by the user.
+ *
+ * @param $import_id
+ *   The ID of the import record.
+ * @throws Exception
+ */
+function tripal_run_importer($import_id, TripalJob $job = NULL) {
+
+  $loader = NULL;
+  try {
+    // begin the transaction
+    $transaction = db_transaction();
+    print "\nNOTE: Loading of this file is performed using a database transaction. \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";
+
+    $loader = TripalImporter::byID($import_id);
+    $loader->setJob($job);
+    $loader->prepareFile();
+    $loader->run();
+    $loader->cleanFile();
+
+    if ($job) {
+      $job->logMessage("Done");
+    }
+
+    // Remove the temp file
+    if (!empty($details->arguments['file_url'])) {
+      $loader->logMessage('Removing downloaded file...');
+      unlink($temp);
+    }
+
+    print "\nDone\n";
+
+
+    // Check for tables with new cvterms
+    tripal_chado_map_cvterms();
+
+    // Check for new fields and notify the user.
+    tripal_tripal_cron_notification();
+
+  }
+  catch (Exception $e) {
+    $transaction->rollback();
+    if ($job) {
+      $job->logMessage($e->getMessage(), array(), TRIPAL_ERROR);
+    }
+    if ($loader) {
+      $loader->cleanFile();
+    }
+  }
+}
+

+ 150 - 182
tripal/api/tripal.jobs.api.inc

@@ -80,77 +80,41 @@
 function tripal_add_job($job_name, $modulename, $callback, $arguments, $uid,
     $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);
 
-  // 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)));
+
+    // 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)));
+          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)));
+          "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
  *
  * @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
  */
 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;
   }
-
-  $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;
 }
 
 /**
@@ -255,7 +217,7 @@ function tripal_max_jobs_exceeded($max_jobs) {
       // the job is not running so terminate it
       $record = new stdClass();
       $record->job_id = $job->job_id;
-      $record->end_time = REQUEST_TIME;
+      $record->end_time = time();
       $record->status = 'Error';
       $record->error_msg = 'Job has terminated unexpectedly.';
       drupal_write_record('tripal_jobs', $record, 'job_id');
@@ -280,24 +242,47 @@ function tripal_rerun_job($job_id, $goto_jobs_page = TRUE) {
 
   $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;
   }
 
-  $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");
+    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) {
 
-  // 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()) {
     print "Jobs are still running. Use the --parallel=1 option with the Drush command to run jobs in parallel.\n";
     return;
@@ -377,55 +354,45 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $si
     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) {
-    $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 {
-    $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 AND
+        NOT TJ.status = 'Cancelled'
+      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
     // to serialized arrays now allows nested arrays which cause errors when
     // printed using implode alone.
+    $args = $job->getArguments();
     $string_args = array();
     foreach ($args as $k => $a) {
       if (is_array($a)) {
@@ -439,13 +406,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) {
+      $job->logMessage($e->getMessage(), array(), TRIPAL_ERROR);
+      drupal_set_message($e->getMessage(), 'error');
+    }
 
     if ($single) {
       // Don't start any more jobs
@@ -455,7 +425,7 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $si
       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 +444,17 @@ function tripal_launch_job($do_parallel = 0, $job_id = NULL, $max_jobs = -1, $si
  */
 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 +465,21 @@ function tripal_set_job_progress($job_id, $percentage) {
  *
  * @return
  *   A value between 0 and 100 indicating the percentage complete of the job.
+ *   FALSE on failure.
  */
 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;
   }
-
-  // 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.
@@ -558,5 +528,3 @@ function tripal_get_active_jobs($modulename = NULL) {
   }
   return $jobs;
 }
-
-

+ 12 - 6
tripal/api/tripal.notice.api.inc

@@ -26,10 +26,13 @@ define('TRIPAL_NOTICE',5);
 define('TRIPAL_INFO',6);
 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
  *   The catagory to which this message belongs. Can be any string, but the
@@ -83,7 +86,7 @@ function tripal_report_error($type, $severity, $message, $variables = array(), $
       break;
   }
 
-  // get the backtrace and include in the error message, but only if the
+  // Get the backtrace and include in the error message, but only if the
   // TRIPAL_DEBUG environment variable is set.
   if (getenv('TRIPAL_DEBUG') == 1) {
     $backtrace = debug_backtrace();
@@ -123,8 +126,10 @@ function tripal_report_error($type, $severity, $message, $variables = array(), $
 }
 
 /**
- * Display messages to tripal administrators. This can be used instead of
- * drupal_set_message when you want to target tripal administrators.
+ * Display messages to tripal administrators.
+ *
+ * This can be used instead of drupal_set_message when you want to target
+ * tripal administrators.
  *
  * @param $message
  *   The message to be displayed to the tripal administrators
@@ -226,3 +231,4 @@ function tripal_log($message, $type = 'error', $options = array()) {
   return error_log($message);
 
 }
+

+ 42 - 309
tripal/includes/TripalBundleUIController.inc

@@ -412,8 +412,7 @@ function tripal_bundle_access($op, $type = NULL, $account = NULL) {
  */
 function tripal_admin_add_type_form($form, &$form_state) {
 
-  // TODO: the Chado specific function calls should not be here.  They need
-  // to be genericized.
+
   $stores = module_invoke_all('vocab_storage_info');
   if (!is_array($stores) or count($stores) == 0) {
     tripal_set_message('A storage backend is not enabled for managing
@@ -456,6 +455,8 @@ function tripal_admin_add_type_form($form, &$form_state) {
     ),
   );
 
+  // If the term has been provided by the user then we want to search for
+  // matching terms in the database and let them select among any matches.
   if ($term_name) {
     $submit_disabled = TRUE;
     $form['terms_list'] = array(
@@ -471,7 +472,10 @@ function tripal_admin_add_type_form($form, &$form_state) {
     $terms = chado_generate_var('cvterm', $match, array('return_array' => TRUE));
     $terms = chado_expand_var($terms, 'field', 'cvterm.definition');
     $num_terms = 0;
-    $selected_term_id = '';
+    $selected_term = '';
+
+    // Let the user select from any matching terms. Sometimes there may be
+    // more than one that match.
     foreach ($terms as $term) {
       // Save the user a click by setting the default value as 1 if there's
       // only one matching term.
@@ -500,7 +504,7 @@ function tripal_admin_add_type_form($form, &$form_state) {
 
       if (array_key_exists('values', $form_state) and array_key_exists($term_element_name, $form_state['values']) and
           $form_state['values'][$term_element_name] == 1) {
-        $selected_term_id = $term->cvterm_id;
+        $selected_term = $term;
       }
       $num_terms++;
     }
@@ -510,6 +514,8 @@ function tripal_admin_add_type_form($form, &$form_state) {
         '#markup' => '<i>' . t('There is no term that matches the entered text.') . '</i>'
       );
     }
+
+    // Now let the user select where the data type will be stored.
     $form['storage'] = array(
       '#type' => 'fieldset',
       '#title' => t('Storage Settings'),
@@ -518,12 +524,9 @@ function tripal_admin_add_type_form($form, &$form_state) {
           storage method and settings for this content type.')
     );
 
-    // TODO: we should have a default store setting so that user's have
-    // fewer clicks.
-
     // TODO: there should be a way for each storage backend to determine if
     // it can handle the content type.  Maybe certain content types aren't
-    // yet supported by every sotrage backend.
+    // yet supported by every storage backend.
     $default_store = 'term_chado_storage';
     $store_options = array(0 => '-- Select --');
     foreach ($stores as $store_type => $store) {
@@ -548,273 +551,14 @@ function tripal_admin_add_type_form($form, &$form_state) {
     );
 
     if ($default_store) {
-      if ($store_type == 'term_chado_storage') {
-        // TODO: Move this Chado-specific code out of there.
-        $default_table = '';
-        if (array_key_exists('base_chado_table', $form_state['values'])
-            and $form_state['values']['base_chado_table']) {
-          $default_table = $form_state['values']['base_chado_table'];
-        }
-        else {
-          $mapped_table = chado_get_cvterm_mapping(array('cvterm_id' => $selected_term_id));
-          if ($mapped_table) {
-            $default_table = $mapped_table->chado_table;
-          }
-        }
-
-        $form['storage'][$store_type]['selected_cvterm_id'] = array(
-          '#type' => 'value',
-          '#value' => $selected_term_id,
-        );
-
-        $base_tables = chado_get_base_tables();
-        $options = array(0 => '-- Select table --');
-        foreach ($base_tables AS $tablename) {
-          $options[$tablename] = $tablename;
-        }
-        $form['storage'][$store_type]['base_chado_table'] = array(
-          '#type' => 'select',
-          '#title' => 'Chado table',
-          '#options' => $options,
-          '#description' => 'Select the Chado table into which the primary records for this content type will be stored.',
-          '#default_value' => $default_table,
-          '#ajax' => array(
-            'callback' => "tripal_admin_add_type_form_ajax_callback",
-            'wrapper' => "tripal-vocab-select-form",
-            'effect' => 'fade',
-            'method' => 'replace'
-          ),
-        );
-        $form_state['input']['base_chado_table'] = $default_table;
-
-        if ($default_table) {
-
-          // There are a few places in form below where the type columns
-          // can be used to identify a record. So, we'll create the
-          // select options here so it can be used multiple places.  We
-          // only want to include in our column options those fields that
-          // are foreign keys to the cvterm table
-          $schema = chado_get_schema($default_table);
-          $column_options = array('0' => '--Select column--');
-          $cvt_fkeys = array_keys($schema['foreign keys']['cvterm']['columns']);
-          foreach ($schema['fields'] as $column_name => $column_details) {
-            if (in_array($column_name, $cvt_fkeys)) {
-              $column_options[$column_name] = $column_name;
-            }
-          }
-
-          $default_has_all = 'No';
-          if (array_key_exists('chado_table_has_all', $form_state['values'])
-              and $form_state['values']['chado_table_has_all']) {
-            $default_has_all = $form_state['values']['chado_table_has_all'];
-          }
-          $form['storage'][$store_type]['chado_table_has_all'] = array(
-            '#type' => 'radios',
-            '#options' => array(
-              'Yes' => 'Yes',
-              'No' => 'No'
-            ),
-            '#title' => 'Are all records in the "' . $default_table .
-              '" table of type "'. $term_name . '"?',
-            '#description' => 'Select "Yes" if the "' .
-              $default_table . '" table houses more that just data of type "' .
-              $term_name . '".',
-            '#default_value' => $default_has_all,
-            '#ajax' => array(
-              'callback' => "tripal_admin_add_type_form_ajax_callback",
-              'wrapper' => "tripal-vocab-select-form",
-              'effect' => 'fade',
-              'method' => 'replace'
-            ),
-          );
-
-          // If the table does not contain just one single type of record.
-          if ($default_has_all == 'No') {
-
-            $default_type_column = '';
-            if (array_key_exists('type_id', $schema['fields'])) {
-              $default_type_column = 'type_id';
-            }
-
-            // If the table doesn't have an obvious type_id column then
-            // let the user specify how record types are identified.
-            if ($default_type_column) {
-
-              $default_has_type = 'Yes';
-              if (array_key_exists('chado_table_has_type', $form_state['values'])
-                  and $form_state['values']['chado_table_has_type']) {
-                $default_has_type = $form_state['values']['chado_table_has_type'];
-              }
-              $form['storage'][$store_type]['chado_table_has_type'] = array(
-                '#type' => 'radios',
-                '#title' => 'Do you want to use the "' . $default_table . '.' .
-                   $default_type_column . '" to distinguish between content types?',
-                '#options' => array(
-                  'Yes' => 'Yes',
-                  'No' => 'No'
-                ),
-                '#description' => t('Many tables in Chado use a "type_id" column
-                    to identify specific data types. For example, the "feature.type_id"
-                    column is used to distinguish between different types of
-                    genomic features that are all housed in the feature table.
-                    But there is sometimes a cvterm linker table where additional
-                    attributes for the record can be set.  Here you can specify if you
-                    want to use the type_id column or select another way
-                    to identify records in the "' . $default_table . '" table that
-                    are of this type'),
-                '#default_value' => $default_has_type,
-                '#ajax' => array(
-                  'callback' => "tripal_admin_add_type_form_ajax_callback",
-                  'wrapper' => "tripal-vocab-select-form",
-                  'effect' => 'fade',
-                  'method' => 'replace'
-                ),
-              );
-
-              // If the type_id column is not wanted to differentiate between
-              // different records of this type then find out if the user wants
-              // to use a linker cvterm table, but only if one exists
-              $linker_table = $default_table . '_cvterm';
-              if ($default_has_type == "Yes") {
-                $submit_disabled = FALSE;
-              }
-              else if ($default_has_type == 'No' and chado_table_exists($linker_table)) {
-                $default_use_linker = 'Yes';
-                if (array_key_exists('chado_type_use_linker', $form_state['values'])
-                    and $form_state['values']['chado_type_use_linker']) {
-                  $default_use_linker = $form_state['values']['chado_type_use_linker'];
-                }
-                $form['storage'][$store_type]['chado_type_use_linker'] = array(
-                  '#type' => 'radios',
-                  '#title' => 'Do you want to use the "' . $linker_table . '" table
-                     to distinguish between content types?',
-                  '#options' => array(
-                    'Yes' => 'Yes',
-                    'No' => 'No'
-                  ),
-                  '#description' => t('Sometimes records can be distringuish
-                      using a linker table, especially if there is no column
-                      in the specified Chado table to identify the
-                      record types. In these cases the linker table is
-                      sometimes used.'),
-                  '#default_value' => $default_use_linker,
-                  '#ajax' => array(
-                    'callback' => "tripal_admin_add_type_form_ajax_callback",
-                    'wrapper' => "tripal-vocab-select-form",
-                    'effect' => 'fade',
-                    'method' => 'replace'
-                  ),
-                );
-
-                if($default_use_linker == 'No') {
-                  if (count(array_keys($column_options)) == 1) {
-                    $form['storage'][$store_type]['type_column'] = array(
-                      '#type' => 'item',
-                      '#title' => 'Type Column',
-                      '#description' => 'The  "' . $default_table .
-                        '" table does not have a column
-                        that stores data types. You cannot map the "' .
-                        $term_name . '" type to this table.',
-                    );
-                  }
-                  else {
-                    $form['storage'][$store_type]['type_column'] = array(
-                      '#type' => 'select',
-                      '#title' => 'Type Column',
-                      '#options' => $column_options,
-                      '#description' => 'Please select the column in the "' .
-                        $default_table . '" table that will identify a record
-                        as being of type "' . $term_name . '".',
-                      '#default_value' => $default_type_column,
-                      '#ajax' => array(
-                        'callback' => "tripal_admin_add_type_form_ajax_callback",
-                        'wrapper' => "tripal-vocab-select-form",
-                        'effect' => 'fade',
-                        'method' => 'replace'
-                      ),
-                    );
-                    $submit_disabled = FALSE;
-                  }
-                } // end if(!$default_use_linker) {
-                else {
-                  $submit_disabled = FALSE;
-                }
-              } // end if ($default_has_type == 'No' and ...
-            } // end else if ($default_type_column) {
-            else {
-              // If the type_id column is not wanted to differentiate between
-              // different records of this type then find out if the user wants
-              // to use a linker table, but only if one exists
-              $linker_table = $default_table . '_cvterm';
-              if (chado_table_exists($linker_table)) {
-                $default_use_linker = 'Yes';
-                if (array_key_exists('chado_type_use_linker', $form_state['values'])
-                    and $form_state['values']['chado_type_use_linker']) {
-                  $default_use_linker = $form_state['values']['chado_type_use_linker'];
-                }
-                $form['storage'][$store_type]['chado_type_use_linker'] = array(
-                  '#type' => 'radios',
-                  '#title' => 'Do you want to use the "' . $linker_table . '" table
-                     to distinguish between content types?',
-                  '#options' => array(
-                    'Yes' => 'Yes',
-                    'No' => 'No'
-                  ),
-                  '#description' => t('Sometimes records can be distringuish
-                      using a linker, especially if there is no column
-                      in the specified Chado table to identify the
-                      record types. In these cases the linker table is
-                      sometimes used.'),
-                  '#default_value' => $default_use_linker,
-                  '#ajax' => array(
-                    'callback' => "tripal_admin_add_type_form_ajax_callback",
-                    'wrapper' => "tripal-vocab-select-form",
-                    'effect' => 'fade',
-                    'method' => 'replace'
-                  ),
-                );
-
-                if($default_use_linker == 'No') {
-                  if (count(array_keys($column_options)) == 1) {
-                    $form['storage'][$store_type]['type_column'] = array(
-                      '#type' => 'item',
-                      '#title' => 'Type Column',
-                      '#description' => 'The  "' . $default_table .
-                        '" table does not have a column
-                        that stores data types. You cannot map the "' .
-                        $term_name . '" type to this table.',
-                    );
-                  }
-                  else {
-                    $form['storage'][$store_type]['type_column'] = array(
-                      '#type' => 'select',
-                      '#title' => 'Type Column',
-                      '#options' => $column_options,
-                      '#description' => 'Please select the column in the "' .
-                        $default_table . '" table that will identify a record
-                        as being of type "' . $term_name . '".',
-                      '#default_value' => $default_type_column,
-                      '#ajax' => array(
-                        'callback' => "tripal_admin_add_type_form_ajax_callback",
-                        'wrapper' => "tripal-vocab-select-form",
-                        'effect' => 'fade',
-                        'method' => 'replace'
-                      ),
-                    );
-                    $submit_disabled = FALSE;
-                  }
-                } // end if(!$default_use_linker) {
-                else {
-                  $submit_disabled = FALSE;
-                }
-              } // end if ($default_has_type == 'No' and ...
-            } // end else
-          } //  end if ($default_has_all == 'No') {
-          else {
-            $submit_disabled = FALSE;
-          }
-        } // end if ($default_table) {
-      } // end if ($default_store) {
+      $selected_store_module = $stores[$store_type]['module'];
+
+      $function = $selected_store_module . '_field_storage_bundle_mapping_form';
+      if (function_exists($function)) {
+        $store_form = $function($form, $form_state, $selected_term, $submit_disabled);
+        $form['storage'][$store_type] = $store_form;
+      }
+
       // Add in the button for the cases of no terms or too many.
       $form['submit_button'] = array(
         '#type' => 'submit',
@@ -843,12 +587,7 @@ function tripal_admin_add_type_form_ajax_callback($form, $form_state) {
  */
 function tripal_admin_add_type_form_validate($form, &$form_state) {
   $stores = module_invoke_all('vocab_storage_info');
-  $keys = array_keys($stores);
-  $module = $stores[$keys[0]]['module'];
-  $function = $module . '_vocab_select_term_form_validate';
-  if (function_exists($function)) {
-    $function($form, $form_state);
-  }
+  $store_select = $form_state['values']['store_select'];
 
   if (array_key_exists('clicked_button', $form_state) and
       $form_state['clicked_button']['#name'] =='use_cvterm') {
@@ -866,6 +605,7 @@ function tripal_admin_add_type_form_validate($form, &$form_state) {
         $num_selected++;
       }
     }
+
     if ($num_selected == 0) {
       form_set_error('', 'Please select at least one term.');
     }
@@ -873,15 +613,20 @@ function tripal_admin_add_type_form_validate($form, &$form_state) {
       form_set_error('term-' . $cvterm_id, 'Please select only one term from the list below.');
     }
     else {
+      // Add the term to the form state so we can access it later.
       $form_state['term']['vocabulary'] = $term->dbxref_id->db_id->name;
       $form_state['term']['accession'] = $term->dbxref_id->accession;
       $form_state['term']['term_name'] = $term->name;
 
-      // Make sure a default table is selected
-      // TODO: move this Chado specific code out.
-      $default_table = $form_state['values']['base_chado_table'];
-      if (!$default_table) {
-        form_set_error('base_chado_table', 'Please select a default table.');
+      // Call the submit hook for this form for the storage method that
+      // will be responsible for this cotent type.
+      $stores = module_invoke_all('vocab_storage_info');
+      $selected_store_module = $stores[$store_select]['module'];
+      $selected_term = $form_state['term'];
+
+      $function = $selected_store_module . '_field_storage_bundle_mapping_form_validate';
+      if (function_exists($function)) {
+        $function($form, $form_state, $selected_term);
       }
     }
   }
@@ -899,6 +644,7 @@ function tripal_admin_add_type_form_submit($form, &$form_state) {
   $accession = '';
   if (array_key_exists('term', $form_state)) {
     $selected_term = $form_state['term'];
+    $store_select = $form_state['values']['store_select'];
     $vocabulary = array_key_exists('vocabulary', $selected_term) ? $selected_term['vocabulary'] : '';
     $accession = array_key_exists('accession', $selected_term) ? $selected_term['accession'] : '';
     $term_name = array_key_exists('term_name', $selected_term) ? $selected_term['term_name'] : '';
@@ -907,34 +653,25 @@ function tripal_admin_add_type_form_submit($form, &$form_state) {
     // as a bundle.
     $term = tripal_load_term_entity(array('vocabulary' => $vocabulary, 'accession' => $accession));
     if (!$term) {
-      $error = '';
-      // TODO: the storage args are Chado specific. This should be made
-      // more generic to support other back-ends.
+
+      // Call the submit hook for this form for the storage method that
+      // will be responsible for this cotent type.
+      $stores = module_invoke_all('vocab_storage_info');
+      $selected_store_module = $stores[$store_select]['module'];
+
       $storage_args = array();
-      if (array_key_exists('base_chado_table', $form_state['values'])) {
-        $storage_args['data_table'] = $form_state['values']['base_chado_table'];
-      }
-      if (array_key_exists('chado_type_use_linker', $form_state['values']) and
-          $form_state['values']['chado_type_use_linker'] == 'Yes') {
-        $storage_args['type_linker_table'] = $form_state['values']['base_chado_table'] . '_cvterm';
-        $storage_args['type_column'] = 'cvterm_id';
-      }
-      if (array_key_exists('chado_table_has_type', $form_state['values']) and
-          $form_state['values']['chado_table_has_type'] == 'Yes') {
-        $storage_args['type_column'] = 'type_id';
-      }
-      if (array_key_exists('type_column', $form_state['values']) and
-          $form_state['values']['type_column']) {
-        $storage_args['type_column'] = $form_state['values']['type_column'];
+      $function = $selected_store_module . '_field_storage_bundle_mapping_form_submit';
+      if (function_exists($function)) {
+        $function($form, $form_state, $term, $storage_args);
       }
 
-      $storage_args['type_id'] = $form_state['values']['selected_cvterm_id'];
       $args = array(
         'vocabulary' => $vocabulary,
         'accession' => $accession,
         'term_name' => $term_name,
         'storage_args' => $storage_args,
       );
+
       $bundle = tripal_create_bundle($args, $error);
       if (!$bundle) {
         drupal_set_message($error, 'error');
@@ -945,10 +682,6 @@ function tripal_admin_add_type_form_submit($form, &$form_state) {
         tripal_admin_access($bundle);
         $form_state['redirect'] = "admin/structure/bio_data";
       }
-
-      // TODO: move these Chado specific settings out.
-
-
     }
     else {
       drupal_set_message("The term '$accession' already exists as a content type.", 'warning');

+ 1 - 1
tripal/includes/TripalEntity.inc

@@ -331,7 +331,7 @@ class TripalEntityController extends EntityAPIController {
     }
     catch (Exception $e) {
       $transaction->rollback();
-      watchdog_exception('tripal_core', $e);
+      watchdog_exception('tripal', $e);
       drupal_set_message("Could not save the entity: " . $e->getMessage(), "error");
       return FALSE;
     }

+ 2 - 2
tripal/includes/TripalEntityUIController.inc

@@ -512,8 +512,8 @@ function tripal_entity_form_ajax_callback($form, $form_state) {
 
    // If the user is cancelling or deleting the entity then don't validate.
    if (array_key_exists('clicked_button', $form_state) and
-       $form_state['clicked_button']['#name'] =='cancel_data' or
-       $form_state['clicked_button']['#name'] =='delete_data') {
+       ($form_state['clicked_button']['#name'] == 'cancel_data' or
+        $form_state['clicked_button']['#name'] == 'delete_data')) {
      return;
    }
    // For adds and updates, perform validation.

+ 18 - 21
tripal/includes/TripalFieldQuery.inc

@@ -56,7 +56,6 @@ class TripalField {
     // is convenient for speed.  Fields that are slow should for loading
     // should ahve auto_attach set to FALSE so tha their values can be
     // attached asyncronously.
-    'auto_attach' => TRUE,
   );
 
   // The default widget for this field.
@@ -74,6 +73,12 @@ class TripalField {
   // and field_create_instance().
   public static $no_ui = TRUE;
 
+  // A boolean specifying that the field will not contain any data. This
+  // should exclude the field from web serivces or downloads.  An example
+  // could be a quick search field that appears on the page that redirects
+  // the user but otherwise provides no data.
+  public static $no_data = FALSE;
+
 
   // --------------------------------------------------------------------------
   //              PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
@@ -81,6 +86,7 @@ class TripalField {
   // An array containing details about the field. The format of this array
   // is the same as that returned by field_info_fields()
   protected $field;
+
   // An array containing details about an instance of the field. A field does
   // not have to have an instance.  But if dealing with an instance (such as
   // when using the widgetForm, formatterSettingsForm, etc.) it should be set.
@@ -88,7 +94,7 @@ class TripalField {
 
 
   // --------------------------------------------------------------------------
-  //                     CONSTRUCTORS -- DO NOT OVERRIDE
+  //                     CONSTRUCTORS
   // --------------------------------------------------------------------------
 
   /**
@@ -105,25 +111,9 @@ class TripalField {
 
     $class = get_called_class();
 
-    // Make sure the term exist.
     if (!$instance) {
       tripal_set_message(t('Missing instance of field "%field"', array('%field' => $field['field_name'])), TRIPAL_ERROR);
     }
-    else {
-      // If the vocabulary and accession are set then make sure that the
-      // term is a real term. It is possible that the vocabulary and accession
-      // may not be set initially. This occurs when a field is created
-      // dynamically be a priviledge site admin.
-      if (array_key_exists('term_vocabulary', $instance['settings'])) {
-        $vocabulary = $instance['settings']['term_vocabulary'];
-        $accession = $instance['settings']['term_accession'];
-        $term = tripal_get_term_details($vocabulary, $accession);
-        if (!$term) {
-          throw new Error(t('Cannot create TripalField of type "%term" as that
-              term does not exist.', array('%term' => "$vocabulary:$accession")));
-        }
-      }
-    }
   }
 
   // --------------------------------------------------------------------------
@@ -176,6 +166,15 @@ class TripalField {
   public function getInstance() {
     return $this->instance;
   }
+
+  /**
+   * When constructing a pager for use by a field, all pagers must have
+   * a unique ID
+   */
+  protected function getPagerElementID() {
+    return $this->field['id'];
+  }
+
   // --------------------------------------------------------------------------
   //                            OVERRIDEABLE FUNCTIONS
   // --------------------------------------------------------------------------
@@ -217,7 +216,6 @@ class TripalField {
    * Loads the field values from the underlying data store.
    *
    * @param $entity
-   * @param $details
    *
    * @return
    *   An array of the following format:
@@ -241,11 +239,10 @@ class TripalField {
    *
    *
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
 
   }
 
-
   /**
    * Provides a form for the 'Field Settings' of the field management page.
    *

+ 41 - 5
tripal/includes/TripalFields/TripalFieldFormatter.inc

@@ -66,11 +66,17 @@ class TripalFieldFormatter {
    * This form will not be displayed if the formatter_settings_summary()
    * function does not return anything.
    *
-   * @param $field
-   * @param $instance
-   * @param $view_mode
-   * @param $form
-   * @param $form_state
+   * param $field
+   *   The field structure being configured.
+   * param $instance
+   *   The instance structure being configured.
+   * param $view_mode
+   *   The view mode being configured.
+   * param $form
+   *   The (entire) configuration form array, which will usually have no use
+   *   here.  Typically for reference only.
+   * param $form_state
+   *   The form state of the (entire) configuration form.
    *
    * @return
    *   A Drupal Form array containing the settings form for this field.
@@ -144,5 +150,35 @@ class TripalFieldFormatter {
 
   }
 
+  /**
+   * When constructing a pager for use by a field, all pagers must have
+   * a unique ID
+   */
+  protected function getPagerElementID() {
+    return $this->field['id'];
+  }
+
+  /**
+   * Updates a pager generated by theme('pager') for use with AJAX.
+   *
+   * Because fields are meant to be updated by AJAX we need clicks in the pager
+   * to not reload the entire page but rather to only reload the field.
+   * Therefore the links in the pager must be adjusted to support this.
+   *
+   * @param $pager
+   *   The pager as created by theme('pager')
+   * @param $entity
+   *   The entity object.
+   */
+  protected function ajaxifyPager($pager, $entity) {
+
+    $field_id = 'tripal-entity-' . $entity->id . '--' . $this->field['field_name'];
+
+    $pager = preg_replace('/href="\/.+\?page=(.+?)"/', 'href="javascript:void(0)" onclick="tripal_navigate_field_pager(\'' . $field_id . '\', $1)"', $pager);
+    $pager = preg_replace('/href="\/.+"/', 'href="javascript:void(0)" onclick="tripal_navigate_field_pager(\'' . $field_id . '\', 0)"', $pager);
+
+    $pager = '<img src="/' . drupal_get_path('module', 'tripal') . '/theme/images/ajax-loader.gif" id="' . $field_id . '-spinner" class="tripal-field-ajax-spinner">' . $pager;
+    return $pager;
+  }
 
 }

+ 1 - 1
tripal/includes/TripalFields/content_type/content_type.inc

@@ -22,7 +22,7 @@ class content_type extends TripalField {
   /**
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
     $bundle = tripal_load_bundle_entity(array('name' => $entity->bundle));
     $entity->{$this->field['field_name']}['und'][0]['value'] = $bundle->label;
   }

+ 1 - 1
tripal/includes/TripalFields/rdfs__type/rdfs__type.inc

@@ -46,7 +46,7 @@ class rdfs__type extends TripalField {
   /**
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
     $bundle = tripal_load_bundle_entity(array('name' => $entity->bundle));
     $entity->{$this->field['field_name']}['und'][0]['value'] = $bundle->label;
   }

+ 606 - 0
tripal/includes/TripalImporter.inc

@@ -0,0 +1,606 @@
+<?php
+
+class TripalImporter {
+
+  // --------------------------------------------------------------------------
+  //                     EDITABLE STATIC CONSTANTS
+  //
+  // The following constants SHOULD be set for each descendent class.  They are
+  // used by the static functions to provide information to Drupal about
+  // the field and it's default widget and formatter.
+  // --------------------------------------------------------------------------
+
+  /**
+   * The name of this loader.  This name will be presented to the site
+   * user.
+   */
+  public static $name = 'Tripal Loader';
+
+  /**
+   * The machine name for this loader. This name will be used to construct
+   * the URL for the loader.
+   */
+  public static $machine_name = 'tripal_loader';
+
+  /**
+   * A brief description for this loader.  This description will be
+   * presented to the site user.
+   */
+  public static $description = 'A base loader for all Tripal loaders';
+
+  /**
+   * An array containing the extensions of allowed file types.
+   */
+  public static $file_types = array();
+
+
+  /**
+   * Provides information to the user about the file upload.  Typically this
+   * may include a description of the file types allowed.
+   */
+  public static $upload_description = '';
+
+  /**
+   * The title that should appear above the upload button.
+   */
+  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;
+
+  /**
+   * Text that should appear on the button at the bottom of the importer
+   * form.
+   */
+  public static $button_text = 'Import File';
+
+  /**
+   * Indicates the methods that the file uploader will support.
+   */
+  public static $methods = array(
+    // Allow the user to upload a file to the server.
+    'file_upload' => TRUE,
+    // Allow the user to provide the path on the Tripal server for the file.
+    'file_local' => TRUE,
+    // Allow the user to provide a remote URL for the file.
+    'file_remote' => TRUE,
+  );
+
+  /**
+   * Indicates if the file must be provided.  An example when it may not be
+   * necessary to require that the user provide a file for uploading if the
+   * loader keeps track of previous files and makes those available for
+   * selection.
+   */
+  public static $file_required = TRUE;
+
+
+  /**
+   * The array of arguments used for this loader.  Each argument should
+   * be a separate array containing a machine_name, name, and description
+   * keys.  This information is used to build the help text for the loader.
+   */
+  public static $argument_list = array();
+
+  // --------------------------------------------------------------------------
+  //                  PRIVATE MEMBERS -- DO NOT EDIT or OVERRIDE
+  // --------------------------------------------------------------------------
+
+  /**
+   * 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;
+
+  /**
+   * The number of items that have been handled so far.  This must never
+   * be below 0 and never exceed $total_items;
+   */
+  private $num_handled;
+
+  /**
+   * 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;
+
+  /**
+   * 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;
+
+  /**
+   * The job that this importer is associated with.  This is needed for
+   * updating the status of the job.
+   */
+  protected $job;
+
+  /**
+   * The arguments needed for the importer. This is a list of key/value
+   * pairs in an associative array.
+   */
+  protected $arguments;
+
+  /**
+   * The ID for this import record.
+   */
+  protected $import_id;
+
+  /**
+   * Prior to running an importer it must be prepared to make sure the file
+   * is available.  Preparing the importer will download all the necessary
+   * files.  This value is set to TRUE after the importer is prepared for
+   * funning.
+   */
+  protected $is_prepared;
+
+
+
+  // --------------------------------------------------------------------------
+  //                          CONSTRUCTORS
+  // --------------------------------------------------------------------------
+  /**
+   * Instantiates a new TripalImporter object.
+   *
+   * @param TripalJob $job
+   *   An optional TripalJob object that this loader is associated with.
+   */
+  public function __construct(TripalJob $job = NULL) {
+
+    // Intialize the private member variables.
+    $this->is_prepared = FALSE;
+    $this->import_id = NULL;
+    $this->arguments = array();
+    $this->job = NULL;
+    $this->total_items = 0;
+    $this->interval = 1;
+    $this->num_handled = 0;
+    $this->prev_update = 0;
+  }
+
+  /**
+   * Instantiates a new TripalImporter object using the import record ID.
+   *
+   * This function will automatically instantiate the correct TripalImporter
+   * child class that is appropriate for the provided ID.
+   *
+   * @param $import_id
+   *   The ID of the import recrod.
+   * @return
+   *   An TripalImporter object of the appropriate child class.
+   */
+  static public function byID($import_id) {
+    // Get the importer.
+    $import = db_select('tripal_import', 'ti')
+      ->fields('ti')
+      ->condition('ti.import_id', $import_id)
+      ->execute()
+      ->fetchObject();
+
+    if (!$import) {
+      throw new Exception('Cannot find an importer that matches the given import ID.');
+    }
+
+    $class = $import->class;
+    tripal_load_include_importer_class($class);
+    if (class_exists($class)) {
+      $loader = new $class();
+      $loader->load($import_id);
+      return $loader;
+    }
+    else {
+      throw new Exception('Cannot find the matching class for this import record.');
+    }
+  }
+
+  /**
+   * Associate this importer with the Tripal job that is running it.
+   *
+   * Associating an import with a job will allow the importer to log messages
+   * to the job log.
+   *
+   * @param TripalJob $job
+   *   An instnace of a TripalJob.
+   */
+  public function setJob(TripalJob $job) {
+    $this->job = $job;
+  }
+
+  /**
+   * Creates a new importer record.
+   *
+   * @param $run_args
+   *   An associative array of the arguments needed to run the importer. Each
+   *   importer will have its own defined set of arguments.
+   *
+   * @param $file_details
+   *   An associative array with one of the following keys:
+   *   -fid: provides the Drupal managed File ID for the file.
+   *   -file_local: provides the full path to the file on the server.
+   *   -file_remote: provides the remote URL for the file.
+   *   This argument is optional if the loader does not use the built-in
+   *   file loader.
+   *
+   * @throws Exception
+   */
+  public function create($run_args, $file_details = array()) {
+    global $user;
+    $class = get_called_class();
+
+    try {
+      // Build the values for the tripal_importer table insert.
+      $values = array(
+        'uid' => $user->uid,
+        'class' => $class,
+        'submit_date' => time(),
+      );
+
+      // Build the arguments array, which consists of the run arguments
+      // and the file.
+      $arguments = array(
+        'run_args' => $run_args,
+        'file' => array(
+          'file_path' => '',
+          'file_local' => '',
+          'file_remote' => '',
+          'fid' => NULL,
+        ),
+      );
+
+      // Get the file argument.
+      $has_file = 0;
+      if (array_key_exists('file_local', $file_details)) {
+        $arguments['file']['file_local'] = $file_details['file_local'];
+        $arguments['file']['file_path'] = $file_details['file_local'];
+        $has_file++;
+      }
+      if (array_key_exists('file_remote', $file_details)) {
+        $arguments['file']['file_remote'] = $file_details['file_remote'];
+        $has_file++;
+      }
+      if (array_key_exists('fid', $file_details)) {
+        $fid = $file_details['fid'];
+        $file = file_load($fid);
+        $arguments['file']['file_path'] =  base_path() . drupal_realpath($file->uri);
+        $arguments['file']['fid'] = $fid;
+        $values['fid'] = $fid;
+        $has_file++;
+      }
+
+      // Validate the $file_details argument.
+      if ($has_file == 0 and $class::$file_required == TRUE) {
+        throw new Exception("Must provide a proper file identifier for the \$file_details argument.");
+      }
+
+      // Store the arguments in the class and serialize for table insertion.
+      $this->arguments = $arguments;
+      $values['arguments'] = serialize($arguments);
+
+      // Insert the importer record.
+      $import_id = db_insert('tripal_import')
+        ->fields($values)
+        ->execute();
+
+      $this->import_id = $import_id;
+    }
+    catch (Exception $e){
+      throw new Exception('Cannot create importer: ' .  $e->getMessage());
+    }
+  }
+
+  /**
+   * Loads an existing import record into this object.
+   *
+   * @param $import_id
+   *   The ID of the import record.
+   */
+  public function load($import_id) {
+    $class = get_called_class();
+
+    // Get the importer.
+    $import = db_select('tripal_import', 'ti')
+      ->fields('ti')
+      ->condition('ti.import_id', $import_id)
+      ->execute()
+      ->fetchObject();
+
+    if (!$import) {
+      throw new Exception('Cannot find an importer that matches the given import ID.');
+    }
+
+    if ($import->class != $class) {
+      throw new Exception('The importer specified by the given ID does not match this importer class.');
+    }
+
+    $this->arguments = unserialize($import->arguments);
+    $this->import_id = $import_id;
+
+  }
+
+
+  /**
+   * Submits the importer for execution as a job.
+   *
+   * @return
+   *   The ID of the newly submitted job.
+   */
+  public function submitJob() {
+    global $user;
+
+    $class = get_called_class();
+
+    if (!$this->import_id) {
+      throw new Exception('Cannot submit an importer job without an import record. Please run create() first.');
+    }
+
+    // Add a job to run the importer.
+    try {
+      $args = array($this->import_id);
+      $includes = array(
+        module_load_include('inc', 'tripal', 'api/tripal.importer.api'),
+      );
+      $job_id = tripal_add_job($class::$button_text, 'tripal',
+          'tripal_run_importer', $args, $user->uid, 10, $includes);
+
+      return $job_id;
+    }
+    catch (Exception $e){
+      throw new Exception('Cannot create importer job: ' .  $e->getMessage());
+    }
+  }
+
+  /**
+   * Prepares the importer files for execution.
+   *
+   * This function must be run prior to the run() function to ensure that
+   * the import file is ready to go.
+   */
+  public function prepareFile() {
+    $class = get_called_class();
+
+    // If no file is required then just indicate that all is good to go.
+    if ($class::$file_required == FALSE) {
+      $this->is_prepared = TRUE;
+      return;
+    }
+
+    try {
+      if (!empty($this->arguments['file']['file_remote'])) {
+        $file_remote = $this->arguments['file']['file_remote'];
+        $this->logMessage('Download file: !file_remote...', array('!file_remote' => $file_remote));
+
+        // Create a temporary file.
+        $temp = tempnam("temporary://", 'import_');
+        $url_fh = fopen($file_remote, "r");
+        $tmp_fh = fopen($temp, "w");
+        if (!$url_fh) {
+          throw new Exception(t("Unable to download the remote file at %url. Could a firewall be blocking outgoing connections?",
+              array('%url', $file_remote)));
+        }
+
+        // Write the contents of the remote file to the temp file.
+        while (!feof($url_fh)) {
+          fwrite($tmp_fh, fread($url_fh, 255), 255);
+        }
+
+        // Set the path to the file for the importer to use.
+        $this->arguments['file']['file_path'] = $temp;
+        $this->is_prepared = TRUE;
+      }
+    }
+    catch (Exception $e){
+      throw new Exception('Cannot prepare the importer: ' .  $e->getMessage());
+    }
+  }
+
+  /**
+   * Cleans up any temporary files that were created by the prepareFile().
+   *
+   * This function should be called after a run() to remove any temporary
+   * files and keep them from building up on the server.
+   */
+  public function cleanFile() {
+    try {
+      // If a remote file was downloaded then remove it.
+      if (!empty($this->arguments['file']['file_remote']) and
+          file_exists($this->arguments['file']['file_path'])) {
+        $this->logMessage('Removing downloaded file...');
+        unlink($this->arguments['file']['file_path']);
+        $this->is_prepared = FALSE;
+      }
+    }
+    catch (Exception $e){
+      throw new Exception('Cannot prepare the importer: ' .  $e->getMessage());
+    }
+  }
+
+  // --------------------------------------------------------------------------
+  //                     OVERRIDEABLE FUNCTIONS
+  // --------------------------------------------------------------------------
+
+  /**
+   * Provides form elements to be added to the loader form.
+   *
+   * These form elements are added after the file uploader section that
+   * is automaticaly provided by the TripalImporter.
+   *
+   * @return
+   *   A $form array.
+   */
+  public function form($form, &$form_state) {
+    return $form;
+  }
+
+  /**
+   * Handles submission of the form elements.
+   *
+   * The form elements provided in the implementation of the form() function
+   * can be used for special submit if needed.
+   */
+  public function formSubmit($form, &$form_state) {
+
+  }
+
+  /**
+   * Handles validation of the form elements.
+   *
+   * The form elements provided in the implementation of the form() function
+   * should be validated using this function.
+   */
+  public function formValidate($form, &$form_state) {
+
+  }
+
+  /**
+   * Performs the import.
+   */
+  public function run() {
+  }
+
+  /**
+   * 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.
+   */
+  public function logMessage($message, $variables = array(), $severity = TRIPAL_INFO) {
+    // Generate a translated message.
+    $tmessage = t($message, $variables);
+
+
+    // 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) {
+    $items_handled = $this->num_handled = $this->num_handled + $num_handled;
+    $this->setItemsHandled($items_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;
+
+    if ($total_handled == 0) {
+      $memory = number_format(memory_get_usage());
+      print "Percent complete: 0%. Memory: " . $memory . " bytes.\r";
+      return;
+    }
+
+    // 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 >= $this->interval) {
+
+      $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);
+      }
+
+      $this->prev_update = $diff;
+    }
+  }
+
+  /**
+   * 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;
+  }
+}

+ 472 - 0
tripal/includes/TripalJob.inc

@@ -0,0 +1,472 @@
+<?php
+
+class TripalJob {
+
+  /**
+   * The ID of the job.
+   */
+  private $job_id = NULL;
+
+  /**
+   * Contains the job record for this job.
+   */
+  private $job = NULL;
+
+  /**
+   * Instantiates a new TripalJob object.
+   *
+   * 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() {
+  }
+
+  /**
+   * 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() {
+
+    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;
+  }
+
+  /**
+   * 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.
+   *
+   * 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
+   *   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.
+   */
+  public 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";
+
+    // 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);
+        $this->job->status = 'Error';
+    }
+  }
+}

+ 4 - 2
tripal/includes/tripal.entity.inc

@@ -328,11 +328,13 @@ function tripal_entity_view($entity, $type, $view_mode, $langcode) {
       // the field.
       $instance = field_info_instance('TripalEntity', $child_name, $entity->bundle);
       if ($instance and array_key_exists('settings', $instance)) {
+        $class = '';
         if (array_key_exists('auto_attach', $instance['settings']) and
             $instance['settings']['auto_attach'] == FALSE) {
-          $entity->content[$child_name]['#prefix'] .= '<div id="tripal-entity-' . $entity->id . '--' . $child_name . '" class="tripal-entity-unattached">';
-          $entity->content[$child_name]['#suffix'] .= '</div>';
+          $class = 'class="tripal-entity-unattached"';
         }
+        $entity->content[$child_name]['#prefix'] .= '<div id="tripal-entity-' . $entity->id . '--' . $child_name . '" ' . $class . '>';
+        $entity->content[$child_name]['#suffix'] .= '</div>';
       }
     }
   }

+ 1 - 2
tripal/includes/tripal.field_storage.inc

@@ -22,8 +22,7 @@ function tripal_field_storage_info() {
 /**
  * Implements hook_field_storage_load().
  *
- * Responsible for loading the fields from the Chado database and adding
- * their values to the entity.
+ * Responsible for loading the fields and adding their values to the entity.
  */
 function tripal_field_storage_load($entity_type, $entities, $age,
     $fields, $options) {

+ 1 - 1
tripal/includes/tripal.fields.inc

@@ -358,7 +358,7 @@ function tripal_form_field_ui_field_overview_form_submit($form, &$form_state) {
         // Unset the the _add_new_field entry so Drupal doesn't try to
         // Create the field.
         unset($form_state['values']['fields']['_add_new_field']);
-        drupal_set_message('Please set the controlled vocabulary that best describes the data of this field. See the "Controlled Vocabulary Term" section below.', 'notice');
+        drupal_set_message('Please set the controlled vocabulary that best describes the data of this field. See the "Controlled Vocabulary Term" section below.', 'warning');
       }
     }
     catch (Exception $e) {

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

@@ -0,0 +1,211 @@
+<?php
+
+
+/**
+ * Build the form for a TripalImporter implementation.
+ */
+function tripal_get_importer_form($form, &$form_state, $class) {
+
+  tripal_load_include_importer_class($class);
+
+  $form['importer_class'] = array(
+    '#type' => 'value',
+    '#value' => $class,
+  );
+
+  if ((array_key_exists('file_upload', $class::$methods) and $class::$methods['file_upload'] == TRUE) or
+      (array_key_exists('file_local', $class::$methods) and $class::$methods['file_local'] == TRUE) or
+      (array_key_exists('file_remote', $class::$methods) and $class::$methods['file_remote'] == TRUE)) {
+    $form['file'] = array(
+      '#type' => 'fieldset',
+      '#title' => t($class::$upload_title),
+      '#description' => t($class::$upload_description)
+    );
+  }
+
+  if (array_key_exists('file_upload', $class::$methods) and $class::$methods['file_upload'] == TRUE) {
+    $form['file']['file_upload']= array(
+      '#type' => 'html5_file',
+      '#title' => '',
+      '#description' => 'Remember to click the "Upload" button below to send ' .
+        'your file to the server.  This interface is capable of uploading very ' .
+        'large files.  If you are disconnected you can return, reload the file and it ' .
+        'will resume where it left off.  Once the file is uploaded the "Upload '.
+        'Progress" will indicate "Complete".  If the file is already present on the server ' .
+        'then the status will quickly update to "Complete".',
+      '#usage_type' => 'tripal_importer',
+      '#usage_id' => 0,
+    );
+  }
+
+  if (array_key_exists('file_local', $class::$methods) and $class::$methods['file_local'] == TRUE) {
+    $form['file']['file_local']= array(
+      '#title' => t('Server path'),
+      '#type' => 'textfield',
+      '#maxlength' => 5120,
+      '#description'  => t('If the file is local to the Tripal server please provide the full path here.'),
+    );
+  }
+  if (array_key_exists('file_remote', $class::$methods) and $class::$methods['file_remote'] == TRUE) {
+    $form['file']['file_remote']= array(
+      '#title' => t('Remote path'),
+      '#type' => 'textfield',
+      '#maxlength' => 5102,
+      '#description'  => t('If the file is available via a remote URL please provide the full URL here.  The file will be downloaded when the importer job is executed.'),
+    );
+  }
+
+  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();
+  $element = array();
+  $form['class_elements'] = $importer->form($element, $form_state);
+
+  $form['button'] = array(
+    '#type' => 'submit',
+    '#value' => t($class::$button_text),
+    '#weight' => 10,
+  );
+  return $form;
+}
+
+/**
+ * Validate function for the tripal_get_importer_form form().
+ */
+function tripal_get_importer_form_validate($form, &$form_state) {
+
+  $class = $form_state['values']['importer_class'];
+  tripal_load_include_importer_class($class);
+
+  $file_local = NULL;
+  $file_upload = NULL;
+  $file_remote = NULL;
+
+  // Get the form values for the file.
+  if (array_key_exists('file_local', $class::$methods) and $class::$methods['file_local'] == TRUE) {
+    $file_local = trim($form_state['values']['file_local']);
+    // If the file is local make sure it exists on the local filesystem.
+    if ($file_local) {
+      // check to see if the file is located local to Drupal
+      $file_local = trim($file_local);
+      $dfile = $_SERVER['DOCUMENT_ROOT'] . base_path() . $file_local;
+      if (!file_exists($dfile)) {
+        // if not local to Drupal, the file must be someplace else, just use
+        // the full path provided
+        $dfile = $file_local;
+      }
+      if (!file_exists($dfile)) {
+        form_set_error('file_local', t("Cannot find the file on the system. Check that the file exists or that the web server has permissions to read the file."));
+      }
+    }
+  }
+  if (array_key_exists('file_upload', $class::$methods) and $class::$methods['file_upload'] == TRUE) {
+    $file_upload = trim($form_state['values']['file_upload']);
+  }
+  if (array_key_exists('file_remote', $class::$methods) and $class::$methods['file_remote'] == TRUE) {
+    $file_remote = trim($form_state['values']['file_remote']);
+  }
+
+
+
+  // The user must provide at least an uploaded file or a local file path.
+  if ($class::$file_required == TRUE and !$file_upload and !$file_local and !$file_remote) {
+    form_set_error('file_local', t("You must provide a file."));
+  }
+
+  // Now allow the loader to do validation of it's form additions.
+  $importer = new $class();
+  $importer->formValidate($form, $form_state);
+}
+
+/**
+ * Submit function for the tripal_get_importer_form form().
+ */
+function tripal_get_importer_form_submit($form, &$form_state) {
+  global $user;
+
+  $run_args = $form_state['values'];
+  $class = $form_state['values']['importer_class'];
+  tripal_load_include_importer_class($class);
+
+  // Remove the file_local and file_upload args. We'll add in a new
+  // full file path and the fid instead.
+  unset($run_args['file_local']);
+  unset($run_args['file_upload']);
+  unset($run_args['form_build_id']);
+  unset($run_args['form_token']);
+  unset($run_args['form_id']);
+  unset($run_args['op']);
+  unset($run_args['button']);
+
+
+  $file_local = NULL;
+  $file_upload = NULL;
+  $file_remote = NULL;
+
+  // Get the form values for the file.
+  if (array_key_exists('file_local', $class::$methods) and $class::$methods['file_local'] == TRUE) {
+    $file_local = trim($form_state['values']['file_local']);
+  }
+  if (array_key_exists('file_upload', $class::$methods) and $class::$methods['file_upload'] == TRUE) {
+    $file_upload = trim($form_state['values']['file_upload']);
+  }
+  if (array_key_exists('file_remote', $class::$methods) and $class::$methods['file_remote'] == TRUE) {
+    $file_remote = trim($form_state['values']['file_remote']);
+  }
+
+  // Sumbit a job for this loader.
+  $fname = '';
+  $fid = NULL;
+  $file_details = array();
+  if ($file_local) {
+    $fname = preg_replace("/.*\/(.*)/", "$1", $file_local);
+    $file_details['file_local'] = $file_local;
+  }
+  if ($file_upload) {
+    $file_details['fid'] = $file_upload;
+  }
+  if ($file_remote) {
+    $file_details['file_remote'] = $file_remote;
+  }
+  try {
+
+    // Now allow the loader to do it's own submit if needed.
+    $importer = new $class();
+    $importer->formSubmit($form, $form_state);
+
+    // If the importer wants to rebuild the form for some reason then let's
+    // not add a job.
+    if (array_key_exists('rebuild', $form_state) and $form_state['rebuild'] == TRUE) {
+      return;
+    }
+
+    $importer->create($run_args, $file_details);
+    $importer->submitJob();
+
+  }
+  catch (Exception $e) {
+    drupal_set_message('Cannot submit import: ' . $e->getMessage(), 'error');
+  }
+}

+ 2 - 2
tripal/includes/tripal.upload.inc

@@ -136,12 +136,12 @@ function tripal_file_upload_merge($filename, $type, $user_dir) {
       }
       else {
         $status = 'failed';
-        $message = 'Could not add file to GenSAS database.';
+        $message = 'Could not add file to the database.';
       }
     }
     else {
       $status = 'failed';
-      $message = 'Requesting module does not implement hook_handle_uploaded_file.';
+      $message = 'Cannot find the function: ' . $function . '().';
     }
   }
 

+ 0 - 1
tripal/includes/tripal_admin_usage_page.inc

@@ -12,7 +12,6 @@ function tripal_admin_usage_page() {
   $breadcrumb[] = l('Tripal', 'admin/tripal');
   drupal_set_breadcrumb($breadcrumb);
   tripal_add_d3js();
-  //drupal_add_js(drupal_get_path ('module', 'tripal') . '/theme/js/tripal_galaxy.dashboard.js');
   drupal_add_css(drupal_get_path ('module', 'tripal') . '/theme/css/tripal.dashboard.css');
   drupal_add_library('system', 'drupal.collapse');
   $output = '<h2>Tripal Administrative Notifications and Info</h2>';

+ 2 - 4
tripal/theme/css/tripal.css

@@ -72,9 +72,7 @@ div.messages.tripal-site-admin-only{
 /******************************************************************************
  * Spinner for paginated elements
  *****************************************************************************/
- #spinner {
-   position: absolute;
+ .tripal-field-ajax-spinner {
    display: none;
-   left: 24%;
-   bottom: 7%;
+   float: left;
  }

+ 3 - 2
tripal/theme/js/TripalUploadFile.js

@@ -122,7 +122,8 @@
             self.updateProgressBar();
           }
         },
-        error : function() {
+        error : function(jqXHR, textStatus, errorThrown) {
+          alert(errorThrown);
           self.curr_chunk = 0;
           self._upload();
         }
@@ -447,4 +448,4 @@
   // Export the objects to the window for use in other JS files.
   window.TripalUploadFile = TripalUploadFile;
   
-})(jQuery);
+})(jQuery);

+ 1 - 1
tripal/theme/js/TripalUploader.js

@@ -559,7 +559,7 @@
               // by their index. The file with an index of 0 is always ordered first.
               'i': index,
               // The URL at the remote server where the file will uploaded. 
-              'url' : '/tripal/upload/' + category,
+              'url' : baseurl + '/tripal/upload/' + category,
             };
             self.addFile(f, options);
 

+ 20 - 0
tripal/theme/js/tripal.file.js

@@ -0,0 +1,20 @@
+(function($) {
+  Drupal.behaviors.TripalFile = {
+    attach: function (context, settings) {
+
+      var tripal_files = new TripalUploader();
+      
+      $(".tripal-html5-file-upload-table-key").each(function(index) {
+        var form_key = $(this).val()
+        tripal_files.addUploadTable(form_key, {
+          'table_id' : '#tripal-html5-file-upload-table-' + form_key,
+          'submit_id': '#tripal-html5-file-upload-submit-' + form_key,
+          'category' : [form_key],
+          'cardinality' : 1,
+          'target_id' : 'tripal-html5-upload-fid-' + form_key,
+          'module' : 'tripal',
+        });
+      });
+    }
+  }
+}) (jQuery);

+ 8 - 7
tripal/theme/js/tripal.js

@@ -23,14 +23,15 @@
 
 })(jQuery);
 
+// Used for ajax update of fields by links in a pager.
 function tripal_navigate_field_pager(id, page) {
-    jQuery(document).ajaxStart(function () {
-        jQuery('#spinner').show();
-    }).ajaxComplete(function () {
-        jQuery('#spinner').hide();
-    });
+  jQuery(document).ajaxStart(function () {
+    jQuery('#' + id + '-spinner').show();
+  }).ajaxComplete(function () {
+    jQuery('#' + id + '-spinner').hide();
+  });
 
-    jQuery.ajax({
+  jQuery.ajax({
     type: "GET",
     url: Drupal.settings["basePath"] + "bio_data/ajax/field_attach/" + id,
     data: { 'page' : page },
@@ -38,4 +39,4 @@ function tripal_navigate_field_pager(id, page) {
       jQuery("#" + id + ' .field-items').replaceWith(response['content']);
     }
   });
-}
+}

+ 108 - 48
tripal/tripal.install

@@ -188,6 +188,7 @@ function tripal_schema() {
   $schema['tripal_term'] = tripal_tripal_term_schema();
   $schema['tripal_entity'] = tripal_tripal_entity_schema();
   $schema['tripal_bundle'] = tripal_tripal_bundle_schema();
+  $schema['tripal_import'] = tripal_tripal_import_schema();
 
   // Adds a table for additional information related to bundles.
   $schema['tripal_bundle_variables'] = tripal_tripal_bundle_variables_schema();
@@ -195,6 +196,9 @@ function tripal_schema() {
   $schema['tripal_admin_notfications'] = tripal_tripal_admin_notifications_schema();
   return $schema;
 }
+/**
+ * Returns the Drupal Schema API array for the tripal_jobs table.
+ */
 function tripal_tripal_jobs_schema() {
   return array(
     'fields' => array(
@@ -300,6 +304,72 @@ function tripal_tripal_jobs_schema() {
     'primary key' => array('job_id'),
   );
 }
+/**
+ * Returns the Drupal Schema API array for the tripal_jobs table.
+ */
+function tripal_tripal_import_schema() {
+  return array(
+    'fields' => array(
+      'import_id' => array(
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE
+      ),
+      'uid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'description' => 'The Drupal userid of the submitee.'
+      ),
+      'class' => array(
+        'type' => 'varchar',
+        'length' => 256,
+        'not null' => TRUE,
+      ),
+      'fid' => array(
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => FALSE,
+        'description' => 'The file ID of the file to import. This only applies if the file was uploaded (i.e. not already on the server) and is mangaged by Drupal.'
+      ),
+      'arguments' => array(
+        'type' => 'text',
+        'size' => 'normal',
+        'not null' => FALSE,
+        'description' => 'Holds a serialized PHP array containing the key/value paris that are used for arguments of the job.'
+      ),
+      'submit_date' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'description' => 'UNIX integer submit time'
+      ),
+    ),
+    'indexes' => array(
+      'class' => array('class'),
+    ),
+    'foreign keys' => array(
+      'tripal_jobs' => array(
+        'table' => 'tripal_jobs',
+        'columns' => array(
+          'job_id' => 'job_id',
+        ),
+      ),
+      'users' => array(
+        'table' => 'users',
+        'columns' => array(
+          'uid' => 'uid',
+        ),
+      ),
+      'file_managed' => array(
+        'table' => 'file_managed',
+        'columns' => array(
+          'fid' => 'fid',
+        ),
+      ),
+    ),
+    'primary key' => array('import_id'),
+  );
+}
 /**
  *
  * @return
@@ -771,7 +841,7 @@ function tripal_update_7300() {
       'not null' => TRUE
     );
     db_change_field('tripal_vocab', 'vocabulary', 'vocabulary',$spec);
-  } 
+  }
   catch (\PDOException $e) {
     $error = $e->getMessage();
     throw new DrupalUpdateException('Could not perform update: '. $error);
@@ -784,55 +854,45 @@ function tripal_update_7300() {
 function tripal_update_7301() {
   $transaction = db_transaction();
   try {
-    $schema['tripal_admin_notfications'] = array(
-      'description' => 'This table is used for information describing administrative
-       notifications. For example, when new fields are available.',
-      'fields' => array (
-        'note_id' => array (
-          'type' => 'serial',
-          'not null' => TRUE,
-        ),
-        'details' => array (
-          'description' => 'Description and additional information relating to the notification.',
-          'type' => 'text',
-          'not null' => TRUE,
-        ),
-        'title' => array (
-          'description' => 'Title of the notification.',
-          'type' => 'text',
-          'not null' => TRUE,
-        ),
-        'actions' => array (
-          'description' => 'Actions that can be performed on the notification, like disimissal or import.',
-          'type' => 'text',
-          'not null' => FALSE,
-        ),
-        'submitter_id' => array (
-          'description' => 'A unique id that should be specific to the notification to ensure notifications are not duplicated.',
-          'type' => 'text',
-          'not null' => TRUE,
-        ),
-        'enabled' => array (
-          'description' => 'Boolean indicating whether the notification is enabled or disabled (disabled will not be shown on the dashboard).',
-          'type' => 'int',
-          'not null' => TRUE,
-          'default' => 1,
-        ),
-        'type' => array (
-          'description' => 'Type of the notification, relating to what tripal function the notification belongs to, IE Fields, Jobs, Vocabulary.',
-          'type' => 'text',
-          'not null' => FALSE,
-        ),
-      ),
-        'primary key' => array (
-          0 => 'note_id',
-        ),
-    );
+    $schema['tripal_admin_notfications'] = tripal_tripal_admin_notifications_schema();
     db_create_table('tripal_admin_notfications', $schema['tripal_admin_notfications']);
   }
   catch (\PDOException $e) {
-      $transaction->rollback();
-      $error = $e->getMessage();
-      throw new DrupalUpdateException('Could not perform update: '. $error);
+    $transaction->rollback();
+    $error = $e->getMessage();
+    throw new DrupalUpdateException('Could not perform update: '. $error);
   }
 }
+
+/**
+ * Create new tripal import table.
+ */
+function tripal_update_7302() {
+  $transaction = db_transaction();
+  try {
+    $schema['tripal_import'] = tripal_tripal_import_schema();
+    db_create_table('tripal_import', $schema['tripal_import']);
+  }
+  catch (\PDOException $e) {
+    $transaction->rollback();
+    $error = $e->getMessage();
+    throw new DrupalUpdateException('Could not perform update: '. $error);
+  }
+}
+
+/**
+ * Remove the job_id from the tripal import table.
+ */
+function tripal_update_7303() {
+  $transaction = db_transaction();
+  try {
+    if (db_field_exists('tripal_import', 'job_id')) {
+      db_drop_field('tripal_import', 'job_id');
+    }
+  }
+  catch (\PDOException $e) {
+    $transaction->rollback();
+    $error = $e->getMessage();
+    throw new DrupalUpdateException('Could not perform update: '. $error);
+  }
+}

+ 212 - 27
tripal/tripal.module

@@ -29,6 +29,8 @@ require_once "includes/TripalFields/TripalField.inc";
 require_once "includes/TripalFields/TripalFieldWidget.inc";
 require_once "includes/TripalFields/TripalFieldFormatter.inc";
 require_once "includes/TripalFieldQuery.inc";
+require_once "includes/TripalJob.inc";
+require_once "includes/TripalImporter.inc";
 
 /**
  * @defgroup tripal Tripal Core Module
@@ -108,17 +110,6 @@ function tripal_menu() {
     'access arguments' => array('administer tripal'),
   );
 
-  $items['admin/tripal/terms'] = array(
-    'title' => 'Vocabularies',
-    'description' => t("Vocabulary terms are essential to creating content
-        in Tripal. This allows data to be shared more easily with others
-        using technologies such as the semantic web and web services.
-        Before creating content you must have loaded vocabularies and their
-        terms."),
-    'weight' => 8,
-    'access arguments' => array('administer tripal'),
-  );
-
   $items['admin/tripal/dashboard'] = array(
     'title' => 'Dashboard',
     'description' => t("A dashboard view of Tripal including new fields for entities."),
@@ -130,16 +121,16 @@ function tripal_menu() {
     'file path' => drupal_get_path('module', 'tripal'),
   );
 
-  $items['admin/tripal/terms/import'] = array(
-    'title' => 'Import Vocabulary',
-    'description' => t("Import vocabularies and terms in OBO format."),
-    'access arguments' => array('administer tripal'),
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('tripal_vocabulary_import_form'),
-    'file' => 'includes/tripal.admin.inc',
-    'file path' => drupal_get_path('module', 'tripal'),
-    'type' => MENU_NORMAL_ITEM,
-  );
+//   $items['admin/tripal/loaders/obo_loader'] = array(
+//     'title' => 'OBO Controlled Vocabulary Loader',
+//     'description' => t("Import vocabularies and terms in OBO format."),
+//     'access arguments' => array('administer tripal'),
+//     'page callback' => 'drupal_get_form',
+//     'page arguments' => array('tripal_vocabulary_import_form'),
+//     'file' => 'includes/tripal.admin.inc',
+//     'file path' => drupal_get_path('module', 'tripal'),
+//     'type' => MENU_NORMAL_ITEM,
+//   );
 
   $items['admin/tripal/extension'] = array(
     'title' => 'Extensions',
@@ -325,6 +316,25 @@ function tripal_menu() {
     'type' => MENU_CALLBACK,
   );
 
+
+  // Add in the loaders
+  $importers = tripal_get_importers();
+  foreach ($importers as $class_name) {
+    tripal_load_include_importer_class($class_name);
+    if (class_exists($class_name)) {
+      $items['admin/tripal/loaders/' . $class_name::$machine_name] = array(
+        'title' => $class_name::$name,
+        'description' =>  $class_name::$description,
+        'page callback' => 'drupal_get_form',
+        'page arguments' => array('tripal_get_importer_form', $class_name),
+        'access arguments' => array('administer tripal'),
+        'type' => MENU_NORMAL_ITEM,
+        'file' => 'includes/tripal.importer.inc',
+        'file path' => drupal_get_path('module', 'tripal'),
+      );
+    }
+  }
+
   return $items;
 }
 
@@ -348,6 +358,10 @@ function tripal_permission() {
       'description' => t('Allows the user to create, update and delete Tripal content types.'),
       'restrict access' => TRUE,
     ),
+    'upload files' => array(
+      'title' => t('Upload Files'),
+      'description' => t('Allows the user to upload files using Tripal\'s HTML5 loader.'),
+    ),
     'view dev helps' => array(
       'title' => t('View Developer Hints'),
       'description' => t('Tripal will provide blue shaded boxes that provide
@@ -610,6 +624,7 @@ function TripalEntity_load($id, $reset = FALSE) {
 function tripal_import_api() {
   module_load_include('inc', 'tripal', 'api/tripal.d3js.api');
   module_load_include('inc', 'tripal', 'api/tripal.fields.api');
+  module_load_include('inc', 'tripal', 'api/tripal.importer.api');
   module_load_include('inc', 'tripal', 'api/tripal.terms.api');
   module_load_include('inc', 'tripal', 'api/tripal.entities.api');
   module_load_include('inc', 'tripal', 'api/tripal.files.api');
@@ -791,12 +806,12 @@ function tripal_block_configure ($delta = '') {
   switch ($delta) {
     case 'powered_by_tripal':
       $form['logo_size'] = array(
-      '#type' => 'radios',
-      '#title' => t('Logo Size'),
-      '#default_value' => variable_get('powered_by_tripal_size', 'small'),
-      '#options' => array(
-      'large' => t('Large'),
-      'small' => t('Small')
+        '#type' => 'radios',
+        '#title' => t('Logo Size'),
+        '#default_value' => variable_get('powered_by_tripal_size', 'small'),
+        '#options' => array(
+        'large' => t('Large'),
+        'small' => t('Small')
       ),
       '#description' => t('Select if you would like a small or large "Powered by Tripal" logo.'),
       );
@@ -814,4 +829,174 @@ function tripal_block_configure ($delta = '') {
 
 
   return $form;
+}
+
+/**
+ * Implements hook_cron().
+ */
+function tripal_cron() {
+  if (variable_get('tripal_admin_notification_creation_during_cron', TRUE)) {
+    $modules = module_implements('tripal_cron_notification');
+    foreach ($modules as $module) {
+      $function = $module . '_tripal_cron_notification';
+      $function();
+    }
+    watchdog('tripal_cron', 'tripal_cron ran');
+  }
+}
+
+/**
+ * Implements hook_element_info().
+ *
+ * Used for creating new form API elements.
+ */
+function tripal_element_info() {
+
+  // Element for uploading large files.  This form element
+  // accepts the following keys when using in a form:
+  //   - #title:  The title that will appear above the element.
+  //   - #description:  The description that will appear below the element.
+  //   - #usage_type:  Required.  The type of file.  This will be stored in
+  //     the 'type' column of the file_usage table.
+  //   - #usage_id: Required. A unique numeric ID representing an entity, node
+  //     or some other record identifier.  This can be any identifier that
+  //     makes sense to the module that implements a form that uses this
+  //     element.
+  $elements['html5_file'] = array(
+    '#input' => 'TRUE',
+    '#process' => array('tripal_html5_file_process'),
+    '#element_validate' => array('tripal_html5_file_validate'),
+    '#value_callback' => 'tripal_html5_file_value',
+  );
+  return $elements;
+}
+
+/**
+ *  The process function for the html5_file form element.
+ */
+function tripal_html5_file_process($element, $form_state, $complete_form) {
+
+  $type = $element['#usage_id'] . '-' . $element['#usage_type'];
+  $name = $element['#name'];
+  $name = preg_replace('/[^\w]/', '_', $name);
+
+  $headers = array(
+    array('data' => 'File'),
+    array('data' => 'Size', 'width' => '10%'),
+    array('data' => 'Upload Progress', 'width' => '20%'),
+    array('data' => 'Action', 'width' => '10%')
+  );
+  $rows = array();
+  $table_vars = array(
+    'header'      => $headers,
+    'rows'        => $rows,
+    'attributes'  => array(
+      'class' => array('tripal-html5-file-upload-table'),
+      'id' => 'tripal-html5-file-upload-table-' . $type
+    ),
+    'sticky'      => TRUE,
+    'colgroups'   => array(),
+    'empty'       => t('There are currently no files.'),
+  );
+  $element['html5_file_table_key'] = array(
+    '#type' => 'hidden',
+    '#value' => $type,
+    '#attributes' => array(
+      'class' => array('tripal-html5-file-upload-table-key')
+    )
+  );
+  $element['html5_file_table'] = array(
+    '#type' => 'item',
+    '#title' => $element['#title'],
+    '#description' => $element['#description'],
+    '#markup' => theme('table', $table_vars)
+  );
+
+  $element[$name] = array(
+    '#type' => 'hidden',
+    '#attributes' => array('id' => 'tripal-html5-upload-fid-' . $type),
+    '#default_value' => $element['#value'],
+  );
+  $element['html5_file_submit'] = array(
+    '#type'     => 'submit',
+    '#value'    => 'Upload File',
+    '#name' => 'tripal_html5_file_upload_submit-' . $type,
+    // We don't want this button to submit as the file upload
+    // is handled by the JavaScript code.
+    '#attributes' => array(
+      'id' => 'tripal-html5-file-upload-submit-' . $type,
+      'onclick' => 'return (false);'
+    )
+  );
+
+  drupal_add_js(drupal_get_path ('module', 'tripal') . '/theme/js/TripalUploader.js');
+  drupal_add_js(drupal_get_path ('module', 'tripal') . '/theme/js/TripalUploadFile.js');
+  drupal_add_js(drupal_get_path ('module', 'tripal') . '/theme/js/tripal.file.js');
+
+  return $element;
+}
+/**
+ *
+ */
+function tripal_html5_file_validate($element, &$form_state) {
+  $is_required = $element['#required'];
+  $fid = $element['#value'];
+
+  if ($is_required and !$fid) {
+    form_error($element, t('A file must be uploaded.'));
+  }
+}
+
+
+
+/**
+ * Implements hook_handle_uplaoded_file().
+ */
+function tripal_handle_uploaded_file($filename, $filepath, $type) {
+
+  global $user;
+
+  // Split the type into a node ID and form_key
+  list($nid, $form_key) = explode('-', $type);
+
+  // See if this file is already managed then add another entry fin the
+  // usage table.
+  $fid = db_select('file_managed', 'fm')
+  ->fields('fm', array('fid'))
+  ->condition('uri', $filepath)
+  ->execute()
+  ->fetchField();
+  if ($fid) {
+    $file = file_load($fid);
+    file_usage_add($file, 'tripal', $form_key, $nid);
+    return $fid;
+  }
+
+  // Create a file object.
+  $file = new stdClass();
+  $file->uri = $filepath;
+  $file->filename = $filename;
+  $file->filemime = file_get_mimetype($filepath);
+  $file->uid = $user->uid;
+  $file->status = FILE_STATUS_PERMANENT;
+  $file = file_save($file);
+
+  return $file->fid;
+}
+
+/**
+ * Implements hook_value() for the html5_file form element.
+ */
+function tripal_html5_file_value($element, $input = FALSE, &$form_state) {
+
+  if ($input) {
+    if (is_array($input)) {
+      $name = $element['#name'];
+      $name = preg_replace('/[^\w]/', '_', $name);
+      return $input[$name];
+    }
+    else {
+      return $input;
+    }
+  }
 }

+ 3 - 5
tripal/tripal.views.inc

@@ -30,7 +30,7 @@ function tripal_views_data() {
   $data = array();
   // Job Management System
   tripal_views_data_jobs($data);
-  tripal_entity_views_data($data);
+  tripal_views_data_tripal_entity($data);
   tripal_views_data_fields($data);
 
   return $data;
@@ -78,7 +78,7 @@ function tripal_views_data_fields(&$data) {
 /**
  * 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
   // as "base tables" for views.
@@ -122,7 +122,7 @@ function tripal_entity_views_data(&$data) {
  *
  * @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']['base'] = array(
@@ -371,6 +371,4 @@ function tripal_views_data_jobs($data) {
       'handler' => 'views_handler_sort',
     ),
   );
-
-  return $data;
 }

+ 2 - 2
tripal_chado/api/modules/tripal_chado.analysis.api.inc

@@ -174,7 +174,7 @@ function tripal_get_analysis_select_options($syncd_only = TRUE) {
   if ($syncd_only) {
     $sql = "
       SELECT *
-      FROM public.chado_analysis CA
+      FROM [chado_analysis] CA
         INNER JOIN {analysis} A ON A.analysis_id = CO.analysis_id
       ORDER BY A.name
     ";
@@ -196,4 +196,4 @@ function tripal_get_analysis_select_options($syncd_only = TRUE) {
     }
   }
   return $analysis_list;
-}
+}

+ 3 - 1
tripal_chado/api/modules/tripal_chado.cv.api.inc

@@ -432,7 +432,7 @@ function tripal_update_cvtermpath_loop($origin, $child_id, $cv_id, $type_id, $de
   $count =  db_query(
     'SELECT *
      FROM cvtermpath
-     WHERE cv_id = :cvid 
+     WHERE cv_id = :cvid
       AND object_id = :origin
       AND subject_id = :child_id
       AND pathdistance = :depth
@@ -1221,6 +1221,8 @@ function tripal_insert_cvterm($term, $options = array()) {
 }
 
 /**
+ * TODO: deprecate this function
+ *
  * This function allows other modules to programatically
  * submit an ontology for loading into Chado.
  *

+ 36 - 11
tripal_chado/api/tripal_chado.api.inc

@@ -59,6 +59,7 @@ function tripal_chado_publish_records($values, $job_id = NULL) {
   $type_column = $chado_bundle->type_column;
   $type_linker_table = $chado_bundle->type_linker_table;
   $cvterm_id  = $chado_bundle->type_id;
+  $type_value = $chado_bundle->type_value;
 
   // Get the table information for the Chado table.
   $table_schema = chado_get_schema($table);
@@ -66,7 +67,7 @@ function tripal_chado_publish_records($values, $job_id = NULL) {
 
   // Construct the SQL for identifying which records should be published.
   $args = array();
-  $select = "SELECT $pkey_field as record_id ";
+  $select = "SELECT T.$pkey_field as record_id ";
   $from = "
     FROM {" . $table . "} T
       LEFT JOIN public.$chado_entity_table CE on CE.record_id = T.$pkey_field
@@ -80,9 +81,8 @@ function tripal_chado_publish_records($values, $job_id = NULL) {
   }
   $where = " WHERE CE.record_id IS NULL ";
 
-  // Handle bundles that use a linker property table for identifying the type
-  // of record to publish.
-  if ($type_linker_table and $type_column) {
+  // Handle records that are mapped to property tables.
+  if ($type_linker_table and $type_column and $type_value) {
     $propschema = chado_get_schema($type_linker_table);
     $fkeys = $propschema['foreign keys'][$table]['columns'];
     foreach ($fkeys as $leftkey => $rightkey) {
@@ -90,21 +90,46 @@ function tripal_chado_publish_records($values, $job_id = NULL) {
         $from .= " INNER JOIN {" . $type_linker_table . "} LT ON T.$pkey_field = LT.$leftkey ";
       }
     }
+    $where .= "AND LT.$type_column = :cvterm_id and LT.value = :prop_value";
+    $args[':cvterm_id'] = $cvterm_id;
+    $args[':prop_value'] = $type_value;
+  }
+
+  // Handle records that are mapped to cvterm linking tables.
+  if ($type_linker_table and $type_column and !$type_value) {
+    $cvtschema = chado_get_schema($type_linker_table);
+    $fkeys = $cvtschema['foreign keys'][$table]['columns'];
+    foreach ($fkeys as $leftkey => $rightkey) {
+      if ($rightkey == $pkey_field) {
+        $from .= " INNER JOIN {" . $type_linker_table . "} LT ON T.$pkey_field = LT.$leftkey ";
+      }
+    }
     $where .= "AND LT.$type_column = :cvterm_id";
     $args[':cvterm_id'] = $cvterm_id;
   }
 
-  // If the type column is in the base table then add in the SQL for that.
+  // Handle records that are mapped via a type_id column in the base table.
   if (!$type_linker_table and $type_column) {
     $where .= "AND T.$type_column = :cvterm_id";
     $args[':cvterm_id'] = $cvterm_id;
   }
-  // If no type column is specified then we have a problem.
-  if ($type_linker_table and !$type_column) {
-    tripal_report_error('tripal_chado', TRIPAL_ERROR,
-        "Could not publish record: @error",
-        array('@error' => 'The bundle does not properly map to Chado.'));
-    return FALSE;
+
+  // Handle the case where records are in the cvterm table and mapped via a single
+  // vocab.  Here we use the type_value for the cv_id.
+  if ($table == 'cvterm' and $type_value) {
+    $where .= "AND T.cv_id = :cv_id";
+    $args[':cv_id'] = $type_value;
+  }
+
+  // Handle the case where records are in the cvterm table but we want to
+  // use all of the child terms.
+  if ($table == 'cvterm' and !$type_value) {
+    $where .= "AND T.cvterm_id IN (
+       SELECT CVTP.subject_id
+       FROM {cvtermpath} CVTP
+       WHERE CVTP.object_id = :cvterm_id)
+     ";
+    $args[':cvterm_id'] = $cvterm_id;
   }
 
   // Now add in any additional filters

+ 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
     // that may leave parts of the site unfunctional
     $transaction = db_transaction();
+    $previous_db = chado_set_active('chado');  // use chado database
     try {
       $success = chado_query("DELETE FROM {" . $mview->mv_table . "}");
       $success = chado_query("INSERT INTO {" . $mview->mv_table . "} ($mview->query)");
@@ -372,8 +373,10 @@ function tripal_populate_mview($mview_id) {
       else {
         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) {
+      chado_set_active($previous_db);
       $transaction->rollback();
       // print and save the error message
       $record = new stdClass();

+ 25 - 0
tripal_chado/api/tripal_chado.property.api.inc

@@ -627,3 +627,28 @@ function chado_get_record_with_property($record, $property, $options = array())
 
   return $records;
 }
+
+
+/**
+ * Retrieves all of the property types currently availalbe in a prop table.
+ *
+ * @param $prop_table
+ *   The name of the property table.
+ * @throws Exception
+ * @return
+ *   An array of cvterm objects as created by chado_generate_var().
+ */
+function chado_get_table_property_types($prop_table) {
+
+  // Make sure this is a prop table.
+  if (!preg_match('/prop$/', $prop_table)) {
+    throw new Exception('Please provide a valid Chado property table');
+  }
+  $sql = 'SELECT DISTINCT type_id FROM {' . $prop_table . '}';
+  $results = chado_query($sql);
+  $types = array();
+  foreach ($results as $result) {
+    $types[] = chado_generate_var('cvterm', array('cvterm_id' => $result->type_id));
+  }
+  return $types;
+}

+ 3 - 7
tripal_chado/api/tripal_chado.query.api.inc

@@ -969,7 +969,7 @@ function chado_delete_record($table, $match, $options = NULL) {
   $fields = $table_desc['fields'];
   if (empty($table_desc)) {
     tripal_report_error('tripal_chado', TRIPAL_WARNING,
-      'chado_insert_record; There is no table description for !table_name',
+      'chado_delete_record; There is no table description for !table_name',
       array('!table_name' => $table), array('print' => $print_errors)
     );
   }
@@ -1229,8 +1229,6 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
     return FALSE;
   }
 
-  $select = '';
-  $from = '';
   $where = array();
   $args = array();
 
@@ -1328,8 +1326,6 @@ function chado_select_record($table, $columns, $values, $options = NULL) {
       return array();
     }
 
-    $select[] = $field;
-
     // CASE 1: We have an array for a value.
     if (is_array($value)) {
 
@@ -1608,7 +1604,7 @@ function chado_select_record_check_value_type(&$op, &$value, $type) {
  *          WHERE
  *            F.uniquename = :feature_uniquename";
  * $args = array( ':feature_uniquename' => $form_state['values']['uniquename'] );
- * $result = chado_query( $sql, $args );
+ * $result = chado_query($sql, $args);
  * foreach ($result as $r) { [Do something with the records here] }
  * @endcode
  *
@@ -1907,4 +1903,4 @@ function chado_db_select($table, $alias = NULL, array $options = array()) {
   $conninfo = Database::getConnectionInfo();
   $conn = new ChadoDatabaseConnection($conninfo['default']);
   return $conn->select($table, $alias, $options);
-}
+}

+ 7 - 0
tripal_chado/api/tripal_chado.schema.api.inc

@@ -594,6 +594,13 @@ function chado_get_base_tables() {
     }
   }
 
+  // Remove the phenotype table. It really shouldn't be a base table as
+  // it is meant to store individual phenotype measurements.
+  unset($final_list['phenotyp']);
+
+  // Now add in the cvterm table to the list.
+  $final_list[] = 'cvterm';
+
   // Sort the tables and return the list.
   sort($final_list);
   return $final_list;

+ 19 - 19
tripal_chado/api/tripal_chado.schema_v1.11.api.inc

@@ -1697,7 +1697,7 @@ function tripal_chado_chado_schema_v1_11_cell_line_dbxref() {
       'is_current' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(
@@ -2024,12 +2024,12 @@ function tripal_chado_chado_schema_v1_11_cell_line_synonym() {
       'is_current' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
       'is_internal' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
     ),
     'primary key' => array(
@@ -4113,12 +4113,12 @@ function tripal_chado_chado_schema_v1_11_feature() {
       'is_analysis' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
       'is_obsolete' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
       'timeaccessioned' => array(
         'type' => 'datetime',
@@ -4236,7 +4236,7 @@ function tripal_chado_chado_schema_v1_11_feature_cvterm() {
       'is_not' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
       'rank' => array(
         'type' => 'int',
@@ -4523,7 +4523,7 @@ function tripal_chado_chado_schema_v1_11_feature_dbxref() {
       'is_current' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(
@@ -5323,12 +5323,12 @@ function tripal_chado_chado_schema_v1_11_feature_synonym() {
       'is_current' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
       'is_internal' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
     ),
     'primary key' => array(
@@ -5411,7 +5411,7 @@ function tripal_chado_chado_schema_v1_11_featureloc() {
       'is_fmin_partial' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
       'fmax' => array(
         'type' => 'int',
@@ -5420,7 +5420,7 @@ function tripal_chado_chado_schema_v1_11_featureloc() {
       'is_fmax_partial' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
       'strand' => array(
         'type' => 'int',
@@ -6262,7 +6262,7 @@ function tripal_chado_chado_schema_v1_11_library_dbxref() {
       'is_current' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(
@@ -6463,12 +6463,12 @@ function tripal_chado_chado_schema_v1_11_library_synonym() {
       'is_current' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'ru',
+        'default' => 'true',
       ),
       'is_internal' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
     ),
     'primary key' => array(
@@ -8473,7 +8473,7 @@ function tripal_chado_chado_schema_v1_11_pub() {
       'is_obsolete' => array(
         'type' => 'boolean',
         'not NULL' => '',
-        'default' => 'als',
+        'default' => 'false',
       ),
       'publisher' => array(
         'type' => 'varchar',
@@ -8542,7 +8542,7 @@ function tripal_chado_chado_schema_v1_11_pub_dbxref() {
       'is_current' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(
@@ -8684,7 +8684,7 @@ function tripal_chado_chado_schema_v1_11_pubauthor() {
       'editor' => array(
         'type' => 'boolean',
         'not NULL' => '',
-        'default' => 'als',
+        'default' => 'false',
       ),
       'surname' => array(
         'type' => 'varchar',
@@ -9108,7 +9108,7 @@ function tripal_chado_chado_schema_v1_11_stock() {
       'is_obsolete' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'als',
+        'default' => 'false',
       ),
     ),
     'primary key' => array(
@@ -9271,7 +9271,7 @@ function tripal_chado_chado_schema_v1_11_stock_dbxref() {
       'is_current' => array(
         'type' => 'boolean',
         'not NULL' => '1',
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(

+ 20 - 20
tripal_chado/api/tripal_chado.schema_v1.2.api.inc

@@ -1969,7 +1969,7 @@ function tripal_chado_chado_schema_v1_2_cell_line_dbxref() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(
@@ -2316,13 +2316,13 @@ function tripal_chado_chado_schema_v1_2_cell_line_synonym() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'is_internal' => array(
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
     ),
     'primary key' => array(
@@ -4877,13 +4877,13 @@ function tripal_chado_chado_schema_v1_2_feature() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'is_obsolete' => array(
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'timeaccessioned' => array(
         'description' => '',
@@ -5010,7 +5010,7 @@ function tripal_chado_chado_schema_v1_2_feature_cvterm() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'rank' => array(
         'description' => '',
@@ -5325,7 +5325,7 @@ function tripal_chado_chado_schema_v1_2_feature_dbxref() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(
@@ -6206,13 +6206,13 @@ function tripal_chado_chado_schema_v1_2_feature_synonym() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'is_internal' => array(
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
     ),
     'primary key' => array(
@@ -6302,7 +6302,7 @@ function tripal_chado_chado_schema_v1_2_featureloc() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'fmax' => array(
         'description' => '',
@@ -6313,7 +6313,7 @@ function tripal_chado_chado_schema_v1_2_featureloc() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'strand' => array(
         'description' => '',
@@ -7317,7 +7317,7 @@ function tripal_chado_chado_schema_v1_2_library_dbxref() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(
@@ -7536,13 +7536,13 @@ function tripal_chado_chado_schema_v1_2_library_synonym() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
       'is_internal' => array(
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
     ),
     'primary key' => array(
@@ -11236,7 +11236,7 @@ function tripal_chado_chado_schema_v1_2_pub() {
         'description' => '',
         'type' => 'boolean',
         'not null' => FALSE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'publisher' => array(
         'description' => '',
@@ -11354,7 +11354,7 @@ function tripal_chado_chado_schema_v1_2_pub_dbxref() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(
@@ -11508,7 +11508,7 @@ function tripal_chado_chado_schema_v1_2_pubauthor() {
         'description' => '',
         'type' => 'boolean',
         'not null' => FALSE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'surname' => array(
         'description' => '',
@@ -11970,7 +11970,7 @@ function tripal_chado_chado_schema_v1_2_stock() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
     ),
     'primary key' => array(
@@ -12075,7 +12075,7 @@ function tripal_chado_chado_schema_v1_2_stock_cvterm() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'als',
+        'default' => 'false',
       ),
       'rank' => array(
         'description' => '',
@@ -12250,7 +12250,7 @@ function tripal_chado_chado_schema_v1_2_stock_dbxref() {
         'description' => '',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'primary key' => array(

+ 9 - 9
tripal_chado/api/tripal_chado.schema_v1.3.api.inc

@@ -552,7 +552,7 @@ function tripal_chado_chado_schema_v1_3_analysis_dbxref() {
         'size' => 'normal',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'unique keys' => array(
@@ -2453,7 +2453,7 @@ function tripal_chado_chado_schema_v1_3_cell_line_dbxref() {
         'size' => 'normal',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'unique keys' => array(
@@ -6305,7 +6305,7 @@ function tripal_chado_chado_schema_v1_3_feature_dbxref() {
         'size' => 'normal',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'unique keys' => array(
@@ -7016,7 +7016,7 @@ function tripal_chado_chado_schema_v1_3_featuremap_dbxref() {
         'size' => 'normal',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'indexes' => array(
@@ -8856,7 +8856,7 @@ function tripal_chado_chado_schema_v1_3_library_dbxref() {
         'size' => 'normal',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'unique keys' => array(
@@ -9661,7 +9661,7 @@ function tripal_chado_chado_schema_v1_3_library_synonym() {
         'size' => 'normal',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
       'is_internal' => array(
         'size' => 'normal',
@@ -14034,7 +14034,7 @@ function tripal_chado_chado_schema_v1_3_project_dbxref() {
         'size' => 'normal',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'unique keys' => array(
@@ -15020,7 +15020,7 @@ function tripal_chado_chado_schema_v1_3_pub_dbxref() {
         'size' => 'normal',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'unique keys' => array(
@@ -16193,7 +16193,7 @@ function tripal_chado_chado_schema_v1_3_stock_dbxref() {
         'size' => 'normal',
         'type' => 'boolean',
         'not null' => TRUE,
-        'default' => 'ru',
+        'default' => 'true',
       ),
     ),
     'unique keys' => array(

+ 4 - 3
tripal_chado/includes/TripalFields/chado_linker__contact/chado_linker__contact.inc

@@ -62,8 +62,9 @@ class chado_linker__contact extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
-    $record = $details['record'];
+  public function load($entity) {
+    $record = $entity->chado_record;
+
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];
@@ -71,7 +72,7 @@ class chado_linker__contact extends ChadoField {
 
     // Get the FK that links to the base record.
     $schema = chado_get_schema($field_table);
-    $base_table = $details['record']->tablename;
+    $base_table = $entity->chado_table;
     $pkey = $schema['primary key'][0];
     if (!isset($schema['foreign keys'][$base_table]['columns'])) {
       return;

+ 1 - 1
tripal_chado/includes/TripalFields/chado_linker__cvterm/chado_linker__cvterm.inc

@@ -55,7 +55,7 @@ class chado_linker__cvterm extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];

+ 1 - 1
tripal_chado/includes/TripalFields/chado_linker__prop/chado_linker__prop.inc

@@ -59,7 +59,7 @@ class chado_linker__prop extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];

+ 2 - 2
tripal_chado/includes/TripalFields/data__accession/data__accession.inc

@@ -47,9 +47,9 @@ class data__accession extends ChadoField {
   /**
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
 
-    $record = $details['record'];
+    $record = $entity->chado_record;
 
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];

+ 1 - 1
tripal_chado/includes/TripalFields/data__accession/data__accession_widget.inc

@@ -106,7 +106,7 @@ class data__accession_widget extends ChadoFieldWidget {
     );
     $widget['links'] = array(
       '#type' => 'item',
-      '#markup' => l('Add a new database', 'admin/tripal/storage/chado/db/add', array('attributes' => array('target' => '_blank')))
+      '#markup' => l('Add a new database', 'admin/tripal/loaders/chado_db/add', array('attributes' => array('target' => '_blank')))
     );
   }
 

+ 2 - 2
tripal_chado/includes/TripalFields/data__protein_sequence/data__protein_sequence.inc

@@ -47,9 +47,9 @@ class data__protein_sequence extends ChadoField {
   /**
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
     $field_name = $this->field['field_name'];
-    $feature = $details['record'];
+    $feature = $entity->chado_record;
     $num_seqs = 0;
 
     // Look for Protein sequences

+ 2 - 2
tripal_chado/includes/TripalFields/data__sequence/data__sequence.inc

@@ -46,9 +46,9 @@ class data__sequence extends ChadoField {
   /**
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
     $field_name = $this->field['field_name'];
-    $feature = $details['record'];
+    $feature = $entity->chado_record;
 
     // We don't want to get the sequence for traditionally large types. They are
     // too big,  bog down the web browser, take longer to load and it's not

+ 1 - 1
tripal_chado/includes/TripalFields/data__sequence_coordinates/data__sequence_coordinates.inc

@@ -59,7 +59,7 @@ class data__sequence_coordinates extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
 
   }
 }

+ 4 - 3
tripal_chado/includes/TripalFields/go__gene_expression/go__gene_expression.inc

@@ -64,8 +64,9 @@ class go__gene_expression extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
-    $record = $details['record'];
+  public function load($entity) {
+
+    $record = $entity->chado_record;
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];
@@ -73,7 +74,7 @@ class go__gene_expression extends ChadoField {
 
     // Get the FK that links to the base record.
     $schema = chado_get_schema($field_table);
-    $base_table = $details['record']->tablename;
+    $base_table = $entity->chado_table;
     $pkey = $schema['primary key'][0];
     $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
     $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];

+ 2 - 2
tripal_chado/includes/TripalFields/local__source_data/local__source_data.inc

@@ -59,8 +59,8 @@ class local__source_data extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
-    $analysis = $details['record'];
+  public function load($entity) {
+    $analysis = $entity->chado_record;
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];

+ 2 - 2
tripal_chado/includes/TripalFields/obi__organism/obi__organism.inc

@@ -65,9 +65,9 @@ class obi__organism extends ChadoField {
   /**
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
 
-    $record = $details['record'];
+    $record = $entity->chado_record;
     $settings = $this->instance['settings'];
 
     $field_name = $this->field['field_name'];

+ 3 - 2
tripal_chado/includes/TripalFields/ogi__location_on_map/ogi__location_on_map.inc

@@ -59,8 +59,9 @@ class ogi__location_on_map extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
-    $record = $details['record'];
+  public function load($entity) {
+
+    $record = $entity->chado_record;
     $settings = $this->field['settings'];
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];

+ 2 - 2
tripal_chado/includes/TripalFields/sbo__database_cross_reference/sbo__database_cross_reference.inc

@@ -61,8 +61,8 @@ class sbo__database_cross_reference extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
-    $record = $details['record'];
+  public function load($entity) {
+    $record = $entity->chado_record;
 
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];

+ 1 - 1
tripal_chado/includes/TripalFields/sbo__database_cross_reference/sbo__database_cross_reference_widget.inc

@@ -136,7 +136,7 @@ class sbo__database_cross_reference_widget extends ChadoFieldWidget {
     if (!$db_id) {
       $widget['links'] = array(
         '#type' => 'item',
-        '#markup' => l('Add a database', 'admin/tripal/storage/chado/db/add', array('attributes' => array('target' => '_blank')))
+        '#markup' => l('Add a database', 'admin/tripal/loaders/chado_db/add', array('attributes' => array('target' => '_blank')))
       );
     }
   }

+ 3 - 3
tripal_chado/includes/TripalFields/sbo__phenotype/sbo__phenotype.inc

@@ -61,8 +61,8 @@ class sbo__phenotype extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
-    $record = $details['record'];
+  public function load($entity) {
+    $record = $entity->chado_record;
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];
@@ -70,7 +70,7 @@ class sbo__phenotype extends ChadoField {
 
     // Get the FK that links to the base record.
     $schema = chado_get_schema($field_table);
-    $base_table = $details['record']->tablename;
+    $base_table = $entity->chado_table;
     $pkey = $schema['primary key'][0];
     $fkey_lcolumn = key($schema['foreign keys'][$base_table]['columns']);
     $fkey_rcolumn = $schema['foreign keys'][$base_table]['columns'][$fkey_lcolumn];

+ 22 - 5
tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship.inc

@@ -35,12 +35,22 @@ class sbo__relationship extends ChadoField {
     // type. This will create form elements when editing the field instance
     // to allow the site admin to change the term settings above.
     'term_fixed' => FALSE,
+    // Inidates if this field should be automatically attached to display
+    // or web services or if this field should be loaded separately. This
+    // is convenient for speed.  Fields that are slow should for loading
+    // should ahve auto_attach set to FALSE so tha their values can be
+    // attached asyncronously.
+    'auto_attach' => FALSE,
+    // Settings to help the site admin control how relationship types and
+    // valid subject/objects can be selected by the user.
     'relationships' => array(
       'option1_vocabs' => '',
       'option2_vocab' => '',
       'option2_parent' => '',
       'relationship_types' => '',
     ),
+    // The number of items to show on a page.
+    'items_per_page' => 10,
   );
 
   // The default widget for this field.
@@ -65,10 +75,10 @@ class sbo__relationship extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
     $settings = $this->field['settings'];
 
-    $record = $details['record'];
+    $record = $entity->chado_record;
 
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
@@ -80,7 +90,7 @@ class sbo__relationship extends ChadoField {
     $schema = chado_get_schema($field_table);
     $pkey = $schema['primary key'][0];
 
-    // Get the Pkeys for the subject and object tables
+    // Get the foreign keys for the subject and object tables
     $subject_fkey_table = '';
     $object_fkey_table = '';
     $fkeys = $schema['foreign keys'];
@@ -516,9 +526,16 @@ class sbo__relationship extends ChadoField {
    *
    * @see TripalField::settingsForm()
    */
-  public function settingsForm($has_data) {
+  public function instanceSettingsForm() {
     $element = parent::instanceSettingsForm();
 
+    $element['items_per_page'] = array(
+      '#type' => 'textfield',
+      '#title' => 'Items per Page',
+      '#description' => t('The number of items that should appear on each page.  A pager is provided if more than this number of items exist.'),
+      '#default_value' => $this->instance['settings']['items_per_page'],
+    );
+
     //$element = parent::instanceSettingsForm();
     $element['relationships'] = array(
       '#type' => 'fieldset',
@@ -604,7 +621,7 @@ class sbo__relationship extends ChadoField {
    * @param unknown $form
    * @param unknown $form_state
    */
-  public function settingsFormValidate($form, &$form_state) {
+  public function instanceSettingsFormValidate($form, &$form_state) {
     // Get relationships settings
     $settings = $form_state['values']['instance']['settings']['relationships'];
     $form_state['values']['instance']['settings']['relationships']['relationship_types']= trim($settings['relationship_types']);

+ 39 - 38
tripal_chado/includes/TripalFields/sbo__relationship/sbo__relationship_formatter.inc

@@ -1,6 +1,7 @@
 <?php
 
 class sbo__relationship_formatter extends ChadoFieldFormatter {
+
   // The default lable for this field.
   public static $default_label = 'Relationship';
 
@@ -51,13 +52,14 @@ class sbo__relationship_formatter extends ChadoFieldFormatter {
    * @see TripalFieldFormatter::view()
    */
   public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+
     // Get the settings
     $settings = $display['settings'];
     $rows = array();
     $headers = array($settings['title']);
 
     foreach ($items as $delta => $item) {
-      if (!$item['value']) {
+      if (empty($item['value'])) {
         continue;
       }
       $subject_name = $item['value']['local:relationship_subject']['schema:name'];
@@ -69,7 +71,8 @@ class sbo__relationship_formatter extends ChadoFieldFormatter {
       // Handle some special cases.
       // For mRNA objects we don't want to show the CDS, exons, 5' UTR, etc.
       // we want to show the parent gene and the protein.
-      if ($object_type == 'mRNA' and (in_array($subject_type, array('CDS', 'exon', 'five_prime_UTR', 'three_prime_UTR')))) {
+      if ($object_type == 'mRNA' and
+          (in_array($subject_type, array('CDS', 'exon', 'five_prime_UTR', 'three_prime_UTR')))) {
         continue;
       }
 
@@ -91,35 +94,36 @@ class sbo__relationship_formatter extends ChadoFieldFormatter {
         }
       }
 
-      $rows[][] = array('data' => $phrase, 'class' => array('tripal-entity-unattached field-items'));
+      $rows[][] = array(
+        'data' => $phrase,
+        'class' => array('tripal-entity-unattached field-items')
+      );
     }
 
-    //$pager = $this->generate_pager(count($rows), $per_page);
-
-    $per_page = 10;
-    // Initialize the pager
-    $current_page = pager_default_initialize(count($rows), $per_page);
-    // Split your list into page sized chunks
-    $chunks = array_chunk($rows, $per_page, TRUE);
-    //format pager
-    $pager = theme('pager', array('quantity', count($rows)));
-
-
-    global $base_path;
-    $tmp_base_path = preg_replace('/\//', '\/', $base_path);
-    $field_id = 'tripal-entity-' . $entity->id . '--' . $this->field['field_name'];
-    $pager = preg_replace('/href="' . $tmp_base_path . 'bio_data\/ajax\/field_attach\/' . $field_id . '\?page=(.+?)"/', 'href="javascript:void(0)" onclick="tripal_navigate_field_pager(\'' . $field_id . '\', $1)"', $pager);
-    $pager = preg_replace('/href="' . $tmp_base_path . 'bio_data\/ajax\/field_attach\/' . $field_id . '"/', 'href="javascript:void(0)" onclick="tripal_navigate_field_pager(\'' . $field_id . '\', 0)"', $pager);
-
-    //$pager = preg_replace("/href=\"" . $tmp_base_path . "gensas\/load_job_view_panel\/" . $job_id . "\/\d\"/", 'href="javascript:void(0)" onclick="gensas.show_job_view_panel(\'' . $job_id . '\', \'' . $job->getName() . '\')"', $pager);
-    // the $table array contains the headers and rows array as well as other
-    // options for controlling the display of the table.  Additional
-    // documentation can be found here:
-    // https://api.drupal.org/api/drupal/includes%21theme.inc/function/theme_table/7
-
-    $table = array(
+    // Build the pager
+    $items_per_page = array_key_exists('items_per_page', $this->instance['settings']) ? $this->instance['settings']['items_per_page'] : 10;
+    $total_records = count($items);
+    $total_pages = (int) ($total_records / $items_per_page) + 1;
+    $pelement = 0; //$this->getPagerElementID();
+    $current_page = pager_default_initialize($total_records, $items_per_page, $pelement);
+    $pager = theme('pager', array(
+      'tags' => array(),
+      'element' => $pelement,
+      'parameters' => array(),
+      'quantity' => $total_pages,
+    ));
+    $pager = $this->ajaxifyPager($pager, $entity);
+    $page_items = array_chunk($rows, $items_per_page);
+
+    if (count($items) == 1) {
+      $content = 'There is ' . count($items) . ' relationship.';
+    }
+    else {
+      $content = 'There are ' . count($items) . ' relationships.';
+    }
+    $content .= theme_table(array(
       'header' => $headers,
-      'rows' => $current_page ? $chunks[$current_page] : array(),
+      'rows' => $page_items[$current_page],
       'attributes' => array(
         'id' => 'sbo--relationship-table',
       ),
@@ -127,16 +131,13 @@ class sbo__relationship_formatter extends ChadoFieldFormatter {
       'caption' => '',
       'colgroups' => array(),
       'empty' => $settings['empty'],
-    );
+    ));
 
-    // once we have our table array structure defined, we call Drupal's theme_table()
-    // function to generate the table.
-    if (count($items) > 0) {
-      $element[0] = array(
-        '#type' => 'markup',
-        '#markup' => theme_table($table),
-        '#suffix' => '<img src=\'/sites/all/modules/tripal-7.x-3.x/tripal/theme/images/ajax-loader.gif\' id=\'spinner\'/>' . $pager,
-      );
-    }
+    $element[0] = array(
+      '#type' => 'markup',
+      '#markup' => $content . $pager,
+    );
   }
 }
+
+

+ 2 - 2
tripal_chado/includes/TripalFields/schema__additional_type/schema__additional_type.inc

@@ -49,8 +49,8 @@ class schema__additional_type extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
-    $record = $details['record'];
+  public function load($entity) {
+    $record = $entity->chado_record;
     $base_table = $this->instance['settings']['base_table'];
 
     $field_name = $this->field['field_name'];

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

@@ -47,8 +47,8 @@ class schema__alternate_name extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
-    $record = $details['record'];
+  public function load($entity) {
+    $record = $entity->chado_record;
     $base_table = $this->instance['settings']['base_table'];
 
     $field_name = $this->field['field_name'];

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

@@ -61,8 +61,8 @@ class schema__publication extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
-    $record = $details['record'];
+  public function load($entity) {
+    $record = $entity->chado_record;
 
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];

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

@@ -22,8 +22,12 @@ class schema__publication_formatter extends ChadoFieldFormatter {
   public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
     $list_items = array();
     $chado_table = $this->instance['settings']['chado_table'];
+
     foreach ($items as $delta => $item) {
 
+      if (empty($item['value'])) {
+        continue;
+      }
       $title = isset($item['value']['TPUB:0000039']) ? $item['value']['TPUB:0000039'] : '';
       $citation = isset($item['value']['TPUB:0000003']) ? $item['value']['TPUB:0000003'] : '';
       $entity = array_key_exists('entity', $item['value']) ? $item['value']['entity'] : '';
@@ -39,10 +43,10 @@ class schema__publication_formatter extends ChadoFieldFormatter {
       $list_items[] = $citation;
     }
 
+    $list = '';
     krsort($list_items, SORT_NUMERIC);
-
     if (count($list_items) == 0) {
-      $list = 'There are no publications.';
+      $list = 'There are no publications associated with this record.';
     }
     if (count($list_items) == 1) {
       $list = $list_items[0];

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

@@ -25,15 +25,13 @@ class schema__publication_widget extends ChadoFieldWidget {
     $fkey = $fkeys[0];
 
     // Get the field defaults.
-    $record_id = '';
-    $fkey_value = array_key_exists('#entity', $element) and $element['#entity'] ? $element['#entity']->chado_record_id : NULL;
+    $fkey_value = (array_key_exists('#entity', $element) and is_object($element['#entity'])) ? $element['#entity']->chado_record_id : NULL;
     $pub_id = '';
     $uname = '';
 
     // If the field already has a value then it will come through the $items
     // array.  This happens when editing an existing record.
     if (count($items) > 0 and array_key_exists($delta, $items)) {
-      $record_id = tripal_get_field_item_keyval($items, $delta, 'chado-' . $table_name . '__' . $pkey, $record_id);
       $pub_id = tripal_get_field_item_keyval($items, $delta, 'chado-' . $table_name . '__pub_id', $pub_id);
       $uname = tripal_get_field_item_keyval($items, $delta, 'uniquename', $uname);
     }
@@ -52,7 +50,7 @@ class schema__publication_widget extends ChadoFieldWidget {
 
     $widget['chado-' . $table_name . '__' . $pkey] = array(
       '#type' => 'value',
-      '#default_value' => $record_id,
+      '#default_value' => '',
     );
     $widget['chado-' . $table_name . '__' . $fkey] = array(
       '#type' => 'value',

+ 2 - 1
tripal_chado/includes/TripalFields/sio__references/sio__references.inc

@@ -59,7 +59,8 @@ class sio__references extends ChadoField {
    *
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
+
     $field_name = $this->field['field_name'];
     $field_type = $this->field['type'];
     $field_table = $this->instance['settings']['chado_table'];

+ 112 - 0
tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary.inc

@@ -0,0 +1,112 @@
+<?php
+
+class sio__vocabulary extends ChadoField {
+
+  // The default lable for this field.
+  public static $default_label = 'Vocabulary';
+
+  // The default description for this field.
+  public static $description = 'The vocabulary to which this resource is associated.';
+
+  // Provide a list of instance specific settings. These can be access within
+  // the instanceSettingsForm.  When the instanceSettingsForm is submitted
+  // then Drupal with automatically change these settings for the instnace.
+  // It is recommended to put settings at the instance level whenever possible.
+  // If you override this variable in a child class be sure to replicate the
+  // term_name, term_vocab, term_accession and term_fixed keys as these are
+  // required for all TripalFields.
+  public static $default_instance_settings  = array(
+    // The short name for the vocabulary (e.g. shcema, SO, GO, PATO, etc.).
+    'term_vocabulary' => 'SIO',
+    // The name of the term.
+    'term_name' => 'vocabulary',
+    // The unique ID (i.e. accession) of the term.
+    'term_accession' => '001080',
+    // Set to TRUE if the site admin is allowed to change the term
+    // type. This will create form elements when editing the field instance
+    // to allow the site admin to change the term settings above.
+    'term_fixed' => FALSE,
+  );
+
+  // The default widget for this field.
+  public static $default_widget = 'sio__vocabulary_widget';
+
+  // The default formatter for this field.
+  public static $default_formatter = 'sio__vocabulary_formatter';
+
+
+  /**
+   * @see TripalField::validate()
+   */
+  public function validate($entity_type, $entity, $field, $items, &$errors) {
+
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
+
+    // Get the field values.
+    foreach ($items as $delta => $values) {
+
+      // Get the field values.
+      $cv_id = $values['chado-' . $field_table . '__cv_id'];
+      if (!$cv_id or $cv_id == 0) {
+        $errors[$field_name]['und'][0][] = array(
+          'message' =>  t("Please specify a vocabulary."),
+          'error' => 'chado-' . $field_table . '__cv_id'
+        );
+      }
+    }
+  }
+
+  /**
+   * @see TripalField::load()
+   */
+  public function load($entity) {
+
+    $record = $entity->chado_record;
+    $settings = $this->instance['settings'];
+
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
+
+    // Set some defaults for the empty record.
+    $entity->{$field_name}['und'][0] = array(
+      'value' => array(),
+    );
+
+    if ($record) {
+      $cv = $record->cv_id;
+      $entity->{$field_name}['und'][0]['value'] = $cv->name;
+      $entity->{$field_name}['und'][0]['chado-' . $field_table . '__cv_id'] = $cv->cv_id;
+    }
+  }
+
+  /**
+   * @see ChadoField::query()
+   */
+  public function query($query, $condition) {
+    $alias = $this->field['field_name'];
+    $operator = $condition['operator'];
+
+    $query->join('cv', $alias, "base.cv_id = $alias.cv_id");
+    $query->condition("$alias.name", $condition['value'], $operator);
+  }
+
+  /**
+   * @see ChadoField::queryOrder()
+   */
+  public function queryOrder($query, $order) {
+
+    // If the table hasn't yet been joined then add it.
+    $joins = $query->getTables();
+    if (!in_array($this->field['field_name'], $joins)) {
+      $alias = $this->field['field_name'];
+      $query->join('cv', $alias, "base.cv_id = $alias.cv_id");
+      $query->orderBy("$alias.name", $order['direction']);
+    }
+  }
+}

+ 24 - 0
tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary_formatter.inc

@@ -0,0 +1,24 @@
+<?php
+
+class sio__vocabulary_formatter extends ChadoFieldFormatter {
+
+  // The default lable for this field.
+  public static $default_label = 'Vocabulary';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('sio__vocabulary');
+
+  /**
+   * @see TripalFieldFormatter::view()
+   */
+  public function view(&$element, $entity_type, $entity, $langcode, $items, $display) {
+    if (count($items) > 0) {
+      // The cardinality of this field is 1 so we don't have to
+      // iterate through the items array, as there will never be more than 1.
+      $element[0] = array(
+        '#type' => 'markup',
+        '#markup' => $items[0]['value'],
+      );
+    }
+  }
+}

+ 54 - 0
tripal_chado/includes/TripalFields/sio__vocabulary/sio__vocabulary_widget.inc

@@ -0,0 +1,54 @@
+<?php
+
+class sio__vocabulary_widget extends ChadoFieldWidget {
+
+  // The default lable for this field.
+  public static $default_label = 'Vocabulary';
+
+  // The list of field types for which this formatter is appropriate.
+  public static $field_types = array('sio__vocabulary');
+
+
+  /**
+   * @see TripalFieldWidget::form()
+   */
+  public function form(&$widget, &$form, &$form_state, $langcode, $items, $delta, $element) {
+
+    parent::form($widget, $form, $form_state, $langcode, $items, $delta, $element);
+
+    $settings = $this->field['settings'];
+    $field_name = $this->field['field_name'];
+    $field_type = $this->field['type'];
+    $field_table = $this->instance['settings']['chado_table'];
+    $field_column = $this->instance['settings']['chado_column'];
+
+    $cv_id = 0;
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#value' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+    $widget['chado-' . $field_table . '__cv_id'] = array(
+      '#type' => 'value',
+      '#value' => $items[$delta]['chado-' . $field_table . '__cv_id'],
+    );
+    $widget['vocabulary_name'] = array(
+      '#type' => 'item',
+      '#title' => 'Vocabulary',
+      '#markup' => array_key_exists($delta, $items) ? $items[$delta]['value'] : '',
+    );
+  }
+
+  /**
+   * @see TripalFieldWidget::validate()
+   */
+  public function validate($element, $form, &$form_state, $langcode, $delta) {
+
+    $field_name = $this->field['field_name'];
+    $field_table = $this->instance['settings']['chado_table'];
+
+    // Make sure the value is set to the cv_id
+    $cv_id = $form_state['values'][$field_name][$langcode][0]['chado-' . $field_table . '__cv_id'];
+    $form_state['values'][$field_name][$langcode][0]['value'] = $cv_id;
+  }
+}

+ 2 - 2
tripal_chado/includes/TripalFields/so__cds/so__cds.inc

@@ -46,9 +46,9 @@ class so__cds extends ChadoField {
   /**
    * @see TripalField::load()
    */
-  public function load($entity, $details = array()) {
+  public function load($entity) {
     $field_name = $this->field['field_name'];
-    $feature = $details['record'];
+    $feature = $entity->chado_record;
     $num_seqs = 0;
 
     $feature = chado_expand_var($feature, 'table', 'featureloc', $options);

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است