Browse Source

Simplified the field interface so more functions are in the field files. Added the featureloc field

Stephen Ficklin 9 years ago
parent
commit
1eeb99cd82

+ 54 - 1
tripal_chado/includes/fields/chado_base__dbxref_id.inc

@@ -1,5 +1,58 @@
 <?php
-
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_base__dbxref_id_info() {
+  return array(
+    'label' => t('Cross reference'),
+    'description' => t('This record can be cross referenced with a record in
+      another online database. This field is intended for the most prominent
+      reference.  At a minimum, the database and accession must be provided.'),
+    'default_widget' => 'chado_base__dbxref_id_widget',
+    'default_formatter' => 'chado_base__dbxref_id_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_base__dbxref_id_widget_info() {
+  return array(
+    'label' => t('Cross reference'),
+    'field types' => array('chado_base__dbxref_id'),
+    'description' => t('This record can be cross referenced with a record in
+        another online database. This field is intended for the most
+        prominent reference.  At a minimum, the database and accession
+        must be provided.'),
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_base__dbxref_id_formatter_info() {
+  return array(
+    'label' => t('Database Cross Reference'),
+    'field types' => array('chado_base__dbxref_id'),
+    'settings' => array(
+    ),
+  );
+}
 /**
  *
  * @param unknown $entity_type

+ 32 - 0
tripal_chado/includes/fields/chado_base__organism_id.inc

@@ -1,4 +1,36 @@
 <?php
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_base__organism_id_info() {
+  return array(
+    'label' => t('Organism'),
+    'description' => t('A field for specifying an organism.'),
+    'default_widget' => 'chado_base__organism_id_widget',
+    'default_formatter' => 'chado_base__organism_id_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_base__organism_id_widget_info() {
+  return array(
+    'label' => t('Organism Select'),
+    'field types' => array('chado_base__organism_id')
+  );
+}
 /**
  * Implements hook_formatter_info.
  *

+ 48 - 0
tripal_chado/includes/fields/chado_feature__md5checksum.inc

@@ -1,4 +1,52 @@
 <?php
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_feature__md5checksum_info() {
+  return array(
+    'label' => t('MD5 checksum'),
+    'description' => t('A field for generating MD5 checksum for a sequence.'),
+    'default_widget' => 'chado_feature__md5checksum_widget',
+    'default_formatter' => 'chado_feature__md5checksum_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_feature__md5checksum_widget_info() {
+  return array(
+    'label' => t('MD5 Checksum Checkbox'),
+    'field types' => array('chado_feature__md5checksum'),
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_feature__md5checksum_formatter_info() {
+  return array(
+    'label' => t('MD5 Checksum'),
+    'field types' => array('chado_feature__md5checksum'),
+    'settings' => array(
+    ),
+  );
+}
 
 /**
  *

+ 46 - 1
tripal_chado/includes/fields/chado_feature__residues.inc

@@ -1,5 +1,50 @@
 <?php
-
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_feature__residues_info() {
+  return array(
+    'label' => t('Residues'),
+    'description' => t('A field for managing nucleotide and protein residues.'),
+    'default_widget' => 'chado_feature__residues_widget',
+    'default_formatter' => 'chado_feature__residues_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_feature__residues_widget_info() {
+  return array(
+    'label' => t('Residues'),
+    'field types' => array('chado_feature__residues'),
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_feature__residues_formatter_info() {
+  return array(
+    'label' => t('Residues'),
+    'field types' => array('chado_feature__residues'),
+  );
+}
 /**
  *
  * @param unknown $entity_type

+ 48 - 0
tripal_chado/includes/fields/chado_feature__seqlen.inc

@@ -1,4 +1,52 @@
 <?php
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_feature__seqlen_info() {
+  return array(
+    'label' => t('Sequence length'),
+    'description' => t('A field for calculating the length of a sequence.'),
+    'default_widget' => 'chado_feature__seqlen_widget',
+    'default_formatter' => 'chado_feature__seqlen_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_feature__seqlen_widget_info() {
+  return array(
+    'label' => t('Sequence Length'),
+    'field types' => array('chado_feature__seqlen'),
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_feature__seqlen_formatter_info() {
+  return array(
+    'label' => t('Residues Length'),
+    'field types' => array('chado_feature__seqlen'),
+    'settings' => array(
+    ),
+  );
+}
 
 /**
  *

+ 51 - 1
tripal_chado/includes/fields/chado_linker__cvterm.inc

@@ -1,5 +1,55 @@
 <?php
-
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_linker__cvterm_info() {
+  return array(
+    'label' => t('Annotations'),
+    'description' => t('This record can be annotated with terms
+          from other vocabularies.'),
+    'default_widget' => 'chado_linker__cvterm_widget',
+    'default_formatter' => 'chado_linker__cvterm_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_linker__cvterm_widget_info() {
+  return array(
+    'label' => t('Annotations'),
+    'field types' => array('chado_linker__cvterm'),
+    'description' => t('This record can be annotated with terms
+          from other vocabularies.'),
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_linker__cvterm_formatter_info() {
+  return array(
+    'label' => t('Annotations'),
+    'field types' => array('chado_linker__cvterm'),
+    'settings' => array(
+    ),
+  );
+}
 /**
  *
  * @param unknown $entity_type

+ 34 - 14
tripal_chado/includes/fields/chado_linker__cvterm_adder.inc

@@ -1,21 +1,41 @@
 <?php
-
 /**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ *
+ * The field provides a widget for adding new vocabularies for cvterm
+ * linker tables. This will allow cvterms to be grouped by vocabulary
+ * ('category').
  *
- * @param unknown $entity_type
- * @param unknown $entity
- * @param unknown $field
- * @param unknown $instance
- * @param unknown $langcode
- * @param unknown $items
- * @param unknown $display
  */
-function chado_linker__cvterm_adder_formatter(&$element, $entity_type, $entity, $field,
-  $instance, $langcode, $items, $display) {
-
-  foreach ($items as $delta => $item) {
-    // Do nothing, this field is only meant for the form.
-  }
+function chado_linker__cvterm_adder_info() {
+  return array(
+    'label' => t('Add an Annotation Type'),
+    'description' => t('This record may have any number of types of
+      annotations. Use this field to first add the type.'),
+    'default_widget' => 'chado_linker__cvterm_adder_widget',
+    'default_formatter' => 'hidden',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_linker__cvterm_adder_widget_info() {
+  return array(
+    'label' => t('Add an Annotation'),
+    'field types' => array('chado_linker__cvterm_adder'),
+  );
 }
 /**
  *

+ 54 - 1
tripal_chado/includes/fields/chado_linker__dbxref.inc

@@ -1,5 +1,58 @@
 <?php
-
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_linker__dbxref_info() {
+  return array(
+    'label' => t('Cross references'),
+    'description' => t('This record can be cross referenced with a record in
+        another online database. This field is intended for one or more
+        references.  At a minimum, the database and accession must be provided.'),
+    'default_widget' => 'chado_linker__dbxref_widget',
+    'default_formatter' => 'chado_linker__dbxref_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_linker__dbxref_widget_info() {
+  return array(
+    'label' => t('Cross references'),
+    'field types' => array('chado_linker__dbxref'),
+    'description' => t('This record can be cross referenced with a record
+        in another online database. This field is intended for the most
+        prominent reference.  At a minimum, the database and accession
+        must be provided.'),
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_linker__dbxref_formatter_info() {
+  return array(
+    'label' => t('Cross references'),
+    'field types' => array('chado_linker__dbxref'),
+    'settings' => array(
+    ),
+  );
+}
 /**
  *
  * @param unknown $entity_type

+ 375 - 0
tripal_chado/includes/fields/chado_linker__featureloc.inc

@@ -1 +1,376 @@
 <?php
+
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_linker__featureloc_info() {
+  return array(
+    'label' => t('Alignments'),
+    'description' => t('Locations on landmark sequences where the feature is aligned.'),
+    'default_widget' => 'chado_linker__featureloc_widget',
+    'default_formatter' => 'chado_linker__featureloc_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_linker__featureloc_widget_info() {
+  return array(
+    'label' => t('Alignment Settings'),
+    'field types' => array('chado_linker__featureloc')
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_linker__featureloc_formatter_info() {
+  return array(
+    'label' => t('Alignments'),
+    'field types' => array('chado_linker__featureloc'),
+    'settings' => array(
+    ),
+  );
+}
+
+/**
+ * Implements hook_formatter_settings_summary.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_settings_summary() for each field
+ * to specify.
+ *
+ */
+function chado_linker__featureloc_formatter_settings_summary($field, $instance,
+    $view_mode) {
+
+}
+
+/**
+ * Provides a settings form for the formatter.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_settings_form() for each field
+ * to specify.
+ */
+function chado_linker__featureloc_formatter_settings_form($field, $instance,
+    $view_mode, $form, &$form_state) {
+
+
+
+}
+
+/**
+ * Validation function for the chado_linker_featureloc_formatter_settings_form.
+ */
+function chado_linker__featureloc_formatter_settings_form_validate(&$form, &$form_state) {
+
+  // Place here as an example for validating the settings form.
+}
+
+/**
+ *
+ */
+function chado_linker__featureloc_formatter(&$element, $entity_type, $entity,
+    $field, $instance, $langcode, $items, $display) {
+
+  // Get the settings
+  $settings = $display['settings'];
+
+  foreach ($items as $delta => $item) {
+    $alignments = $item['featurelocs'];
+    if (count($alignments) > 0){
+
+      // 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('Aligned Feature' ,'Feature Type', 'Alignment Location');
+
+      // 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 ($alignments as $alignment){
+        $feature_name = $alignment->name;
+        if (property_exists($alignment, 'nid')) {
+          $feature_name = l($feature_name, "node/" . $alignment->nid);
+        }
+        $feature_loc = '';
+        $strand = '.';
+        if ($alignment->strand == -1) {
+          $strand = '-';
+        }
+        elseif ($alignment->strand == 1) {
+           $strand = '+';
+        }
+        // if this is a match then make the other location
+        if(property_exists($alignment, 'right_feature')){
+          $rstrand = '.';
+          if ($alignment->right_strand == -1) {
+            $rstrand = '-';
+          }
+          elseif ($alignment->right_strand == 1) {
+            $rstrand = '+';
+          }
+          $feature_loc = $feature->name .":". ($alignment->fmin + 1) . ".." . $alignment->fmax . " " . $strand;
+          $feature_loc .= "<br>" . $alignment->name .":". ($alignment->right_fmin + 1) . ".." . $alignment->right_fmax . " " . $rstrand;
+        }
+        else {
+          $feature_loc = $alignment->name .":". ($alignment->fmin + 1) . ".." . $alignment->fmax . " " . $strand;
+        }
+
+        $rows[] = array(
+          $feature_name,
+          $alignment->type,
+          $feature_loc
+        );
+      }
+
+      // 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_feature-table-alignments',
+          '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.
+      $element[$delta] = array(
+        '#type' => 'markup',
+        '#markup' => theme_table($table),
+      );
+    }
+  }
+}
+
+/**
+ * Loads the field values with appropriate data.
+ *
+ * This function is called by the tripal_chado_field_storage_load() for
+ * each property managed by the field_chado_storage storage type.  This is
+ * an optional hook function that is only needed if the field has
+ * multiple form elements.
+ */
+function chado_linker__featureloc_load($field, $entity, $base_table, $record) {
+  $field_name = $field['field_name'];
+
+  $options = array(
+    'return_array' => 1,
+    'include_fk' => array(
+      'srcfeature_id' => array(
+        'type_id' => 1,
+      ),
+      'feature_id' => array(
+        'type_id' => 1
+      ),
+    )
+  );
+  $feature = chado_expand_var($record, 'table', 'featureloc', $options);
+
+  // get alignments as child
+  $cfeaturelocs = $feature->featureloc->feature_id;
+  if (!$cfeaturelocs) {
+    $cfeaturelocs = array();
+  }
+  // get alignment as parent
+  $pfeaturelocs = $feature->featureloc->srcfeature_id;
+  if (!$pfeaturelocs) {
+    $pfeaturelocs = array();
+  }
+
+  // get matched alignments (those with an itermediate 'match' or 'EST_match', etc
+  $mfeaturelocs = chado_linker__featureloc_get_matched_alignments($feature);
+  $feature->matched_featurelocs = $mfeaturelocs;
+
+  // combine all three alignments into a single array for printing together in
+  // a single list
+  $alignments = array();
+  foreach ($pfeaturelocs as $featureloc) {
+    // if type is a 'match' then ignore it. We will handle those below
+    if (preg_match('/(^match$|^.*?_match|match_part)$/', $featureloc->feature_id->type_id->name)) {
+      continue;
+    }
+    $alignment = new stdClass();
+    $alignment->record = $featureloc;
+    $alignment->name = $featureloc->feature_id->name;
+    $alignment->type = $featureloc->feature_id->type_id->name;
+    $alignment->fmin = $featureloc->fmin;
+    $alignment->fmax = $featureloc->fmax;
+    $alignment->phase = $featureloc->phase;
+    $alignment->strand = $featureloc->strand;
+    $alignments[] = $alignment;
+    if (property_exists($featureloc->feature_id, 'nid')) {
+      $alignment->nid = $featureloc->feature_id->nid;
+    }
+  }
+  foreach ($cfeaturelocs as $featureloc) {
+    // if type is a 'match' then ignore it. We will handle those below
+    if (preg_match('/(^match$|^.*?_match|match_part)$/', $featureloc->feature_id->type_id->name)) {
+      continue;
+    }
+    $alignment = new stdClass();
+    $alignment->record = $featureloc;
+    $alignment->name = $featureloc->srcfeature_id->name;
+    $alignment->type = $featureloc->srcfeature_id->type_id->name;
+    $alignment->fmin = $featureloc->fmin;
+    $alignment->is_fmin_partial = $featureloc->is_fmin_partial;
+    $alignment->fmax = $featureloc->fmax;
+    $alignment->is_fmax_partial = $featureloc->is_fmax_partial;
+    $alignment->phase = $featureloc->phase;
+    $alignment->strand = $featureloc->strand;
+    $alignments[] = $alignment;
+    if (property_exists($featureloc->srcfeature_id, 'nid')) {
+      $alignment->nid = $featureloc->srcfeature_id->nid;
+    }
+  }
+  // in matching features, the left feature is always the feature
+  // provided to this function.
+  foreach ($mfeaturelocs as $featureloc) {
+    // get more information about the right feature
+    $select = array('feature_id' => $featureloc->right_srcfeature_id);
+    $rfeature = chado_generate_var('feature', $select);
+    // now add to the list
+    $alignment = new stdClass();
+    $alignment->record = $featureloc;
+    $alignment->right_feature = $rfeature;
+    $alignment->name = $rfeature->name;
+    $alignment->type = $rfeature->type_id->name;
+    $alignment->fmin = $featureloc->left_fmin;
+    $alignment->is_fmin_partial = $featureloc->left_is_fmin_partial;
+    $alignment->fmax = $featureloc->left_fmax;
+    $alignment->is_fmax_partial = $featureloc->left_is_fmax_partial;
+    $alignment->phase = $featureloc->left_phase;
+    $alignment->strand = $featureloc->left_strand;
+    $alignment->right_fmin = $featureloc->right_fmin;
+    $alignment->right_is_fmin_partial = $featureloc->right_is_fmin_partial;
+    $alignment->right_fmax = $featureloc->right_fmax;
+    $alignment->right_is_fmax_partial = $featureloc->right_is_fmax_partial;
+    $alignment->right_phase = $featureloc->right_phase;
+    $alignment->right_strand = $featureloc->right_strand;
+    $alignments[] = $alignment;
+    if (property_exists($rfeature, 'nid')) {
+      $alignment->nid = $rfeature->nid;
+    }
+  }
+  $entity->{$field_name}['und'][0]['featurelocs'] = $alignments;
+}
+/**
+ * This function is for features that align through an intermediate such
+ * as 'EST_match' or 'match'.  This occurs in the case where two sequences
+ * align but where one does not align perfectly.  Some ESTs may be in a contig
+ * but not all of the EST.  Portions may overhang and not be included in the
+ * consensus if quality is bad.
+ * For example:
+ *    Feature 1: Contig --------------------
+ *    Feature 2: EST_match           -------
+ *    Feature 3: EST                 ---------
+ *
+ * The feature provided to the function will always be the feature 1.  The
+ * featureloc columns prefixed with 'right' (e.g. right_fmin) belong to the
+ * alignment of feature 3 with feature 2
+ *
+ * Features may align to more than one feature and are not matches. We do
+   * not want to include these, so we have to filter on the SO terms:
+   * match, or %_match
+   *
+   * @ingroup tripal_feature
+   */
+ function chado_linker__featureloc_get_matched_alignments($feature) {
+
+   $sql = "
+     SELECT
+       FL1.featureloc_id    as left_featureloc_id,
+       FL1.srcfeature_id    as left_srcfeature_id,
+       FL1.feature_id       as left_feature_id,
+       FL1.fmin             as left_fmin,
+       FL1.is_fmin_partial  as left_is_fmin_partial,
+       FL1.fmax             as left_fmax,
+       FL1.is_fmax_partial  as left_is_fmax_partial,
+       FL1.strand           as left_strand,
+       FL1.phase            as left_phase,
+       FL1.locgroup         as left_locgroup,
+       FL1.rank             as left_rank,
+       FL2.featureloc_id    as right_featureloc_id,
+       FL2.srcfeature_id    as right_srcfeature_id,
+       FL2.feature_id       as right_feature_id,
+       FL2.fmin             as right_fmin,
+       FL2.is_fmin_partial  as right_is_fmin_partial,
+       FL2.fmax             as right_fmax,
+       FL2.is_fmax_partial  as right_is_fmax_partial,
+       FL2.strand           as right_strand,
+       FL2.phase            as right_phase,
+       FL2.locgroup         as right_locgroup,
+       FL2.rank             as right_rank
+     FROM {feature} F1
+       INNER JOIN {featureloc} FL1 on FL1.srcfeature_id = F1.feature_id
+       INNER JOIN {feature} F2 on FL1.feature_id = F2.feature_id
+       INNER JOIN {featureloc} FL2 on FL2.feature_id = F2.feature_id
+       INNER JOIN {cvterm} CVT2 on F2.type_id = CVT2.cvterm_id
+     WHERE
+       F1.feature_id = :feature_id  AND
+       (CVT2.name = 'match' or CVT2.name like '%_match')
+     ORDER BY FL1.fmin
+   ";
+
+   $results = chado_query($sql, array(':feature_id' => $feature->feature_id));
+
+   // iterate through the results and add them to our featurelocs array
+   $featurelocs = array();
+   while ($fl = $results->fetchObject()) {
+     // ignore featurelocs where the left and right srcfeature is the same
+     if (strcmp($fl->left_srcfeature_id, $fl->right_srcfeature_id) == 0) {
+       continue;
+     }
+     $featurelocs[] = $fl ;
+   }
+   return $featurelocs;
+ }
+
+/**
+ * Implements hook_ws_formatter().
+ */
+function chado_linker__featureloc_ws_formatter(&$element, $entity_type, $entity,
+    $field, $instance, $items) {
+
+}
+
+/**
+ *  Implements hook_widget().
+ */
+function chado_linker__featureloc_widget(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
+
+}
+/**
+ * Callback function for validating the chado_linker_featureloc_widget.
+ */
+function chado_linker__featureloc_widget_validate($element, &$form_state) {
+
+}

+ 48 - 1
tripal_chado/includes/fields/chado_linker__prop.inc

@@ -1,5 +1,52 @@
 <?php
-
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_linker__prop_info() {
+  return array(
+    'label' => t('Add a Property'),
+    'description' => t('Add details about this property.'),
+    'default_widget' => 'chado_linker__prop_widget',
+    'default_formatter' => 'chado_linker__prop_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_linker__prop_widget_info() {
+  return array(
+    'label' => t('Property'),
+    'field types' => array('chado_linker__prop'),
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_linker__prop_formatter_info() {
+  return array(
+    'label' => t('Property'),
+    'field types' => array('chado_linker__prop'),
+    'settings' => array(
+    ),
+  );
+}
 /**
  *
  * @param unknown $entity_type

+ 34 - 14
tripal_chado/includes/fields/chado_linker__prop_adder.inc

@@ -1,21 +1,41 @@
 <?php
-
 /**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ *
+ * Fields that add new fields. These fields are not shown on
+ * pages.  They are avaiable to site curators when adding/updating
+ * a record and allow the user to add new linker table fields.
  *
- * @param unknown $entity_type
- * @param unknown $entity
- * @param unknown $field
- * @param unknown $instance
- * @param unknown $langcode
- * @param unknown $items
- * @param unknown $display
  */
-function chado_linker__prop_adder_formatter(&$element, $entity_type, $entity, $field,
-  $instance, $langcode, $items, $display) {
-
-  foreach ($items as $delta => $item) {
-    // Do nothing, this field is only meant for the form.
-  }
+function chado_linker__prop_adder_info() {
+  return array(
+    'label' => t('Add a Property Type'),
+    'description' => t('This record may have any number of properties. Use
+          this field to first add the type.'),
+    'default_widget' => 'chado_linker__prop_adder_widget',
+    'default_formatter' => 'hidden',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_linker__prop_adder_widget_info() {
+  return array(
+    'label' => t('Add a Property'),
+    'field types' => array('chado_linker__prop_adder'),
+  );
 }
 /**
  *

+ 49 - 1
tripal_chado/includes/fields/chado_linker__pub.inc

@@ -1,5 +1,53 @@
 <?php
-
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_linker__pub_info() {
+  return array(
+    'label' => t('Publications'),
+    'description' => t('Associates a publication (e.g. journal article,
+          conference proceedings, book chapter, etc.) with this record.'),
+    'default_widget' => 'chado_linker__pub_widget',
+    'default_formatter' => 'chado_linker__pub_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_linker__pub_widget_info() {
+  return array(
+    'label' => t('Publications'),
+    'field types' => array('chado_linker__pub'),
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_linker__pub_formatter_info() {
+  return array(
+    'label' => t('Publications'),
+    'field types' => array('chado_linker__pub'),
+    'settings' => array(
+    ),
+  );
+}
 /**
  *
  * @param unknown $entity_type

+ 48 - 1
tripal_chado/includes/fields/chado_linker__synonym.inc

@@ -1,5 +1,52 @@
 <?php
-
+/**
+ * Implements hook_info() for fields.
+ *
+ * This is a hook provided by the tripal_chado module for offloading the
+ * hook_field_info() hook for each field to specify.
+ */
+function chado_linker__synonym_info() {
+  return array(
+    'label' => t('Synonyms'),
+    'description' => t('Adds an alternative name (synonym or alias) to this record.'),
+    'default_widget' => 'chado_linker__synonym_widget',
+    'default_formatter' => 'chado_linker__synonym_formatter',
+    'settings' => array(),
+    'storage' => array(
+      'type' => 'field_chado_storage',
+      'module' => 'tripal_chado',
+      'active' => TRUE
+    ),
+  );
+}
+/**
+ * Implements hook_widget_info.
+ *
+ * This is a hook provided by the tripal_chado module for offloading
+ * the hook_field_widget_info() hook for each field to specify.
+ */
+function chado_linker__synonym_widget_info() {
+  return array(
+    'label' => t('Synonyms'),
+    'field types' => array('chado_linker__synonym'),
+  );
+}
+/**
+ * Implements hook_formatter_info.
+ *
+ * This is a hook provided by the tripal_chado module for
+ * offloading the hook_field_formatter_info() for each field
+ * to specify.
+ *
+ */
+function chado_linker__synonym_formatter_info() {
+  return array(
+    'label' => t('Synonyms'),
+    'field types' => array('chado_linker__synonym'),
+    'settings' => array(
+    ),
+  );
+}
 /**
  *
  * @param unknown $entity_type

+ 107 - 259
tripal_chado/includes/tripal_chado.fields.inc

@@ -3,277 +3,67 @@
 /**
  * Implements hook_field_info().
  *
- * TODO: move these array elements to a hook function that
- * is implemented in the field file.  This will put all of the
- * field info in a single place for each field.  See the formatter_info()
- * function for an example.
+ * This function would normally provide a large info array for all of the
+ * fields provided by this module.  But instead it will call a hook that
+ * can be implmented within each individual field file.  This will allow
+ * all of the code for a single field to be self contained in a single file.
+ *
+ * New fields can be added automatically by including a new file in the
+ * tripal_chado/includes/fields directory.  The file must be named with a
+ * 'chado_' prefix and end with a '.inc' suffix.  After adding the file,
+ * the cache must be cleared.
+ *
  */
 function tripal_chado_field_info() {
-  $fields = array(
-    /*
-     * Generic fields that support multiple base tables.
-     */
-    'chado_base__organism_id' => array(
-      'label' => t('Organism'),
-      'description' => t('A field for specifying an organism.'),
-      'default_widget' => 'chado_base__organism_id_widget',
-      'default_formatter' => 'chado_base__organism_id_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-
-    'chado_base__dbxref_id' => array(
-      'label' => t('Cross reference'),
-      'description' => t('This record can be cross referenced with a record in
-          another online database. This field is intended for the most prominent
-          reference.  At a minimum, the database and accession must be provided.'),
-      'default_widget' => 'chado_base__dbxref_id_widget',
-      'default_formatter' => 'chado_base__dbxref_id_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-
-    /*
-     * Fields that support linker tables.
-     */
-    'chado_linker__cvterm' => array(
-      'label' => t('Annotations'),
-      'description' => t('This record can be annotated with terms
-          from other vocabularies.'),
-      'default_widget' => 'chado_linker__cvterm_widget',
-      'default_formatter' => 'chado_linker__cvterm_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'chado_linker__synonym' => array(
-      'label' => t('Synonyms'),
-      'description' => t('Adds an alternative name (synonym or alias) to this record.'),
-      'default_widget' => 'chado_linker__synonym_widget',
-      'default_formatter' => 'chado_linker__synonym_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'chado_linker__prop' => array(
-      'label' => t('Add a Property'),
-      'description' => t('Add details about this property.'),
-      'default_widget' => 'chado_linker__prop_widget',
-      'default_formatter' => 'chado_linker__prop_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'chado_linker__dbxref' => array(
-      'label' => t('Cross references'),
-      'description' => t('This record can be cross referenced with a record in
-        another online database. This field is intended for one or more
-        references.  At a minimum, the database and accession must be provided.'),
-      'default_widget' => 'chado_linker__dbxref_widget',
-      'default_formatter' => 'chado_linker__dbxref_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'chado_linker__pub' => array(
-      'label' => t('Publications'),
-      'description' => t('Associates a publication (e.g. journal article,
-          conference proceedings, book chapter, etc.) with this record.'),
-      'default_widget' => 'chado_linker__pub_widget',
-      'default_formatter' => 'chado_linker__pub_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    /*
-     * Fields that add new fields. These fields are not shown on
-     * pages.  They are avaiable to site curators when adding/updating
-     * a record and allow the user to add new linker table fields.
-     */
-    'chado_linker__prop_adder' => array(
-      'label' => t('Add a Property Type'),
-      'description' => t('This record may have any number of properties. Use
-          this field to first add the type.'),
-      'default_widget' => 'chado_linker__prop_adder_widget',
-      'default_formatter' => 'hidden',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-
-    // The field provides a widget for adding new vocabularies for cvterm
-    // linker tables. This will allow cvterms to be grouped by vocabulary
-    // ('category').
-    'chado_linker__cvterm_adder' => array(
-      'label' => t('Add an Annotation Type'),
-      'description' => t('This record may have any number of types of
-          annotations. Use this field to first add the type.'),
-      'default_widget' => 'chado_linker__cvterm_adder_widget',
-      'default_formatter' => 'hidden',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    /*
-     * Field specific to the feature table of Chado.
-     */
-    'chado_feature__residues' => array(
-      'label' => t('Residues'),
-      'description' => t('A field for managing nucleotide and protein residues.'),
-      'default_widget' => 'chado_feature__residues_widget',
-      'default_formatter' => 'chado_feature__residues_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'chado_feature__md5checksum' => array(
-      'label' => t('MD5 checksum'),
-      'description' => t('A field for generating MD5 checksum for a sequence.'),
-      'default_widget' => 'chado_feature__md5checksum_widget',
-      'default_formatter' => 'chado_feature__md5checksum_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
-    'chado_feature__seqlen' => array(
-      'label' => t('Sequence length'),
-      'description' => t('A field for calculating the length of a sequence.'),
-      'default_widget' => 'chado_feature__seqlen_widget',
-      'default_formatter' => 'chado_feature__seqlen_formatter',
-      'settings' => array(),
-      'storage' => array(
-        'type' => 'field_chado_storage',
-        'module' => 'tripal_chado',
-        'active' => TRUE
-      ),
-    ),
+  $info = array();
+
+  // Find all of the files in the tripal_chado/includes/fields directory.
+  $fields_path = drupal_get_path('module', 'tripal_chado') . '/includes/fields';
+  $field_files = file_scan_directory($fields_path, '/^chado_.*\.inc$/');
+
+  // Iterate through the fields, include the file and run the info function.
+  foreach ($field_files as $file) {
+    $field_name = $file->name;
+    module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_name);
+    $function = $field_name . '_info';
+    if (function_exists($function)) {
+      $info[$field_name] = $function();
+    }
+  }
+  return $info;
 
-  );
-  return $fields;
 }
 /**
  * Implements hook_field_widget_info().
  *
- * TODO: move these array elements to a hook function that
- * is implemented in the field file.  This will put all of the
- * field info in a single place for each field.  See the formatter_info()
- * function for an example.
+ * This function would normally provide a large info array for all of the
+ * widgets provided by this module.  But instead it will call a hook that
+ * can be implmented within each individual field file.  This will allow
+ * all of the code for a single field to be self contained in a single file.
  */
 function tripal_chado_field_widget_info() {
-  return array(
-    /*
-     * Generic fields that support multiple base tables.
-  */
-    'chado_base__organism_id_widget' => array(
-      'label' => t('Organism Select'),
-      'field types' => array('chado_base__organism_id')
-    ),
-    'chado_base__dbxref_id_widget' => array(
-      'label' => t('Cross reference'),
-      'field types' => array('chado_base__dbxref_id'),
-      'description' => t('This record can be cross referenced with a record in
-        another online database. This field is intended for the most
-        prominent reference.  At a minimum, the database and accession
-        must be provided.'),
-    ),
-
-    /*
-     * Fields that support linker tables.
-     */
-    'chado_linker__pub_widget' => array(
-      'label' => t('Publications'),
-      'field types' => array('chado_linker__pub'),
-    ),
-    'chado_linker__dbxref_widget' => array(
-      'label' => t('Cross references'),
-      'field types' => array('chado_linker__dbxref'),
-      'description' => t('This record can be cross referenced with a record
-        in another online database. This field is intended for the most
-        prominent reference.  At a minimum, the database and accession
-        must be provided.'),
-    ),
+  $widgets = array();
 
-    'chado_linker__cvterm_widget' => array(
-      'label' => t('Annotations'),
-      'field types' => array('chado_linker__cvterm'),
-      'description' => t('This record can be annotated with terms
-          from other vocabularies.'),
-    ),
-    'chado_linker__prop_widget' => array(
-      'label' => t('Property'),
-      'field types' => array('chado_linker__prop'),
-    ),
-    'chado_linker__synonym_widget' => array(
-      'label' => t('Synonyms'),
-      'field types' => array('chado_linker__synonym'),
-    ),
-    /*
-     * Fields that add new fields. These fields are not shown on
-     * pages.  They are avaiable to site curators when adding/updating
-     * a record and allow the user to add new linker table fields.
-     */
-    'chado_linker__prop_adder_widget' => array(
-      'label' => t('Add a Property'),
-      'field types' => array('chado_linker__prop_adder'),
-    ),
-    'chado_linker__cvterm_adder_widget' => array(
-      'label' => t('Add an Annotation'),
-      'field types' => array('chado_linker__cvterm_adder'),
-    ),
-    /*
-     * Field specific to the feature table of Chado.
-     */
-    'chado_feature__md5checksum_widget' => array(
-      'label' => t('MD5 Checksum Checkbox'),
-      'field types' => array('chado_feature__md5checksum'),
-    ),
-    'chado_feature__residues_widget' => array(
-      'label' => t('Residues'),
-      'field types' => array('chado_feature__residues'),
-    ),
-    'chado_feature__seqlen_widget' => array(
-      'label' => t('Sequence Length'),
-      'field types' => array('chado_feature__seqlen'),
-    ),
-  );
+  $fields = field_info_fields();
+  foreach ($fields as $field) {
+    $field_type = $field['type'];
+    if ($field['storage']['type'] == 'field_chado_storage') {
+      module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
+      $function = $field_type . '_widget_info';
+      if (function_exists($function)) {
+        $widgets[$field_type . '_widget'] = $function();
+      }
+    }
+  }
+  return $widgets;
 }
 /**
  * Implements hook_field_formatter_info().
+ *
+ * This function would normally provide a large info array for all of the
+ * formatters provided by this module.  But instead it will call a hook that
+ * can be implmented within each individual field file.  This will allow
+ * all of the code for a single field to be self contained in a single file.
  */
 function tripal_chado_field_formatter_info() {
   $formatters = array();
@@ -333,7 +123,6 @@ function tripal_chado_field_formatter_view($entity_type, $entity, $field,
     $instance, $langcode, $items, $display) {
 
   $element = array();
-
   $field_type = $field['type'];
   module_load_include('inc', 'tripal_chado', 'includes/fields/' . $field_type);
   $function = $display['type'];
@@ -826,6 +615,12 @@ function tripal_chado_add_bundle_fields($entity_type, $bundle, $term) {
   // ADD FIELDS TO BUNDLE
   ////////////////////////////////////////////////////////////////////////////
 
+  /* TODO: the arrays for adding fields should be specified in the field
+   * files themselves so that field developers have complete control over
+   * how the fields behave and what entities they are attached to without
+   * having to edit this function.
+   */
+
   ////
   //
   // Base table fields.
@@ -890,6 +685,14 @@ function tripal_chado_add_bundle_fields($entity_type, $bundle, $term) {
   if (chado_table_exists($pub_table)) {
     tripal_chado_add_bundle_fields_linker__pub_field($entity_type, $bundle_name, $pub_table, $bundle_data['data_table']);
   }
+
+  ////
+  //
+  // Featureloc fields.
+  //
+  if ($bundle_data['data_table'] == 'feature') {
+    tripal_chado_add_bundle_fields_linker__featureloc_field($entity_type, $bundle_name);
+  }
 }
 
 /**
@@ -988,6 +791,51 @@ function tripal_chado_add_bundle_fields_linker__synonym_field($entity_type_name,
 
   tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
 }
+/**
+ * Adds the fields for managing xrefs that are stored in a [base]_dbxref table.
+ *
+ * @param $entity_type
+ * @param $bundle_name
+ * @param $base_table
+ * @param $dbxref_table
+ */
+function tripal_chado_add_bundle_fields_linker__featureloc_field($entity_type_name, $bundle_name) {
+  $field_name = 'featureloc';
+  $schema = chado_get_schema('featureloc');
+  $pkey = $schema['primary key'][0];
+
+  // Initialize the field array.
+  $field_info = array(
+    'field_type' => 'chado_linker__featureloc',
+    'widget_type' => 'chado_linker__featureloc_widget',
+    'widget_settings' => array('display_label' => 1),
+    'description' => '',
+    'label' => 'Alignments',
+    'is_required' => 0,
+    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+    'storage' => 'field_chado_storage',
+    'field_settings' => array(
+      // The Chado table that this field maps to.
+      'chado_table' => 'featureloc',
+      // The column in the chado table that this field maps to.
+      'chado_column' => $pkey,
+      // The base table that this field is connected to.
+      'base_table' => 'feature',
+      'semantic_web' => array(
+        // The type is the term from a vocabulary that desribes this field..
+        'type' => '',
+        // The namepsace for the vocabulary (e.g. 'foaf').
+        'ns' => '',
+        // The URL for the namespace.  It must be that the type can be
+        // appended to the URL.
+        'nsurl' => '',
+      ),
+    ),
+  );
+
+  tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
+}
+
 /**
  * Adds the fields for managing xrefs that are stored in a [base]_dbxref table.
  *