Browse Source

Fixed lots of bugs in the fields

Stephen Ficklin 8 years ago
parent
commit
15959fd25f

+ 11 - 4
tripal/includes/TripalEntityUIController.inc

@@ -180,11 +180,18 @@ function tripal_view_entity($entity, $view_mode = 'full') {
    // For each entity retrieved add a row to the data listing.
    while ($entity = $entities->fetchObject()) {
 
+     $namespace = '';
+     $term_name = '';
+
      // Get the term
      $term = entity_load('TripalTerm', array('id' => $entity->term_id));
      $term = reset($term);
-     $vocab = entity_load('TripalVocab', array('id' => $term->vocab_id));
-     $vocab = reset($vocab);
+     if ($term) {
+       $term_name = $term->name;
+       $vocab = entity_load('TripalVocab', array('id' => $term->vocab_id));
+       $vocab = reset($vocab);
+       $namespace = $vocab->namespace;
+     }
 
      // Retrieve details about the user who created this data.
      $author = user_load($entity->uid);
@@ -192,8 +199,8 @@ function tripal_view_entity($entity, $view_mode = 'full') {
      // Add information to the table.
      $rows[] = array(
        l($entity->title, 'bio_data/' . $entity->id),
-       $vocab->namespace,
-       $term->name,
+       $namespace,
+       $term_name,
        l($author->name, 'user/' . $entity->uid),
        $entity->status == 1 ? 'published' : 'unpublished',
        format_date($entity->changed, 'short'),

+ 45 - 3
tripal/includes/TripalField.inc

@@ -128,9 +128,8 @@ class TripalField {
    *  the web page.  The content returned by the formatter should only include
    *  what is present in the $items[$delta]['values] array. This way, the
    *  contents that are displayed on the page, via webservices and downloaded
-   *  into a CSV file will always be identical.  It should also include all of
-   *  the data in the $items[$delta]['values] array so that all the data is
-   *  present everywhere.
+   *  into a CSV file will always be identical.  The view need not show all
+   *  of the data in the 'values' array.
    *
    *  @param $element
    *  @param $entity_type
@@ -249,7 +248,50 @@ class TripalField {
    *   TRUE if the field already has data, FALSE if not.
    */
   public function settings_form($field, $instance, $has_data) {
+    $settings = $field['settings'];
+    $element = array();
 
+    $element['semantic_web'] = array(
+      '#type' => 'fieldset',
+      '#title' => 'Semantic Web',
+      '#description' => t('Each field must be associated with a term
+          from a controlled vocabulary.  This allows computer programs to understand
+          the data provided on this site.  Please be cautions changing these
+          values.  Defaults are set by Tripal and sites that use the same
+          terms can exchange information.'),
+      '#collapsed' => TRUE,
+      '#collapsible' => TRUE,
+      '#tree' => TRUE,
+    );
+
+    $element['semantic_web']['name'] = array(
+      '#type' => 'textfield',
+      '#title' => 'Term Name',
+      '#description' => t('The name of the term (e.g. gene, mRNA, organism, etc.).'),
+      '#default_value' => $settings['semantic_web']['name'],
+    );
+    $element['semantic_web']['accession'] = array(
+      '#type' => 'textfield',
+      '#title' => 'Term ID',
+      '#description' => t('The unique term ID (accession) in the vocabulary (e.g. ' .
+          'for the term "gene" in the Sequence Ontology, the accession is "0000704").'),
+      '#default_value' => $settings['semantic_web']['accession'],
+    );
+    $element['semantic_web']['ns'] = array(
+      '#type' => 'textfield',
+      '#title' => 'Vocabulary Namespace',
+      '#description' => t('The namespace for the vocabulary to which this term ' .
+          'belongs (e.g. the namespace for the Sequence Ontology is "SO"). This '.
+          'value is prefixed to the Term ID to form the complete id (e.g. "SO:0000704")'),
+      '#default_value' => $settings['semantic_web']['ns'],
+    );
+    $element['semantic_web']['nsurl'] = array(
+      '#type' => 'textfield',
+      '#title' => 'Vocabulary URL',
+      '#description' => t('The web URL of the vocabulary..'),
+      '#default_value' => $settings['semantic_web']['nsurl'],
+    );
+    return $element;
   }
 
   /**

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

@@ -235,7 +235,7 @@ function chado_insert_property($record, $property, $options = array()) {
          "The property is already assigned to the record with the following " .
          "rank.  And, because the 'force_rank' option is used, the property " .
          "cannot be added: %property.",
-          array('%property' => print_r($property, true)));
+          array('%property' => print_r($property, TRUE)));
         return FALSE;
       }
     }

+ 0 - 13
tripal_chado/includes/fields/chado_base__dbxref_id.inc

@@ -277,19 +277,6 @@ class chado_base__dbxref_id extends TripalField {
       }
     }
   }
-
-
-  /**
-   * @see TripalField::ws_formatter()
-   */
-  function ws_formatter($entity_type, $entity, $field, $instance, $items) {
-
-    $dbxref = $entity->chado_record->dbxref_id;
-
-    unset($dbxref->tablename);
-    unset($dbxref->db_id->tablename);
-    return $dbxref;
-  }
 }
 
 /**

+ 23 - 33
tripal_chado/includes/fields/chado_base__organism_id.inc

@@ -41,6 +41,12 @@ class chado_base__organism_id extends TripalField {
       return $field_info;
     }
 
+    // If this is the organism table then do not attach as that is the
+    // primary key
+    if ($table_name == 'organism') {
+      return $field_info;
+    }
+
     // There is an organism_id column so attach the field!
     $field_info = array(
       'field_name' => $table_name . '__organism_id',
@@ -95,11 +101,16 @@ class chado_base__organism_id extends TripalField {
   public function formatter_view(&$element, $entity_type, $entity,
       $field, $instance, $langcode, $items, $display) {
 
+    $content =  $items[0]['value'];
+    if (array_key_exists('entity_id', $items[0])) {
+      $content = l(strip_tags($items[0]['value']), 'bio_data/' . $items[0]['entity_id']);
+    }
+
     // 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'],
+      '#markup' => $content,
     );
   }
 
@@ -109,13 +120,18 @@ class chado_base__organism_id extends TripalField {
   public function widget_form(&$widget, $form, $form_state, $field, $instance,
       $langcode, $items, $delta, $element) {
 
+    $default_value = 0;
+    if (array_key_exists('organism_id', $items[0])) {
+      $default_value = $items[0]['organism_id'];
+    }
+
     $options = tripal_get_organism_select_options(FALSE);
     $widget['value'] = array(
       '#type' => 'select',
       '#title' => $element['#title'],
       '#description' => $element['#description'],
       '#options' => $options,
-      '#default_value' => count($items) > 0 ? $items[0]['organism_id'] : 0,
+      '#default_value' => $default_value,
       '#required' => $element['#required'],
       '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
       '#delta' => $delta,
@@ -127,17 +143,6 @@ class chado_base__organism_id extends TripalField {
     );
   }
 
-  /**
-   * @see TripalField::ws_formatter()
-   */
-  public function ws_formatter($entity_type, $entity, $field, $instance, $items) {
-
-    $organism = (array) $entity->chado_record->organism_id;
-    unset($organism->tablename);
-
-    return $organism;
-  }
-
   /**
    * @see TripalField::load()
    */
@@ -169,23 +174,11 @@ class chado_base__organism_id extends TripalField {
   /**
    * @see TripalField::settings_form()
    */
-  public function settings_form($field, $instance, $view_mode) {
+  public function settings_form($field, $instance, $has_data) {
 
     $settings = $field['settings'];
 
     $element = array();
-    $term = NULL;
-    $entity = NULL;
-
-    // Check to see if the organism bundle exists
-    $term = tripal_load_term_entity(array(
-      'namespace' => $field['settings']['semantic_web']['ns'],
-      'accession' => $field['settings']['semantic_web']['accession']
-    ));
-    if ($term) {
-      $entity = tripal_load_bundle_entity(array('term_id' => $term->id));
-    }
-
     $element['instructions'] = array(
       '#type' => 'item',
       '#markup' => 'You may rewrite the way this field is presented to the end-user.
@@ -240,16 +233,13 @@ class chado_base__organism_id extends TripalField {
       '#markup' => theme_table($table_vars),
     );
 
+    // Add in the semantic web fields.
+    $parent_elements = parent::settings_form($field, $instance, $has_data);
+    $element = array_merge($element, $parent_elements);
+
     return $element;
   }
 
-
-  /**
-   * @see TripalField::views_data()
-   */
-  public function views_data_alter(&$data, $field, $entity_info) {
-    dpm($data);
-  }
 }
 
 

+ 122 - 155
tripal_chado/includes/fields/chado_feature__md5checksum.inc

@@ -1,153 +1,137 @@
 <?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_attach_info().
- *
- * This is a hook provided by the tripal_chado module. It allows the field
- * to specify which bundles it will attach to and to specify the settings.
- *
- * @param $entity_type
- * @param $entity
- * @param $term
- *
- * @return
- *   A field array
- */
-function chado_feature__md5checksum_attach_info($entity_type, $bundle, $target) {
-  $field_info = array();
 
-  $table_name = $target['data_table'];
-  $type_table = $target['type_table'];
-  $type_field = $target['field'];
-  $cv_id      = $target['cv_id'];
-  $cvterm_id  = $target['cvterm_id'];
+class chado_feature__md5checksum  extends TripalField {
+
+  /**
+   * @see TripalField::field_info()
+   */
+  function field_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
+      ),
+    );
+  }
+
+  /**
+   * @see TripalField::attach_info()
+   */
+  function attach_info($entity_type, $bundle, $settings) {
+    $field_info = array();
+
+    $table_name = $settings['data_table'];
+    $type_table = $settings['type_table'];
+    $type_field = $settings['field'];
+    $cv_id      = $settings['cv_id'];
+    $cvterm_id  = $settings['cvterm_id'];
+
 
+    // If  this is not the feature table then we don't want to attach.
+    if ($table_name != 'feature') {
+      return $field_info;
+    }
 
-  // If  this is not the feature table then we don't want to attach.
-  if ($table_name != 'feature') {
+    // Create an array with information about this field.
+    $field_info = array(
+      'field_name' => 'feature__md5checksum',
+      'field_type' => 'chado_feature__md5checksum',
+      'widget_type' => 'chado_feature__md5checksum_widget',
+      'description' => 'The MD5 checksum for the sequence.',
+      'label' => 'MD5 Checksum',
+      'is_required' => 0,
+      'storage' => 'field_chado_storage',
+      'widget_settings' => array(
+        'display_label' => 1
+      ),
+      'field_settings' => array(
+        'chado_table' => $table_name,
+        'chado_column' => 'md5checksum',
+        'semantic_web' => array(
+          'name' => 'md5_checksum',
+          'accession' => 'md5_checksum',
+          'ns' => 'local',
+          'nsurl' => '',
+        ),
+      ),
+    );
     return $field_info;
   }
 
-  // Create an array with information about this field.
-  $field_info = array(
-    'field_name' => 'feature__md5checksum',
-    'field_type' => 'chado_feature__md5checksum',
-    'widget_type' => 'chado_feature__md5checksum_widget',
-    'description' => 'The MD5 checksum for the sequence.',
-    'label' => 'MD5 Checksum',
-    'is_required' => 0,
-    'storage' => 'field_chado_storage',
-    'widget_settings' => array(
-      'display_label' => 1
-    ),
-    'field_settings' => array(
-      'chado_table' => $table_name,
-      'chado_column' => 'md5checksum',
-      'semantic_web' => array(
-        'name' => '',
-        'accession' => '',
-        'ns' => '',
-        'nsurl' => '',
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
+    return array(
+      'label' => t('MD5 Checksum Checkbox'),
+      'field types' => array('chado_feature__md5checksum'),
+    );
+  }
+
+  /**
+   * @see TripalField::formatter_info()
+   */
+  function formatter_info() {
+    return array(
+      'label' => t('MD5 Checksum'),
+      'field types' => array('chado_feature__md5checksum'),
+      'settings' => array(
       ),
-    ),
-  );
-  return $field_info;
-}
-/**
- * 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(
-    ),
-  );
-}
+    );
+  }
 
-/**
- *
- * @param unknown $entity_type
- * @param unknown $entity
- * @param unknown $field
- * @param unknown $instance
- * @param unknown $langcode
- * @param unknown $items
- * @param unknown $display
- */
-function chado_feature__md5checksum_formatter(&$element, $entity_type, $entity, $field,
-    $instance, $langcode, $items, $display) {
-  foreach ($items as $delta => $item) {
-    $content = key_exists('value', $item) ? $item['value'] : '';
-    $element[$delta] = array(
-      // We create a render array to produce the desired markup,
-      '#type' => 'markup',
-      '#markup' => $content,
+  /**
+   * @see TripalField::formatter_view()
+   */
+  function formatter_view(&$element, $entity_type, $entity, $field,
+      $instance, $langcode, $items, $display) {
+    foreach ($items as $delta => $item) {
+      $content = key_exists('value', $item) ? $item['value'] : '';
+      $element[$delta] = array(
+        // We create a render array to produce the desired markup,
+        '#type' => 'markup',
+        '#markup' => $content,
+      );
+    }
+  }
+
+  /**
+   * @see TripalField::widget_form()
+   */
+  function widget_form(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
+
+    $widget['value'] = array(
+      '#type' => 'checkbox',
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#options' => array(0, 1),
+      '#default_value' => 1,
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#delta' => $delta,
+      '#element_validate' => array('chado_feature__md5checksum_widget_validate'),
     );
   }
+
+
+  /**
+   * @see TripalField::load()
+   */
+  function load($field, $entity, $details) {
+    $record = $details['record'];
+
+    $field_name = $field['field_name'];
+    if ($record and property_exists($record, 'md5checksum')) {
+      $entity->{$field_name}['und'][] = array('value' => $record->md5checksum);
+    }
+  }
 }
-/**
- *
- * @param unknown $field_name
- * @param unknown $widget
- * @param unknown $form
- * @param unknown $form_state
- * @param unknown $field
- * @param unknown $instance
- * @param unknown $langcode
- * @param unknown $items
- * @param unknown $delta
- * @param unknown $element
- */
-function chado_feature__md5checksum_widget(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
-
-  $widget['value'] = array(
-    '#type' => 'checkbox',
-    '#title' => $element['#title'],
-    '#description' => $element['#description'],
-    '#options' => array(0, 1),
-    '#default_value' => 1,
-    '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
-    '#delta' => $delta,
-    '#element_validate' => array('chado_feature__md5checksum_widget_validate'),
-  );
-}
+
 /**
  * Callback function for validating the chado_feature__md5checksum_widget.
  */
@@ -165,21 +149,4 @@ function chado_feature__md5checksum_widget_validate($element, &$form_state) {
     // Otherwise, remove the md5 value
     tripal_chado_set_field_form_values($field_name, $form_state, '__NULL__');
   }
-}
-
-/**
- * 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.
- *
- * @param $field
- * @param $entity
- * @param $record
- */
-function chado_feature__md5checksum_load($field, $entity, $record) {
-  $field_name = $field['field_name'];
-  if ($record and property_exists($record, 'md5checksum')) {
-    $entity->{$field_name}['und'][] = array('value' => $record->md5checksum);
-  }
 }

+ 144 - 137
tripal_chado/includes/fields/chado_feature__residues.inc

@@ -1,152 +1,159 @@
 <?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_attach_info().
- *
- * This is a hook provided by the tripal_Chado module. It allows the field
- * to specify which bundles it will attach to and to specify thee settings.
- *
- * @param $entity_type
- * @param $entity
- * @param $term
- *
- * @return
- *   A field array
- */
-function chado_feature__residues_attach_info($entity_type, $bundle, $target) {
-  $field_info = array();
 
-  $table_name = $target['data_table'];
-  $type_table = $target['type_table'];
-  $type_field = $target['field'];
-  $cv_id      = $target['cv_id'];
-  $cvterm_id  = $target['cvterm_id'];
+class chado_feature__residues extends TripalField {
+
+  /**
+   * 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 field_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(),
+      'instance_settings' => array('text_processing' => 1, 'display_summary' => 0),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    );
+  }
+  /**
+   * Implements hook_attach_info().
+   *
+   * This is a hook provided by the tripal_Chado module. It allows the field
+   * to specify which bundles it will attach to and to specify thee settings.
+   *
+   * @param $entity_type
+   * @param $entity
+   * @param $term
+   *
+   * @return
+   *   A field array
+   */
+  function attach_info($entity_type, $bundle, $settings) {
+    $field_info = array();
+
+    $table_name = $settings['data_table'];
+    $type_table = $settings['type_table'];
+    $type_field = $settings['field'];
+    $cv_id      = $settings['cv_id'];
+    $cvterm_id  = $settings['cvterm_id'];
+
 
+    // If  this is not the feature table then we don't want to attach.
+    if ($table_name != 'feature') {
+      return $field_info;
+    }
 
-  // If  this is not the feature table then we don't want to attach.
-  if ($table_name != 'feature') {
+    $field_info = array(
+      'field_name' => 'feature__residues',
+      'field_type' => 'chado_feature__residues',
+      'widget_type' => 'chado_feature__residues_widget',
+      'description' => 'An IUPAC compatible residues for this feature.',
+      'label' => 'Residues',
+      'is_required' => 0,
+      'storage' => 'field_chado_storage',
+      'widget_settings' => array(
+        'display_label' => 1
+      ),
+      'field_settings' => array(
+        'chado_table' => $table_name,
+        'chado_column' => 'residues',
+        'semantic_web' => array(
+          'name' => '',
+          'accession' => '',
+          'ns' => '',
+          'nsurl' => '',
+        ),
+      ),
+    );
     return $field_info;
   }
+  /**
+   * 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 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 formatter_info() {
+    return array(
+      'label' => t('Residues'),
+      'field types' => array('chado_feature__residues'),
+    );
+  }
+  /**
+   *
+   * @param unknown $entity_type
+   * @param unknown $entity
+   * @param unknown $field
+   * @param unknown $instance
+   * @param unknown $langcode
+   * @param unknown $items
+   * @param unknown $display
+   */
+  function formatter_view(&$element, $entity_type, $entity, $field,
+    $instance, $langcode, $items, $display) {
 
-  $field_info = array(
-    'field_name' => 'feature__residues',
-    'field_type' => 'chado_feature__residues',
-    'widget_type' => 'chado_feature__residues_widget',
-    'description' => 'An IUPAC compatible residues for this feature.',
-    'label' => 'Residues',
-    'is_required' => 0,
-    'storage' => 'field_chado_storage',
-    'widget_settings' => array(
-      'display_label' => 1
-    ),
-    'field_settings' => array(
-      'chado_table' => $table_name,
-      'chado_column' => 'residues',
-      'semantic_web' => array(
-        'name' => '',
-        'accession' => '',
-        'ns' => '',
-        'nsurl' => '',
-      ),
-    ),
-  );
-  return $field_info;
-}
-/**
- * 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
- * @param unknown $entity
- * @param unknown $field
- * @param unknown $instance
- * @param unknown $langcode
- * @param unknown $items
- * @param unknown $display
- */
-function chado_feature__residues_formatter(&$element, $entity_type, $entity, $field,
-  $instance, $langcode, $items, $display) {
+    foreach ($items as $delta => $item) {
+      $residues = key_exists('value', $item) ? $item['value'] : '';
+      $content = '<pre class="residues-formatter">' . $residues . '</pre>';
+      $element[$delta] = array(
+        // We create a render array to produce the desired markup,
+        '#type' => 'markup',
+        '#markup' => $content,
+      );
+    }
+  }
 
-  foreach ($items as $delta => $item) {
-    $residues = key_exists('value', $item) ? $item['value'] : '';
-    $content = '<pre class="residues-formatter">' . $residues . '</pre>';
-    $element[$delta] = array(
-      // We create a render array to produce the desired markup,
-      '#type' => 'markup',
-      '#markup' => $content,
+  /**
+   *
+   * @param unknown $field_name
+   * @param unknown $widget
+   * @param unknown $form
+   * @param unknown $form_state
+   * @param unknown $field
+   * @param unknown $instance
+   * @param unknown $langcode
+   * @param unknown $items
+   * @param unknown $delta
+   * @param unknown $element
+   */
+  function widget_form(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
+
+    $widget['value'] = array(
+      '#type' => 'textarea',
+      '#title' => $element['#title'],
+      '#description' => $element['#description'],
+      '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
+      '#default_value' => count($items) > 0 ? $items[0]['value'] : '',
+      '#delta' => $delta,
+      '#element_validate' => array('chado_feature__residues_widget_validate'),
+      '#cols' => 30,
     );
   }
-}
 
-/**
- *
- * @param unknown $field_name
- * @param unknown $widget
- * @param unknown $form
- * @param unknown $form_state
- * @param unknown $field
- * @param unknown $instance
- * @param unknown $langcode
- * @param unknown $items
- * @param unknown $delta
- * @param unknown $element
- */
-function chado_feature__residues_widget(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
-
-  $widget['value'] = array(
-    '#type' => 'textarea',
-    '#title' => $element['#title'],
-    '#description' => $element['#description'],
-    '#weight' => isset($element['#weight']) ? $element['#weight'] : 0,
-    '#default_value' => count($items) > 0 ? $items[0]['value'] : '',
-    '#delta' => $delta,
-    '#element_validate' => array('chado_feature__residues_widget_validate'),
-    '#cols' => 30,
-  );
 }
+
 /**
  * Callback function for validating the chado_feature__residues_widget.
  */

+ 9 - 5
tripal_chado/includes/fields/chado_gene__transcripts.inc

@@ -119,7 +119,7 @@ class chado_gene__transcripts extends TripalField {
     $headers = array('Feature Name', 'Unique Name', 'Type', 'Location');
     $rows = array();
     foreach ($items as $delta => $item) {
-      $entity_id = $item['entity_id'];
+
       $transcript = $item['value'];
 
       // Get the field values
@@ -129,7 +129,8 @@ class chado_gene__transcripts extends TripalField {
       $type = $transcript['type'];
 
       // Add a link i there is an entity.
-      if ($entity_id) {
+      if (array_key_exists('entity_id', $transcript) and $transcript['$entity_id']) {
+        $entity_id = $transcript['entity_id'];
         $feature_name = l($feature_name, "bio_data/" . $entity_id, array('attributes' => array('target' => "_blank")));
       }
       $rows[] = array($feature_name, $feature_uname, $type, $loc);
@@ -185,7 +186,7 @@ class chado_gene__transcripts extends TripalField {
     foreach ($transcripts as $transcript) {
       // link the feature to it's node
       $feature_name = $transcript->record->subject_id->name;
-      $entity_id = $transcript->record->subject_id->entity_id;
+
       $locations = $transcript->child_featurelocs;
       $loc = "";
       foreach ($locations AS $location) {
@@ -198,8 +199,11 @@ class chado_gene__transcripts extends TripalField {
         'location' => $loc,
 
       );
-      $entity->{$field_name}['und'][$i]['entity_id'] = $entity_id;
-      $entity->{$field_name}['und'][$i]['entity_type'] = 'TripalEntity';
+      if (property_exists($transcript->record->subject_id, 'entity_id')) {
+        $entity_id = $transcript->record->subject_id->entity_id;
+        $entity->{$field_name}['und'][$i]['entity_id'] = $entity_id;
+        $entity->{$field_name}['und'][$i]['entity_type'] = 'TripalEntity';
+      }
       $i++;
     }
   }

+ 14 - 3
tripal_chado/includes/fields/chado_linker__contact.inc

@@ -66,9 +66,9 @@ class chado_linker__contact extends TripalField {
         'chado_column' => $pkey,
         'base_table' => $table_name,
         'semantic_web' => array(
-          'name' => '',
-          'accession' => '',
-          'ns' => '',
+          'name' => 'contact',
+          'accession' => 'contact',
+          'ns' => 'local',
           'nsurl' => '',
         ),
       ),
@@ -145,8 +145,19 @@ class chado_linker__contact extends TripalField {
     }
   }
 
+  /**
+   * @see TripalField::settings_form()
+   */
   public function settings_form($field, $instance, $has_data) {
+    $element = array();
 
+    // TODO: add settings here.
+
+    // Add in the semantic web fields.
+    $parent_elements = parent::settings_form($field, $instance, $has_data);
+    $element = array_merge($element, $parent_elements);
+
+    return $element;
   }
 
 

+ 1 - 0
tripal_chado/includes/fields/chado_linker__cvterm_adder.inc

@@ -23,6 +23,7 @@ function chado_linker__cvterm_adder_info() {
       'module' => 'tripal_chado',
       'active' => TRUE
     ),
+    'no_ui' => TRUE
   );
 }
 /**

+ 0 - 25
tripal_chado/includes/fields/chado_linker__dbxref.inc

@@ -459,29 +459,4 @@ function chado_linker__dbxref_load($field, $entity, $base_table, $record) {
       $i++;
     }
   }
-}
-
-/**
- * Implements hook_ws_formatter().
- */
-function chado_linker__dbxref_ws_formatter($entity_type, $entity,
-    $field, $instance, $items) {
-
-  $field_name = $field['field_name'];
-  $field_type = $field['type'];
-  $chado_table = $field['settings']['chado_table'];
-  $record = $entity->chado_record;
-
-  $values = array();
-  $options = array('return_array' => 1);
-  $record = chado_expand_var($record, 'table', $chado_table, $options);
-  $linker_dbxrefs = $record->$chado_table;
-  foreach ($linker_dbxrefs as $linker_dbxref) {
-    $dbxref = $linker_dbxref->dbxref_id;
-    unset($dbxref->tablename);
-    unset($dbxref->db_id->tablename);
-    $values[] = $dbxref;
-  }
-
-  return $values;
 }

+ 1 - 1
tripal_chado/includes/fields/chado_linker__expression.inc

@@ -141,7 +141,7 @@ class chado_linker__expression extends TripalField {
 
         $i++;
       }
-    }dpm($record);
+    }
   }
 
   public function settings_form($field, $instance, $has_data) {

+ 1 - 0
tripal_chado/includes/fields/chado_linker__prop_adder.inc

@@ -23,6 +23,7 @@ function chado_linker__prop_adder_info() {
       'module' => 'tripal_chado',
       'active' => TRUE
     ),
+    'no_ui' => TRUE
   );
 }
 /**

+ 4 - 4
tripal_chado/includes/fields/chado_linker__pub.inc

@@ -67,10 +67,10 @@ function chado_linker__pub_attach_info($entity_type, $bundle, $target) {
       'chado_column' => $pkey,
       'base_table' => $table_name,
       'semantic_web' => array(
-        'name' => '',
-        'accession' => '',
-        'ns' => '',
-        'nsurl' => '',
+        'name' => 'publication',
+        'accession' => 'publication',
+        'ns' => 'schema',
+        'nsurl' => 'https://schema.org/',
       ),
     ),
   );

+ 312 - 365
tripal_chado/includes/fields/chado_linker__relationship.inc

@@ -1,394 +1,341 @@
 <?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__relationship_info() {
-  return array(
-    'label' => t('Relationships'),
-    'description' => t('Relationships between features.'),
-    'default_widget' => 'chado_linker__relationship_widget',
-    'default_formatter' => 'chado_linker__relationship_formatter',
-    'settings' => array(),
-    'storage' => array(
-      'type' => 'field_chado_storage',
-      'module' => 'tripal_chado',
-      'active' => TRUE
-    ),
-  );
-}
-/**
- * Implements hook_attach_info().
- *
- * This is a hook provided by the tripal_Chado module. It allows the field
- * to specify which bundles it will attach to and to specify thee settings.
- *
- * @param $entity_type
- * @param $entity
- * @param $term
- *
- * @return
- *   A field array
- */
-function chado_linker__relationship_attach_info($entity_type, $bundle, $target) {
-  $field_info = array();
-
-  $table_name = $target['data_table'];
-  $type_table = $target['type_table'];
-  $type_field = $target['field'];
-  $cv_id      = $target['cv_id'];
-  $cvterm_id  = $target['cvterm_id'];
-
-  // If the linker table does not exists then we don't want to add attach.
-  $rel_table = $table_name . '_relationship';
-  if (!chado_table_exists($rel_table)) {
-    return $field_info;
+class chado_linker__relationship extends TripalField {
+  /**
+   * @see TripalField::field_info()
+   */
+  function field_info() {
+    return array(
+      'label' => t('Relationships'),
+      'description' => t('Relationships between records.'),
+      'default_widget' => 'chado_linker__relationship_widget',
+      'default_formatter' => 'chado_linker__relationship_formatter',
+      'settings' => array(),
+      'storage' => array(
+        'type' => 'field_chado_storage',
+        'module' => 'tripal_chado',
+        'active' => TRUE
+      ),
+    );
   }
 
-  $schema = chado_get_schema($rel_table);
-  $pkey = $schema['primary key'][0];
+  /**
+   * @see TripalField::attach_info()
+   */
+  function attach_info($entity_type, $bundle, $target) {
+    $field_info = array();
+
+    $table_name = $target['data_table'];
+    $type_table = $target['type_table'];
+    $type_field = $target['field'];
+    $cv_id      = $target['cv_id'];
+    $cvterm_id  = $target['cvterm_id'];
+
+    // If the linker table does not exists then we don't want to add attach.
+    $rel_table = $table_name . '_relationship';
+    if (!chado_table_exists($rel_table)) {
+      return $field_info;
+    }
 
-  // Initialize the field array.
-  $field_info = array(
-    'field_name' => $table_name . '__relationship',
-    'field_type' => 'chado_linker__relationship',
-    'widget_type' => 'chado_linker__relationship_widget',
-    'widget_settings' => array('display_label' => 1),
-    'description' => 'A generic field for displaying relationships between data types',
-    'label' => 'Relationships',
-    'is_required' => 0,
-    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-    'storage' => 'field_chado_storage',
-    'field_settings' => array(
-      'chado_table' => $rel_table,
-      'chado_column' => $pkey,
-      'base_table' => $table_name,
-      'semantic_web' => array(
-        'name' => '',
-        'accession' => '',
-        'ns' => '',
-        'nsurl' => '',
+    $schema = chado_get_schema($rel_table);
+    $pkey = $schema['primary key'][0];
+
+    // Initialize the field array.
+    $field_info = array(
+      'field_name' => $table_name . '__relationship',
+      'field_type' => 'chado_linker__relationship',
+      'widget_type' => 'chado_linker__relationship_widget',
+      'widget_settings' => array('display_label' => 1),
+      'description' => 'A generic field for displaying relationships between data types',
+      'label' => 'Relationships',
+      'is_required' => 0,
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'storage' => 'field_chado_storage',
+      'field_settings' => array(
+        'chado_table' => $rel_table,
+        'chado_column' => $pkey,
+        'base_table' => $table_name,
+        'semantic_web' => array(
+          'name' => 'relationship',
+          'accession' => 'relationship',
+          'ns' => 'local',
+          'nsurl' => '',
+        ),
       ),
-    ),
-  );
-
-  return $field_info;
-
-}
-/**
- * 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__relationship_widget_info() {
-  return array(
-    'label' => t('Relationship Settings'),
-    'field types' => array('chado_linker__relationship')
-  );
-}
-/**
- * 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__relationship_formatter_info() {
-  return array(
-    'label' => t('Relationships'),
-    'field types' => array('chado_linker__relationship'),
-    '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__relationship_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__relationship_formatter_settings_form($field, $instance,
-    $view_mode, $form, &$form_state) {
-
-
-
-}
-
-/**
- * Validation function for the chado_linker_featureloc_formatter_settings_form.
- */
-function chado_linker__relationship_formatter_settings_form_validate(&$form, &$form_state) {
-
-  // Place here as an example for validating the settings form.
-}
-
-/**
- * TODO: because this field is meant to handle any xxxxx_relationship table
- * then feature hard-coding needs to be replaced as it won't work for
- * stocks, etc.
- */
-function chado_linker__relationship_formatter(&$element, $entity_type, $entity,
-    $field, $instance, $langcode, $items, $display) {
-
-  // Get the settings
-  $settings = $display['settings'];
-  $record = $entity->chado_record;
-
-  foreach ($items as $delta => $item) {
-
-    $all_relationships = $item['all_relationships'];
-    $object_rels = $all_relationships['object'];
-    $subject_rels = $all_relationships['subject'];
-    $content = '';
+    );
 
-    if (count($object_rels) > 0 or count($subject_rels) > 0) {
+    return $field_info;
 
-      // first add in the subject relationships.
-      foreach ($subject_rels as $rel_type => $rels){
-        foreach ($rels as $obj_type => $objects){
+  }
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
+    return array(
+      'label' => t('Relationship Settings'),
+      'field types' => array('chado_linker__relationship')
+    );
+  }
+  /**
+   * @see TripalField::formatter_info()
+   */
+  function formatter_info() {
+    return array(
+      'label' => t('Relationships'),
+      'field types' => array('chado_linker__relationship'),
+      'settings' => array(
+      ),
+    );
+  }
 
-          // Make the verb in the sentence make sense in English.
-          switch ($rel_type) {
-            case 'integral part of':
-            case 'instance of':
-              $verb = 'is an';
-              break;
-            case 'proper part of':
-            case 'transformation of':
-            case 'genome of':
-            case 'part of':
-            case 'position of':
-            case 'sequence of':
-            case 'variant of':
-              $verb = 'is a';
-              break;
-            case 'derives from':
-            case 'connects on':
-            case 'contains':
-            case 'finishes':
-            case 'guides':
-            case 'has origin':
-            case 'has part':
-            case 'has quality':
-            case 'is consecutive sequence of':
-            case 'maximally overlaps':
-            case 'overlaps':
-            case 'starts':
-              $verb = '';
-              break;
-            default:
-              $verb = 'is';
-          }
+  /**
+   * @see TripalField::formatter_view()
+   */
+  function formatter_view(&$element, $entity_type, $entity,
+      $field, $instance, $langcode, $items, $display) {
 
-          // 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('Feature Name' ,'Unique Name', 'Species', 'Type');
+    // Get the settings
+    $settings = $display['settings'];
 
-          // 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();
+    $rows = array();
+    $headers = array('Subject' ,'Type', 'Object');
+    $headers = array('Relationship');
 
-          foreach ($objects as $object){
-            // link the feature to it's node
-            $feature_name = $object->record->object_id->name;
-            if (property_exists($object->record, 'nid')) {
-              $feature_name = l($feature_name, "node/" . $object->record->nid, array('attributes' => array('target' => "_blank")));
-            }
-            // link the organism to it's node
-            $organism = $object->record->object_id->organism_id;
-            $organism_name = $organism->genus ." " . $organism->species;
-            if (property_exists($organism, 'nid')) {
-              $organism_name = l("<i>" . $organism->genus . " " . $organism->species . "</i>", "node/" . $organism->nid, array('html' => TRUE));
-            }
-            $rows[] = array(
-              array('data' => $feature_name, 'width' => '30%'),
-              array('data' => $object->record->object_id->uniquename, 'width' => '30%'),
-              array('data' => $organism_name, 'width' => '30%'),
-              array('data' => $object->record->object_id->type_id->name, 'width' => '10%'),
-            );
-           }
-           // 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-relationship-object',
-               'class' => 'tripal-data-table'
-             ),
-             'sticky' => FALSE,
-             'caption' => "This " . $record->type_id->name . " $verb  $rel_type the following  <b>$obj_type</b> feature(s):",
-             'colgroups' => array(),
-             'empty' => '',
-           );
+    $this_name = $entity->chado_record->name;
+    if (property_exists($entity->chado_record, 'uniquename')) {
+      $this_name = $entity->chado_record->uniquename;
+    }
 
-           // once we have our table array structure defined, we call Drupal's theme_table()
-           // function to generate the table.
-           $content .= theme_table($table);
-         }
+    foreach ($items as $delta => $item) {
+      $subject_name = $item['value']['subject']['name'];
+      $subject_type = $item['value']['subject']['type'];
+      $object_name = $item['value']['object']['name'];
+      $object_type = $item['value']['object']['type'];
+      $phrase = $item['value']['phrase'];
+
+      // 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 ($subject_type != 'polypeptide')) {
+        continue;
+      }
+      if ($subject_type == 'mRNA' and ($object_type != 'gene')) {
+        continue;
       }
 
-      // second add in the object relationships.
-      foreach ($object_rels as $rel_type => $rels){
-        foreach ($rels as $subject_type => $subjects){
-
-          // Make the verb in the sentence make sense in English.
-          switch ($rel_type) {
-            case 'integral part of':
-            case 'instance of':
-              $verb = 'are an';
-              break;
-            case 'proper part of':
-            case 'transformation of':
-            case 'genome of':
-            case 'part of':
-            case 'position of':
-            case 'sequence of':
-            case 'variant of':
-              $verb = 'are a';
-              break;
-            case 'derives from':
-            case 'connects on':
-            case 'contains':
-            case 'finishes':
-            case 'guides':
-            case 'has origin':
-            case 'has part':
-            case 'has quality':
-            case 'is consecutive sequence of':
-            case 'maximally overlaps':
-            case 'overlaps':
-            case 'starts':
-              $verb = '';
-              break;
-            default:
-              $verb = 'are';
-          }
-
-          // 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('Feature Name' ,'Unique Name', 'Species', 'Type');
+      if (array_key_exists('entity_id', $item['value']['object'])) {
+        $object_entity_id = $item['value']['object']['entity_id'];
+        if ($object_entity_id != $entity->id) {
+          $link = l($object_name, 'bio_data/' . $object_entity_id);
+          $phrase = preg_replace("/$object_name/", $link, $phrase);
+        }
+      }
+      if (array_key_exists('entity_id', $item['value']['subject'])) {
+        $subject_entity_id = $item['value']['subject']['entity_id'];
+        if ($subject_entity_id != $entity->id) {
+          $link = l($subject_name, 'bio_data/' . $subject_entity_id);
+          $phrase = preg_replace("/$subject_name/", $link, $phrase);
+        }
+      }
 
-          // 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();
+      $phrase = preg_replace("/$subject_type/", "<b>$subject_type</b>", $phrase);
+      $phrase = preg_replace("/$object_type/", "<b>$object_type</b>", $phrase);
+      $rows[] = array($phrase);
+    }
 
-          foreach ($subjects as $subject){
-            // link the feature to it's node
-            $feature_name = $subject->record->subject_id->name;
-            if (property_exists($subject->record, 'nid')) {
-              $feature_name = l($feature_name, "node/" . $subject->record->nid, array('attributes' => array('target' => "_blank")));
-            }
-            // link the organism to it's node
-            $organism = $subject->record->subject_id->organism_id;
-            $organism_name = $organism->genus ." " . $organism->species;
-            if (property_exists($organism, 'nid')) {
-              $organism_name = l("<i>" . $organism->genus . " " . $organism->species . "</i>", "node/" . $organism->nid, array('html' => TRUE));
-            }
-            $rows[] = array(
-              array('data' => $feature_name, 'width' => '30%'),
-              array('data' =>$subject->record->subject_id->uniquename, 'width' => '30%'),
-              array('data' =>$organism_name, 'width' => '30%'),
-              array('data' =>$subject->record->subject_id->type_id->name, 'width' => '10%'),
-            );
-           }
-           // 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-relationship-subject',
-               'class' => 'tripal-data-table'
-             ),
-             'sticky' => FALSE,
-             'caption' => "The following <b>" . $subjects[0]->record->subject_id->type_id->name . " </b> feature(s) $verb $rel_type this " . $record->type_id->name . ":",
-             'colgroups' => array(),
-             'empty' => '',
-           );
 
-           // once we have our table array structure defined, we call Drupal's theme_table()
-           // function to generate the table.
-           $content .= theme_table($table);
-         }
-      }
-    }
+    // 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' => $content,
+      '#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__relationship_load($field, $entity, $base_table, $record) {
-  $field_name = $field['field_name'];
-
-
-  $entity->{$field_name}['und'][0]['all_relationships'] = tripal_get_feature_relationships($record);
-}
 
+  /**
+   * @see TripalField::load()
+   */
+  function load($field, $entity, $details) {
+    $settings = $field['settings'];
+
+    $record = $details['record'];
+
+    $field_name = $field['field_name'];
+    $field_type = $field['type'];
+    $field_table = $field['settings']['chado_table'];
+    $field_column = $field['settings']['chado_column'];
+    $base_table = $field['settings']['base_table'];
+
+    // Expand the object to include the relationships.
+    $options = array(
+      'return_array' => 1,
+      'order_by' => array('rank' => 'ASC'),
+      // we don't want to fully recurse we only need information about the
+      // relationship type and the object and subject  (including feature type
+      // and organism)
+      'include_fk' => array(
+        'type_id' => 1,
+        'object_id' => array(
+          'type_id' => 1,
+          'organism_id' => 1
+        ),
+        'subject_id'  => array(
+          'type_id' => 1,
+          'organism_id' => 1
+        ),
+      ),
+    );
+    $rel_table = $base_table . '_relationship';
+    $record = chado_expand_var($record, 'table', $rel_table, $options);
+    $srelationships = $record->$rel_table->subject_id;
+    $orelationships = $record->$rel_table->object_id;
+
+    $i = 0;
+    if ($orelationships) {
+      foreach ($orelationships as $relationship) {
+        $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession;
+        $rel_type = $relationship->type_id->name;
+        $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
+        $verb = $this->get_rel_verb($rel_type_clean);
+        $subject_name = $relationship->subject_id->name;
+        $subject_type = $relationship->subject_id->type_id->name;
+        $object_name = $relationship->object_id->name;
+        $object_type = $relationship->object_id->type_id->name;
+        $entity->{$field_name}['und'][$i]['value'] = array(
+          '@type' => $rel_acc,
+          'subject' => array(
+            '@type' => $relationship->subject_id->type_id->dbxref_id->db_id->name .
+                ':' . $relationship->subject_id->type_id->dbxref_id->accession,
+            'type' =>  $subject_type,
+            'name' => $subject_name,
+          ),
+          'type' => $relationship->type_id->name,
+          'object' => array(
+            'entity_id' => $entity->id,
+            'entity_type' => 'TripalEntity',
+            'type' =>  $object_type,
+            'name' => $object_name,
+          )
+        );
+        if (property_exists($relationship->subject_id, 'uniquename')) {
+          $subject_name = $relationship->subject_id->uniquename;
+          $entity->{$field_name}['und'][$i]['value']['subject']['name'] = $subject_name;
+        }
+        if (property_exists($relationship->object_id, 'uniquename')) {
+          $object_name = $relationship->object_id->uniquename;
+          $entity->{$field_name}['und'][$i]['value']['object']['name'] = $object_name;
+        }
+        if (property_exists($relationship->subject_id, 'entity_id')) {
+          $entity_id = $relationship->subject_id->entity_id;
+          $entity->{$field_name}['und'][$i]['value']['subject']['entity_id'] = $entity_id;
+          $entity->{$field_name}['und'][$i]['value']['subject']['entity_type'] = 'TripalEntity';
+        }
+        $entity->{$field_name}['und'][$i]['value']['phrase'] = 'The ' . $subject_type . ', ' .
+          $subject_name . ', ' . $verb . ' '  . $rel_type_clean . ' this '  .
+          $object_type . '.';
+
+        $i++;
+      }
+    }
 
-/**
- * Implements hook_ws_formatter().
- */
-// function chado_linker__relationship_ws_formatter(&$element, $entity_type, $entity,
-//     $field, $instance, $items) {
-
-//   foreach ($items as $delta => $item) {
-
-//   }
-// }
-
-/**
- *  Implements hook_widget().
- */
-function chado_linker__relationship_widget(&$widget, $form, $form_state, $field, $instance, $langcode, $items, $delta, $element) {
-
-}
-/**
- * Callback function for validating the chado_linker_featureloc_widget.
- */
-function chado_linker__relationship_widget_validate($element, &$form_state) {
+    if ($srelationships) {
+      foreach ($srelationships as $relationship) {
+        $rel_acc = $relationship->type_id->dbxref_id->db_id->name . ':' . $relationship->type_id->dbxref_id->accession;
+        $rel_type = $relationship->type_id->name;
+        $rel_type_clean = lcfirst(preg_replace('/_/', ' ', $rel_type));
+        $verb = $this->get_rel_verb($rel_type_clean);
+        $subject_name = $relationship->subject_id->name;
+        $subject_type = $relationship->subject_id->type_id->name;
+        $object_name = $relationship->object_id->name;
+        $object_type = $relationship->object_id->type_id->name;
+        $entity->{$field_name}['und'][$i]['value'] = array(
+          '@type' => $rel_acc,
+          'subject' => array(
+            'type' =>  $subject_type,
+            'name' => $subject_name,
+            'entity_id' => $entity->id,
+            'entity_type' => 'TripalEntity',
+          ),
+          'type' => $relationship->type_id->name,
+          'object' => array(
+            '@type' => $relationship->object_id->type_id->dbxref_id->db_id->name .
+               ':' . $relationship->subject_id->type_id->dbxref_id->accession,
+            'type' =>  $object_type,
+            'name' => $oject_name,
+          )
+        );
+        if (property_exists($relationship->subject_id, 'uniquename')) {
+          $subject_name = $relationship->subject_id->uniquename;
+          $entity->{$field_name}['und'][$i]['value']['subject']['name'] = $subject_name;
+        }
+        if (property_exists($relationship->object_id, 'uniquename')) {
+          $object_name = $relationship->object_id->uniquename;
+          $entity->{$field_name}['und'][$i]['value']['object']['name'] = $object_name;
+        }
+        if (property_exists($relationship->object_id, 'entity_id')) {
+          $entity_id = $relationship->object_id->entity_id;
+          $entity->{$field_name}['und'][$i]['value']['object']['entity_id'] = $entity_id;
+          $entity->{$field_name}['und'][$i]['value']['object']['entity_type'] = 'TripalEntity';
+        }
+        $entity->{$field_name}['und'][$i]['value']['phrase'] = 'This  ' .
+          $subject_type . ' ' . $verb . ' '  . $rel_type_clean . ' the '  .
+          $object_type . ', ' . $object_name . '.';
+        $i++;
+      }
+    }
+  }
+  private function get_rel_verb($rel_type) {
+    $verb = '';
+    switch ($rel_type) {
+      case 'integral part of':
+      case 'instance of':
+        $verb = 'is an';
+        break;
+      case 'proper part of':
+      case 'transformation of':
+      case 'genome of':
+      case 'part of':
+        $verb = 'is a';
+      case 'position of':
+      case 'sequence of':
+      case 'variant of':
+        $verb = 'is a';
+        break;
+      case 'derives from':
+      case 'connects on':
+      case 'contains':
+      case 'finishes':
+      case 'guides':
+      case 'has origin':
+      case 'has part':
+      case 'has quality':
+      case 'is consecutive sequence of':
+      case 'maximally overlaps':
+      case 'overlaps':
+      case 'starts':
+        $verb = '';
+        break;
+      default:
+        $verb = 'is';
+    }
 
+    return $verb;
+  }
 }

+ 290 - 321
tripal_chado/includes/fields/chado_linker__synonym.inc

@@ -1,251 +1,303 @@
 <?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_attach_info().
- *
- * This is a hook provided by the tripal_Chado module. It allows the field
- * to specify which bundles it will attach to and to specify thee settings.
- *
- * @param $entity_type
- * @param $entity
- * @param $term
- *
- * @return
- *   A field array
- */
-function chado_linker__synonym_attach_info($entity_type, $bundle, $target) {
-  $field_info = array();
-
-  $table_name = $target['data_table'];
-  $type_table = $target['type_table'];
-  $type_field = $target['field'];
-  $cv_id      = $target['cv_id'];
-  $cvterm_id  = $target['cvterm_id'];
-
-  // If the linker table does not exists then we don't want to add attach.
-  $syn_table = $table_name . '_synonym';
-  if (!chado_table_exists($syn_table)) {
-    return $field_info;
+
+class chado_linker__synonym extends TripalField {
+
+  /**
+   * @see TripalField::field_info()
+   */
+  function field_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
+      ),
+    );
   }
+  /**
+   * @see TripalField::attach_info()
+   */
+  function attach_info($entity_type, $bundle, $target) {
+    $field_info = array();
+
+    $table_name = $target['data_table'];
+    $type_table = $target['type_table'];
+    $type_field = $target['field'];
+    $cv_id      = $target['cv_id'];
+    $cvterm_id  = $target['cvterm_id'];
+
+    // If the linker table does not exists then we don't want to add attach.
+    $syn_table = $table_name . '_synonym';
+    if (!chado_table_exists($syn_table)) {
+      return $field_info;
+    }
 
-  $schema = chado_get_schema($syn_table);
-  $pkey = $schema['primary key'][0];
-
-  // Initialize the field array.
-  $field_info = array(
-    'field_name' => $table_name . '__synonym',
-    'field_type' => 'chado_linker__synonym',
-    'widget_type' => 'chado_linker__synonym_widget',
-    'widget_settings' => array('display_label' => 1),
-    'description' => '',
-    'label' => 'Synonyms',
-    'is_required' => 0,
-    'cardinality' => FIELD_CARDINALITY_UNLIMITED,
-    'storage' => 'field_chado_storage',
-    'field_settings' => array(
-      'chado_table' => $syn_table,
-      'chado_column' => $pkey,
-      'base_table' => $table_name,
-      'semantic_web' => array(
-        'name' => '',
-        'accession' => '',
-        'ns' => '',
-        'nsurl' => '',
+    $schema = chado_get_schema($syn_table);
+    $pkey = $schema['primary key'][0];
+
+    // Initialize the field array.
+    $field_info = array(
+      'field_name' => $table_name . '__synonym',
+      'field_type' => 'chado_linker__synonym',
+      'widget_type' => 'chado_linker__synonym_widget',
+      'widget_settings' => array('display_label' => 1),
+      'description' => '',
+      'label' => 'Synonyms',
+      'is_required' => 0,
+      'cardinality' => FIELD_CARDINALITY_UNLIMITED,
+      'storage' => 'field_chado_storage',
+      'field_settings' => array(
+        'chado_table' => $syn_table,
+        'chado_column' => $pkey,
+        'base_table' => $table_name,
+        'semantic_web' => array(
+          'name' => 'alternateName',
+          'accession' => 'alternateName',
+          'ns' => 'schema',
+          'nsurl' => 'https://schema.org/',
+        ),
       ),
-    ),
-  );
-  return $field_info;
-}
-/**
- * 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
- * @param unknown $entity
- * @param unknown $field
- * @param unknown $instance
- * @param unknown $langcode
- * @param unknown $items
- * @param unknown $display
- */
-function chado_linker__synonym_formatter(&$element, $entity_type, $entity, $field,
-    $instance, $langcode, $items, $display) {
-
-  $chado_table = $field['settings']['chado_table'];
-  foreach ($items as $delta => $item) {
-    if ($item[$chado_table . '__synonym_id']) {
-      $synonym = chado_generate_var('synonym', array('synonym_id' => $item[$chado_table . '__synonym_id']));
-      $name = $synonym->name;
-      if ($synonym->type_id->name != 'exact') {
-        $name .= ' (<i>' . $synonym->type_id->name . '</i>)';
+    );
+    return $field_info;
+  }
+  /**
+   * @see TripalField::widget_info()
+   */
+  function widget_info() {
+    return array(
+      'label' => t('Synonyms'),
+      'field types' => array('chado_linker__synonym'),
+    );
+  }
+  /**
+   * @see TripalField::formatter_info()
+   */
+  function formatter_info() {
+    return array(
+      'label' => t('Synonyms'),
+      'field types' => array('chado_linker__synonym'),
+      'settings' => array(
+      ),
+    );
+  }
+  /**
+   * @see TripalField::formatter_view()
+   */
+  function formatter_view(&$element, $entity_type, $entity, $field,
+      $instance, $langcode, $items, $display) {
+
+    $chado_table = $field['settings']['chado_table'];
+    foreach ($items as $delta => $item) {
+      if ($item[$chado_table . '__synonym_id']) {
+        $synonym = chado_generate_var('synonym', array('synonym_id' => $item[$chado_table . '__synonym_id']));
+        $name = $synonym->name;
+        if ($synonym->type_id->name != 'exact') {
+          $name .= ' (<i>' . $synonym->type_id->name . '</i>)';
+        }
+        $element[$delta] = array(
+          '#type' => 'markup',
+          '#markup' => $name,
+        );
       }
-      $element[$delta] = array(
-        '#type' => 'markup',
-        '#markup' => $name,
-      );
     }
   }
-}
-/**
- *
- */
-function chado_linker__synonym_widget(&$widget, $form, $form_state, $field,
-    $instance, $langcode, $items, $delta, $element) {
-
-  $entity = $form['#entity'];
-  $field_name = $field['field_name'];
-
-  // Get the FK column that links to the base table.
-  $table_name = $field['settings']['chado_table'];
-  $base_table = $field['settings']['base_table'];
-  $schema = chado_get_schema($table_name);
-  $pkey = $schema['primary key'][0];
-  $fkeys = array_values($schema['foreign keys'][$base_table]['columns']);
-  $fkey = $fkeys[0];
-
-  // Get the field defaults.
-  $record_id = '';
-  $fkey_value = $element['#entity']->chado_record_id;
-  $synonym_id = '';
-  $pub_id = '';
-  $is_current = TRUE;
-  $is_internal = FALSE;
-  $syn_name = '';
-  $syn_type = '';
-
-  // If the field already has a value then it will come through the $items
-  // array.  This happens when editing an existing record.
-  if (array_key_exists($delta, $items)) {
-    $record_id = $items[$delta]['value'];
-    $fkey_value = $items[$delta][$table_name . '__' . $fkey];
-    $synonym_id = $items[$delta][$table_name . '__synonym_id'];
-    $pub_id = $items[$delta][$table_name . '__pub_id'];
-    $is_current = $items[$delta][$table_name . '__is_current'];
-    $is_internal = $items[$delta][$table_name . '__is_internal'];
-    $syn_name = $items[$delta][$table_name . '--synonym__name'];
-    $syn_type = $items[$delta][$table_name . '--synonym__type_id'];
-  }
+  /**
+   * @see TripalField::widget_form()
+   */
+  function widget_form(&$widget, $form, $form_state, $field,
+      $instance, $langcode, $items, $delta, $element) {
+
+    $entity = $form['#entity'];
+    $field_name = $field['field_name'];
+
+    // Get the FK column that links to the base table.
+    $table_name = $field['settings']['chado_table'];
+    $base_table = $field['settings']['base_table'];
+    $schema = chado_get_schema($table_name);
+    $pkey = $schema['primary key'][0];
+    $fkeys = array_values($schema['foreign keys'][$base_table]['columns']);
+    $fkey = $fkeys[0];
+
+    // Get the field defaults.
+    $record_id = '';
+    $fkey_value = $element['#entity']->chado_record_id;
+    $synonym_id = '';
+    $pub_id = '';
+    $is_current = TRUE;
+    $is_internal = FALSE;
+    $syn_name = '';
+    $syn_type = '';
+
+    // If the field already has a value then it will come through the $items
+    // array.  This happens when editing an existing record.
+    if (array_key_exists($delta, $items)) {
+      $record_id = $items[$delta]['value'];
+      $fkey_value = $items[$delta][$table_name . '__' . $fkey];
+      $synonym_id = $items[$delta][$table_name . '__synonym_id'];
+      $pub_id = $items[$delta][$table_name . '__pub_id'];
+      $is_current = $items[$delta][$table_name . '__is_current'];
+      $is_internal = $items[$delta][$table_name . '__is_internal'];
+      $syn_name = $items[$delta][$table_name . '--synonym__name'];
+      $syn_type = $items[$delta][$table_name . '--synonym__type_id'];
+    }
 
-  // Check $form_state['values'] to see if an AJAX call set the values.
-  if (array_key_exists('values', $form_state) and array_key_exists($delta, $form_state['values'])) {
-    $record_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name);
-    $fkey_value = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__' . $fkey);
-    $synonym_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__synonym_id');
-    $pub_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__pub_id');
-    $is_current = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__is_current');
-    $is_internal = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__is_internal');
-    $syn_name = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '--synonym__name');
-    $syn_type = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '--synonym__type_id');
-  }
+    // Check $form_state['values'] to see if an AJAX call set the values.
+    if (array_key_exists('values', $form_state) and array_key_exists($delta, $form_state['values'])) {
+      $record_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name);
+      $fkey_value = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__' . $fkey);
+      $synonym_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__synonym_id');
+      $pub_id = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__pub_id');
+      $is_current = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__is_current');
+      $is_internal = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '__is_internal');
+      $syn_name = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '--synonym__name');
+      $syn_type = tripal_chado_get_field_form_values($table_name, $form_state, $delta, $table_name . '--synonym__type_id');
+    }
 
-  // Get the synonym type terms.  There shouldn't be too many.
-  $cv = tripal_get_default_cv('synonym', 'type_id');
-  $options = tripal_get_cvterm_select_options($cv->cv_id);
-
-  // Get the schema for the synonym table so we can make sure we limit the
-  // size of the name field to the proper size.
-  $schema = chado_get_schema('synonym');
-
-  $widget['#table_name'] = $table_name;
-  $widget['#fkey_field'] = $fkey;
-  $widget['#element_validate'] = array('chado_linker__synonym_widget_validate');
-  $widget['#theme'] = 'chado_linker__synonym_widget';
-  $widget['#prefix'] =  "<span id='$table_name-$delta'>";
-  $widget['#suffix'] =  "</span>";
-
-  $widget['value'] = array(
-    '#type' => 'value',
-    '#default_value' => $record_id,
-  );
-  $widget[$table_name . '__' . $fkey] = array(
-    '#type' => 'value',
-    '#default_value' => $fkey_value,
-  );
-
-  $widget[$table_name . '--synonym__type_id'] = array(
-    '#type' => 'select',
-    '#title' => t('Type'),
-    '#options' => $options,
-    '#default_value' => $syn_type,
-  );
-  $widget[$table_name . '--synonym__name'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Synonym Name'),
-    '#default_value' => $syn_name,
-    '#size' => 25,
-  );
-
-  $widget[$table_name . '__is_current'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Is Current'),
-    '#default_value' => $is_current,
-    '#required' => $element['#required'],
-  );
-
-  $widget[$table_name . '__is_internal'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Is Internal'),
-    '#default_value' => $is_internal,
-    '#required' => $element['#required'],
-  );
+    // Get the synonym type terms.  There shouldn't be too many.
+    $cv = tripal_get_default_cv('synonym', 'type_id');
+    $options = tripal_get_cvterm_select_options($cv->cv_id);
+
+    // Get the schema for the synonym table so we can make sure we limit the
+    // size of the name field to the proper size.
+    $schema = chado_get_schema('synonym');
+
+    $widget['#table_name'] = $table_name;
+    $widget['#fkey_field'] = $fkey;
+    $widget['#element_validate'] = array('chado_linker__synonym_widget_validate');
+    $widget['#theme'] = 'chado_linker__synonym_widget';
+    $widget['#prefix'] =  "<span id='$table_name-$delta'>";
+    $widget['#suffix'] =  "</span>";
+
+    $widget['value'] = array(
+      '#type' => 'value',
+      '#default_value' => $record_id,
+    );
+    $widget[$table_name . '__' . $fkey] = array(
+      '#type' => 'value',
+      '#default_value' => $fkey_value,
+    );
+
+    $widget[$table_name . '--synonym__type_id'] = array(
+      '#type' => 'select',
+      '#title' => t('Type'),
+      '#options' => $options,
+      '#default_value' => $syn_type,
+    );
+    $widget[$table_name . '--synonym__name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Synonym Name'),
+      '#default_value' => $syn_name,
+      '#size' => 25,
+    );
+
+    $widget[$table_name . '__is_current'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Is Current'),
+      '#default_value' => $is_current,
+      '#required' => $element['#required'],
+    );
+
+    $widget[$table_name . '__is_internal'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Is Internal'),
+      '#default_value' => $is_internal,
+      '#required' => $element['#required'],
+    );
 
+  }
+
+  /**
+   * @see TripalField::load()
+   */
+  function load($field, $entity, $details) {
+
+    $record = $details['record'];
+    $base_table = $field['settings']['base_table'];
+
+    $field_name = $field['field_name'];
+    $field_type = $field['type'];
+    $field_table = $field['settings']['chado_table'];
+    $field_column = $field['settings']['chado_column'];
+
+    // Get the FK that links to the base record.
+    $schema = chado_get_schema($field_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];
+
+    // Set some defaults for the empty record.
+    $entity->{$field_name}['und'][0] = array(
+      'value' => '',
+      $field_table . '__' . $fkey_lcolumn => '',
+      $field_table . '__' . 'synonym_id' => '',
+      $field_table . '__' . 'pub_id' => '',
+      $field_table . '__' . 'is_current' => TRUE,
+      $field_table . '__' . 'is_internal' => '',
+      $field_table . '--' . 'synonym__name' => '',
+      $field_table . '--' . 'synonym__type_id' => '',
+      // Ignore the synonym_sgml column for now.
+    );
+
+    $linker_table = $base_table . '_synonym';
+    $options = array('return_array' => 1);
+    $record = chado_expand_var($record, 'table', $linker_table, $options);
+    if (count($record->$linker_table) > 0) {
+      $i = 0;
+      foreach ($record->$linker_table as $index => $linker) {
+        $synonym = $linker->synonym_id;
+        $entity->{$field_name}['und'][$i] = array(
+          'value' => $linker->$pkey,
+          $field_table . '__' . $fkey_lcolumn => $linker->$fkey_lcolumn->$fkey_lcolumn,
+          $field_table . '__' . 'synonym_id' => $synonym->synonym_id,
+          $field_table . '__' . 'pub_id' => $linker->pub_id->pub_id,
+          $field_table . '__' . 'is_current' => $linker->is_current,
+          $field_table . '__' . 'is_internal' => $linker->is_internal,
+          $field_table . '--' . 'synonym__name' => $synonym->name,
+          $field_table . '--' . 'synonym__type_id' => $synonym->type_id->cvterm_id,
+        );
+        $i++;
+      }
+    }
+  }
 }
+
 /**
- * An Ajax callback for the synonym widget.
+ * Theme function for the synonym widget.
+ *
+ * @param $variables
  */
-function chado_linker__synonym_widget_form_ajax_callback($form, $form_state) {
+function theme_chado_linker__synonym_widget($variables) {
+  $element = $variables['element'];
 
-  $field_name = $form_state['triggering_element']['#parents'][0];
-  $delta = $form_state['triggering_element']['#parents'][2];
+  // These two fields were added to the widget to help identify the fields
+  // for layout.
+  $table_name = $element['#table_name'];
+  $fkey = $element['#fkey_field'];
 
-  return $form[$field_name]['und'][$delta];
-}
+  $layout = "
+      <div class=\"synonym-widget\">
+        <div class=\"synonym-widget-item\">" .
+        drupal_render($element[$table_name . '--synonym__name']) . "
+        </div>
+        <div>" .
+        drupal_render($element[$table_name . '--synonym__type_id']) . "
+        </div>
+        <div class=\"synonym-widget-item\">" .
+        drupal_render($element[$table_name . '__is_internal']) . "
+        </div>
+        <div>" .
+        drupal_render($element[$table_name . '__is_current']) . "
+        </div>
+      </div>
+    ";
 
+  return $layout;
+}
 /**
  * Callback function for validating the chado_linker__synonym_widget.
  */
@@ -317,97 +369,14 @@ function chado_linker__synonym_widget_validate($element, &$form_state) {
   }
 
 }
+
 /**
- * Theme function for the synonym widget.
- *
- * @param $variables
+ * An Ajax callback for the synonym widget.
  */
-function theme_chado_linker__synonym_widget($variables) {
-  $element = $variables['element'];
-
-  // These two fields were added to the widget to help identify the fields
-  // for layout.
-  $table_name = $element['#table_name'];
-  $fkey = $element['#fkey_field'];
-
-  $layout = "
-    <div class=\"synonym-widget\">
-      <div class=\"synonym-widget-item\">" .
-        drupal_render($element[$table_name . '--synonym__name']) . "
-      </div>
-      <div>" .
-        drupal_render($element[$table_name . '--synonym__type_id']) . "
-      </div>
-      <div class=\"synonym-widget-item\">" .
-        drupal_render($element[$table_name . '__is_internal']) . "
-      </div>
-      <div>" .
-        drupal_render($element[$table_name . '__is_current']) . "
-      </div>
-    </div>
-  ";
+function chado_linker__synonym_widget_form_ajax_callback($form, $form_state) {
 
-  return $layout;
-}
+  $field_name = $form_state['triggering_element']['#parents'][0];
+  $delta = $form_state['triggering_element']['#parents'][2];
 
-/**
- * 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.
- *
- * @param $field
- * @param $entity
- * @param $base_table
- * @param $record
- */
-function chado_linker__synonym_load($field, $entity, $base_table, $record) {
-
-  $field_name = $field['field_name'];
-  $field_type = $field['type'];
-  $field_table = $field['settings']['chado_table'];
-  $field_column = $field['settings']['chado_column'];
-
-  // Get the FK that links to the base record.
-  $schema = chado_get_schema($field_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];
-
-  // Set some defaults for the empty record.
-  $entity->{$field_name}['und'][0] = array(
-    'value' => '',
-    $field_table . '__' . $fkey_lcolumn => '',
-    $field_table . '__' . 'synonym_id' => '',
-    $field_table . '__' . 'pub_id' => '',
-    $field_table . '__' . 'is_current' => TRUE,
-    $field_table . '__' . 'is_internal' => '',
-    $field_table . '--' . 'synonym__name' => '',
-    $field_table . '--' . 'synonym__type_id' => '',
-    // Ignore the synonym_sgml column for now.
-  );
-
-  $linker_table = $base_table . '_synonym';
-  $options = array('return_array' => 1);
-  $record = chado_expand_var($record, 'table', $linker_table, $options);
-  if (count($record->$linker_table) > 0) {
-    $i = 0;
-    foreach ($record->$linker_table as $index => $linker) {
-      $synonym = $linker->synonym_id;
-      $entity->{$field_name}['und'][$i] = array(
-        'value' => $linker->$pkey,
-        $field_table . '__' . $fkey_lcolumn => $linker->$fkey_lcolumn->$fkey_lcolumn,
-        $field_table . '__' . 'synonym_id' => $synonym->synonym_id,
-        $field_table . '__' . 'pub_id' => $linker->pub_id->pub_id,
-        $field_table . '__' . 'is_current' => $linker->is_current,
-        $field_table . '__' . 'is_internal' => $linker->is_internal,
-        $field_table . '--' . 'synonym__name' => $synonym->name,
-        $field_table . '--' . 'synonym__type_id' => $synonym->type_id->cvterm_id,
-      );
-      $i++;
-    }
-  }
+  return $form[$field_name]['und'][$delta];
 }
-

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

@@ -58,6 +58,9 @@ function tripal_chado_entity_load($entities, $type) {
 
         // Add in the Chado table information for this entity type.
         $bundle = tripal_load_bundle_entity(array('name' => $entity->bundle));
+        if (!$bundle) {
+          continue;
+        }
         $chado_table = tripal_get_bundle_variable('chado_table', $bundle->id);
         $chado_column = tripal_get_bundle_variable('chado_column', $bundle->id);
         if ($chado_table) {

+ 33 - 31
tripal_chado/includes/tripal_chado.fields.inc

@@ -288,6 +288,9 @@ function tripal_chado_field_widget_form_alter(&$element, &$form_state, $context)
       $tablename = $matches[1];
       $colname = $matches[2];
       $schema = chado_get_schema($tablename);
+      if (!$schema) {
+        return;
+      }
 
       // The timelastmodified field exists in many Chado tables.  We want
       // the form element to update to the most recent time rather than the time
@@ -313,7 +316,7 @@ function tripal_chado_field_widget_form_alter(&$element, &$form_state, $context)
  * Returns a $field_info array for a field based on a database column.
  *
  */
-function tripal_chado_add_bundle_fields_base__fields_defaults($table_name, $schema, $column_name) {
+function tripal_chado_get_bundle_fields_base__fields_defaults($table_name, $schema, $column_name) {
   $details = $schema['fields'][$column_name];
 
   // Create an array with information about this field.
@@ -406,11 +409,29 @@ function tripal_chado_add_bundle_fields_base__fields_defaults($table_name, $sche
   }
 
   // Set some default semantic web information
-  if ($column_name == 'name') {
+  if ($column_name == 'uniquename') {
     $field['field_settings']['semantic_web']['name'] = 'name';
     $field['field_settings']['semantic_web']['accession'] = 'name';
     $field['field_settings']['semantic_web']['ns'] = 'foaf';
     $field['field_settings']['semantic_web']['nsurl'] = 'http://xmlns.com/foaf/0.1/';
+    $field['widget_type'] = 'text_textfield';
+    $field['field_settings']['text_processing'] = 0;
+  }
+  if ($column_name == 'name') {
+    // If this table also has a unqiuename field then use the 'name' field
+    // as an alternate name.
+    if (array_key_exists('uniquename', $schema['fields'])) {
+      $field['field_settings']['semantic_web']['name'] = 'alternateName';
+      $field['field_settings']['semantic_web']['accession'] = 'alternateName';
+      $field['field_settings']['semantic_web']['ns'] = 'schema';
+      $field['field_settings']['semantic_web']['nsurl'] = 'https://schema.org/';
+    }
+    else {
+      $field['field_settings']['semantic_web']['name'] = 'name';
+      $field['field_settings']['semantic_web']['accession'] = 'name';
+      $field['field_settings']['semantic_web']['ns'] = 'foaf';
+      $field['field_settings']['semantic_web']['nsurl'] = 'http://xmlns.com/foaf/0.1/';
+    }
   }
   if ($column_name == 'description' or $column_name == 'definition' or
       $column_name == 'comment') {
@@ -437,14 +458,14 @@ function tripal_chado_add_bundle_fields_base__fields_defaults($table_name, $sche
   //
   // FEATURE TABLE
   //
-  elseif ($field['field_settings']['chado_table'] == 'feature' and $field['field_settings']['chado_column'] == 'uniquename') {
+  elseif ($field['field_settings']['chado_table'] == 'pub' and $field['field_settings']['chado_column'] == 'uniquename') {
     $field['field_type'] = 'text';
     $field['widget_type'] = 'text_textfield';
     $field['field_settings']['text_processing'] = 0;
-    $field['field_settings']['semantic_web']['name'] = 'name';
-    $field['field_settings']['semantic_web']['accession'] = 'name';
-    $field['field_settings']['semantic_web']['ns'] = 'foaf';
-    $field['field_settings']['semantic_web']['nsurl'] = 'http://xmlns.com/foaf/0.1/';
+    $field['field_settings']['semantic_web']['name'] = 'Comment';
+    $field['field_settings']['semantic_web']['accession'] = 'Comment';
+    $field['field_settings']['semantic_web']['ns'] = 'schema';
+    $field['field_settings']['semantic_web']['nsurl'] = 'https://www.schema.org/';
   }
 
   //
@@ -678,6 +699,9 @@ function tripal_chado_get_bundle_fields($entity_type, $bundle, $term) {
   $fields_path = drupal_get_path('module', 'tripal_chado') . '/includes/fields';
   $field_files = file_scan_directory($fields_path, '/^chado_.*\.inc$/');
 
+  // Add fields from the base table.
+  tripal_chado_get_bundle_fields_base__fields($fields, $entity_type, $bundle_name, $bundle_data);
+
   // Iterate through the fields, include the file and run the info function.
   foreach ($field_files as $file) {
     $field_type = $file->name;
@@ -701,10 +725,6 @@ function tripal_chado_get_bundle_fields($entity_type, $bundle, $term) {
     $fields[$field_name] = $field_info;
   }
 
-  // Adds any remaining base fields that may not have been dealt with
-  // by a custom field.
-  tripal_chado_add_bundle_fields_base__fields($fields, $entity_type, $bundle_name, $bundle_data);
-
   return $fields;
 }
 
@@ -712,7 +732,7 @@ function tripal_chado_get_bundle_fields($entity_type, $bundle, $term) {
 /**
  * Adds the fields for the base table to the entity.
  */
-function tripal_chado_add_bundle_fields_base__fields(&$fields, $entity_type_name, $bundle_name, $bundle_data) {
+function tripal_chado_get_bundle_fields_base__fields(&$fields, $entity_type_name, $bundle_name, $bundle_data) {
 
   $table_name = $bundle_data['data_table'];
   $type_table = $bundle_data['type_table'];
@@ -736,7 +756,7 @@ function tripal_chado_add_bundle_fields_base__fields(&$fields, $entity_type_name
     }
 
     // Get the field defaults for this column.
-    $field_info = tripal_chado_add_bundle_fields_base__fields_defaults($table_name, $schema, $column_name);
+    $field_info = tripal_chado_get_bundle_fields_base__fields_defaults($table_name, $schema, $column_name);
 
 
     // TODO: add in a call to drupal_alter to allow other modules to change
@@ -770,28 +790,10 @@ function tripal_chado_add_bundle_fields_base__fields(&$fields, $entity_type_name
 
     // Add the field to the bundle.
     $fields[$field_name] = $field_info;
-    //tripal_add_bundle_field($field_name, $field_info, $entity_type_name, $bundle_name);
   }
 }
 
 
-/**
- * Implements hook_field_attach_validate().
- *
- * This function is used to validate entity-wide validation any of the fields
- * attached to an entity.
- */
-function tripal_chado_field_attach_validate($entity_type, $entity, &$errors) {
-  $bundle_name = $entity->bundle;
-  $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
-  $term = tripal_load_term_entity(array('term_id' => $bundle->term_id));
-
-  // Provide some higher-level validation for the organism type.
-  if ($term->name == 'organism') {
-
-  }
-}
-
 
 
 

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

@@ -350,6 +350,7 @@ function tripal_chado_prepare_chado() {
       'cv_name' => 'local',
     ));
 
+    // TODO: change this to foaf:Project
     tripal_insert_cvterm(array(
       'id' => 'local:project',
       'name' => 'project',
@@ -359,6 +360,33 @@ function tripal_chado_prepare_chado() {
       'cv_name' => 'local',
     ));
 
+    tripal_insert_cvterm(array(
+      'id' => 'local:contact',
+      'name' => 'contact',
+      'definition' => 'An entity (e.g. individual or organization) through ' .
+         'whom a person can gain access to information, favors, ' .
+         'influential people, and the like.',
+      'cv_name' => 'local',
+    ));
+
+    tripal_insert_cvterm(array(
+      'id' => 'local:md5_checksum',
+      'name' => 'md5_checksum',
+      'definition' => 'The MD5 message-digest algorithm is a widely used ' .
+         'cryptographic hash function producing a 128-bit (16-byte) hash ' .
+         'value, typically expressed in text format as a 32-digit hexadecimal ' .
+         'number. MD5 has been utilized in a wide variety of cryptographic ' .
+         'applications and is also commonly used to verify data integrity (Wikipedia)',
+      'cv_name' => 'local',
+    ));
+
+    tripal_insert_cvterm(array(
+      'id' => 'local:relationship',
+      'name' => 'relationship',
+      'definition' => 'The way in which two things are connected.',
+      'cv_name' => 'local',
+    ));
+
     // For the TripalBundle entities we will want to associate the cvterm_id,
     // and the chado table and field that it maps to.  We will use a few
     // variables to do this:
@@ -1252,6 +1280,9 @@ function tripal_feature_add_cvs() {
       'The Sequence Ontology'
   );
 }
+/**
+ *
+ */
 function tripal_feature_add_tripal_gff_temp_table() {
   $schema = array(
     'table' => 'tripal_gff_temp',

+ 11 - 17
tripal_ws/includes/tripal_ws.rest.inc

@@ -462,6 +462,7 @@ function tripal_ws_get_content($api_url, &$response, $ws_args, $ctype, $entity_i
   // TODO: should we allow for custom ordering of fields for web services
   // or use the default display ordering?
   $fields = field_info_instances('TripalEntity', $bundle->name);
+
   uasort($fields, function($a, $b) {
     $a_weight = (is_array($a) && isset($a['display']['default']['weight'])) ? $a['display']['default']['weight'] : 0;
     $b_weight = (is_array($b) && isset($b['display']['default']['weight'])) ? $b['display']['default']['weight'] : 0;
@@ -475,27 +476,19 @@ function tripal_ws_get_content($api_url, &$response, $ws_args, $ctype, $entity_i
   //$response['fields'] = $fields;
   foreach ($fields as $field_name => $field) {
     $field_info = field_info_field($field_name);
-    $items = field_get_items('TripalEntity', $entity, $field_name);
+    $settings = $field_info['settings'];
 
     // By default, the label for the key in the output should be the
     // term from the vocabulary that the field is assigned. But in the
     // case that the field is not assigned a term, we must use the field name.
     $key = $field['field_name'];
-    if (array_key_exists('semantic_web', $field['settings'])) {
-      if (array_key_exists('name', $field['settings']['semantic_web']) and
-          $field['settings']['semantic_web']['name']) {
-        $key = $field['settings']['semantic_web']['name'];
-      }
-    }
-
-    // Get the semantic web settings for this field.
-    $field_type = '';
-    if (array_key_exists('semantic_web', $field['settings'])) {
-      $field_name = $field['settings']['semantic_web']['name'];
-      if ($field_name) {
-        $accession = $field['settings']['semantic_web']['accession'];
-        $ns = $field['settings']['semantic_web']['ns'];
-        $nsurl = $field['settings']['semantic_web']['nsurl'];
+    if (array_key_exists('semantic_web', $settings)) {
+      if (array_key_exists('name', $settings['semantic_web']) and
+          $settings['semantic_web']['name']) {
+        $key = $settings['semantic_web']['name'];
+        $nsurl = $settings['semantic_web']['nsurl'];
+        $ns = $settings['semantic_web']['ns'];
+        $accession = $settings['semantic_web']['accession'];
         $response['@context'][$ns] = $nsurl;
         $response['@context'][$key] = $ns . ':' . $accession;
       }
@@ -507,11 +500,12 @@ function tripal_ws_get_content($api_url, &$response, $ws_args, $ctype, $entity_i
     }
 
     $value = array();
+    $items = field_get_items('TripalEntity', $entity, $field_name);
     for ($i = 0; $i < count($items); $i++) {
 
       // If the value for this key is an array with an 'entity_id' key then
       // we want to do a substitution.
-      if (array_key_exists('entity_id', $items[0])) {
+      if (array_key_exists('entity_id', $items[$i]) and $items[$i]['entity_id']) {
         $lentity = entity_load($items[$i]['entity_type'], array($items[$i]['entity_id']));
         $lentity = reset($lentity);
         $lterm = tripal_load_term_entity(array('term_id' => $lentity->term_id));