Browse Source

Clean-ed up the cv/lookup and added a simple tree browser that could use some improvement

Stephen Ficklin 7 years ago
parent
commit
54e848aee5

+ 103 - 0
tripal/api/tripal.terms.api.inc

@@ -153,6 +153,48 @@ function hook_vocab_import_form_submit($form, &$form_state) {
 function hook_vocab_get_term($vocabulary, $accession) {
   // See the tripal_chado_vocab_get_term() function for an example.
 
+}
+/**
+ * Hook used by the default term storage backend to provide children for a term.
+ *
+ * This hook is called by the tripal_entity module to retrieve a list of
+ * children for a term from the storage backend.  It must return an array
+ * of terms where each term contains the same structure as that of the
+ * hook_vocab_get_term().
+ *
+ * @param $vocabulary
+ *   The vocabulary of the vocabulary in which the term is found.
+ * @param $accession
+ *   The unique identifier (accession) for this term.
+ *
+ * @return
+ *   An array of terms where each term contains the same structure as that of
+ *   the hook_vocab_get_term(), or an empty array if no children are present.
+ *
+ * @ingroup tripal_terms_api
+ */
+function hook_vocab_get_term_children($vocabulary, $accession) {
+
+}
+/**
+ * Hook used by the default term storage backend to provide root terms.
+ *
+ * This hook is called by the tripal_entity module to retrieve a list of
+ * root terms for a given vocabulary from the storage backend.  It must return
+ * an array of terms where each term contains the same structure as that of the
+ * hook_vocab_get_term().
+ *
+ * @param $vocabulary
+ *   The vocabulary of the vocabulary in which the term is found.
+ *
+ * @return
+ *   An array of root terms where each term contains the same structure as that
+ *   of the hook_vocab_get_term(), or an empty array if no children are present.
+ *
+ * @ingroup tripal_terms_api
+ */
+function hook_vocab_get_root_terms($vocabulary) {
+
 }
 /**
  * Hook used by the default term storage backend to provide details for a vocab.
@@ -294,6 +336,67 @@ function tripal_get_term_details($vocabulary, $accession) {
     }
   }
 }
+/**
+ * Retrieves the immediate children of the given term.
+ *
+ * @param $vocabulary
+ *   The vocabulary of the vocabulary in which the term is found.
+ * @param $accession
+ *   The unique identifier (accession) for this term.
+ *
+ * @return
+ *   Returns an array of terms where each term is compatible with the
+ *   array returned by the tripal_get_term_details() function.
+ *
+ * @ingroup tripal_terms_api
+ */
+function tripal_get_vocabulary_root_terms($vocabulary) {
+  if (empty($vocabulary)) {
+    tripal_report_error('tripal_term', TRIPAL_ERROR, 'Unable to retrieve details for term due to missing vocabulary.');
+  }
+
+  // TODO: we need some sort of administrative interface that lets the user
+  // switch to the desired vocabulary type. For now, we'll just use the
+  // first one in the list.
+  $stores = module_invoke_all('vocab_storage_info');
+  if (is_array($stores) and count($stores) > 0) {
+    $keys = array_keys($stores);
+    $module = $stores[$keys[0]]['module'];
+    $function = $module . '_vocab_get_root_terms';
+    if (function_exists($function)) {
+      return $function($vocabulary);
+    }
+  }
+}
+/**
+ * Retrieves the immediate children of the given term.
+ *
+ * @param $vocabulary
+ *   The vocabulary of the vocabulary in which the term is found.
+ * @param $accession
+ *   The unique identifier (accession) for this term.
+ *
+ * @return
+ *   Returns an array of terms where each term is compatible with the
+ *   array returned by the tripal_get_term_details() function.
+ *
+ * @ingroup tripal_terms_api
+ */
+function tripal_get_term_children($vocabulary, $accession) {
+  if (empty($vocabulary) OR empty($accession)) {
+    tripal_report_error('tripal_term', TRIPAL_ERROR, 'Unable to retrieve details for term due to missing vocabulary and/or accession.');
+  }
+
+  $stores = module_invoke_all('vocab_storage_info');
+  if (is_array($stores) and count($stores) > 0) {
+    $keys = array_keys($stores);
+    $module = $stores[$keys[0]]['module'];
+    $function = $module . '_vocab_get_term_children';
+    if (function_exists($function)) {
+      return $function($vocabulary, $accession);
+    }
+  }
+}
 /**
  * Retrieves full information about a vocabulary.
  *

+ 122 - 3
tripal/includes/tripal.term_lookup.inc

@@ -27,7 +27,19 @@ function tripal_vocabulary_lookup_form_submit($form, $form_state) {
 
 function tripal_vocabulary_lookup_page($vocabulary) {
 
+  // set the breadcrumb
+  $breadcrumb = array();
+  $breadcrumb[] = l('Home', '<front>');
+  $breadcrumb[] = l('Controlled Vocabularies', 'cv/lookup');
+  drupal_set_breadcrumb($breadcrumb);
+
   $vocab = tripal_get_vocabulary_details($vocabulary);
+  if ($vocab['description']) {
+    drupal_set_title($vocab['description']);
+  }
+  else {
+    drupal_set_title($vocabulary);
+  }
 
   // If we can't find the term then just return a message.
   if (!$vocab) {
@@ -41,11 +53,12 @@ function tripal_vocabulary_lookup_page($vocabulary) {
   if ($vocab['url']) {
     $vocab_name = l($vocab['name'], $vocab['url'], array('attributes' => array('target' => '_blank')));
   }
+
   $short_name = $vocab['short_name'];
   $vocab_desc = $vocab['description'];
   $rows[] = array(
     array(
-      'data' => 'Name',
+      'data' => 'Vocabulary Name(s)',
       'header' => TRUE,
       'width' => '20%',
     ),
@@ -73,13 +86,99 @@ function tripal_vocabulary_lookup_page($vocabulary) {
     'rows' => $rows,
     'attributes' => array(),
     'sticky' => FALSE,
-    'caption' => 'Vocabulary details',
+    'caption' => '',
     'colgroups' => array(),
     'empty' => '',
   );
-  $content =  theme_table($table);
+
+  $root_terms = tripal_get_vocabulary_root_terms($vocabulary);
+  $items = tripal_vocabulary_lookup_term_children_format($root_terms);
+
+  drupal_add_js(array(
+    'tripal' => array(
+      'cv_lookup' => array(
+        'vocabulary' => $vocabulary,
+      ),
+    ),
+  ), 'setting');
+
+  $content = array(
+    'vocab_table' => array(
+      '#type' => 'item',
+      '#title' => 'Details',
+      '#markup' => theme_table($table),
+    ),
+    'vocab_browser' => array(
+      '#type' => 'item',
+      '#title' => 'Term Browser',
+      '#markup' => $items,
+    ),
+  );
+
+  // Add support for our custom tree viewer
+  drupal_add_css(drupal_get_path('module', 'tripal') . '/theme/css/tripal.cv_lookup.css');
+  drupal_add_js(drupal_get_path('module', 'tripal') . '/theme/js/tripal.cv_lookup.js', 'file');
+
   return $content;
 }
+
+/**
+ * A helper function to format an array of terms into a list for the web page.
+ *
+ * @param $children
+ *   A list of children terms.
+ */
+function tripal_vocabulary_lookup_term_children_format($children) {
+  $items = '<ul id="tripal-cv-lookup-tree">';
+  foreach ($children as $child) {
+    $grand = tripal_get_term_children($child['vocabulary']['short_name'], $child['accession']);
+    $num_grand = count($grand);
+    $items .= '<li vocabulary = "' . $child['vocabulary']['short_name'] . '" ' .
+        'accession = "' . $child['accession'] . '" ' .
+        'children = "' . $num_grand . '" ' .
+        'state = "closed" '.
+        'class = "cv-lookup-tree-node">';
+    $class = 'tree-node-closed';
+    if ($num_grand == 0) {
+      $class = 'tree-node-single';
+    }
+    $items .= '<i class = "tree-node-icon ' . $class . '"></i>';
+    $items .= l($child['name'], 'cv/lookup/' . $child['vocabulary']['short_name'] . '/' . $child['accession'], array('attributes' => array('target' => '_blank'))) . ' (' . $num_grand . ')';
+    $items .= '</li>';
+  }
+  $items .= '</ul>';
+
+  if (count($children)== 0) {
+    $items ='';
+  }
+
+  return $items;
+}
+
+/**
+ * An ajax callback to get the children of a term.
+ *
+ * @param $vocabulary
+ *   The short name of the vocabulary (e.g. SO, GO, etc.)
+ * @param $accession
+ *   The term accession.
+ *
+ * @return
+ *   A JSON array compatible with the JSTree library.
+ *   https://www.jstree.com/docs/json/
+ */
+function tripal_vocabulary_lookup_term_children_ajax($vocabulary, $accession) {
+
+  $term = tripal_get_term_details($vocabulary, $accession);
+  $children = tripal_get_term_children($vocabulary, $accession);
+  $response = array(
+    'vocabulary' => $vocabulary,
+    'accession' => $accession,
+    'content' => tripal_vocabulary_lookup_term_children_format($children)
+  );
+  drupal_json_output($response);
+}
+
 /**
  *
  * @param $vocabulary
@@ -88,7 +187,17 @@ function tripal_vocabulary_lookup_page($vocabulary) {
  * @return
  */
 function tripal_vocabulary_lookup_term_page($vocabulary, $accession) {
+
+  // set the breadcrumb
+  $breadcrumb = array();
+  $breadcrumb[] = l('Home', '<front>');
+  $breadcrumb[] = l('Controlled Vocabularies', 'cv/lookup');
+  $breadcrumb[] = l($vocabulary, 'cv/lookup/' . $vocabulary);
+  drupal_set_breadcrumb($breadcrumb);
+
   $term = tripal_get_term_details($vocabulary, $accession);
+  drupal_set_title($term['name']);
+
 
   // If we can't find the term then just return a message.
   if (!$term) {
@@ -184,5 +293,15 @@ function tripal_vocabulary_lookup_term_page($vocabulary, $accession) {
     'empty' => '',
   );
   $content .=  theme_table($table);
+
+  drupal_add_js(array(
+    'tripal' => array(
+      'cv_lookup' => array(
+        'vocabulary' => $vocabulary,
+        'accession' => $accession,
+      ),
+    ),
+  ), 'setting');
+
   return $content;
 }

+ 54 - 0
tripal/theme/css/tripal.cv_lookup.css

@@ -0,0 +1,54 @@
+#tripal-cv-lookup-tree {
+  list-style-type: none;
+  margin: 0;
+  padding: 0;
+}
+#tripal-cv-lookup-tree .tree-node-icon {
+  width: 22px;
+  height: 22px;
+  line-height: 22px;
+  display: inline-block;
+  vertical-align: top;
+  text-align: center;
+  cursor: pointer;
+  text-indent: 0;
+}
+#tripal-cv-lookup-tree .tree-node-loading {
+  background: url(../images/ajax-loader.gif) no-repeat;
+  background-size: 22px 22px;
+}
+#tripal-cv-lookup-tree .tree-node-closed {
+  background: url(../images/tree-node-closed.png) no-repeat;
+  background-size: 22px 22px;
+}
+#tripal-cv-lookup-tree .tree-node-open {
+  background: url(../images/tree-node-open.png) no-repeat;
+  background-size: 22px 22px;
+}
+#tripal-cv-lookup-tree .tree-node-single {
+  background: url(../images/tree-node-single.png) no-repeat;
+  background-size: 22px 22px;
+}
+#tripal-cv-lookup-tree li:last-child .tree-node-closed {
+  background: url(../images/tree-node-closed-last.png) no-repeat;
+  background-size: 22px 22px;
+}
+#tripal-cv-lookup-tree li:last-child .tree-node-single {
+  background: url(../images/tree-node-single-last.png) no-repeat;
+  background-size: 22px 22px;
+}
+#tripal-cv-lookup-tree ul {
+  margin-left: 10px;
+}
+
+#tripal-cv-lookup-tree li {
+  margin: 0;
+  padding: 0 12px;
+  line-height: 22px;
+  color: #369;
+}
+
+#tripal-cv-lookup-tree a {
+  border-bottom-width: 1px;
+  border-bottom-style: dotted;
+}

BIN
tripal/theme/images/tree-node-closed-last.png


BIN
tripal/theme/images/tree-node-closed.png


BIN
tripal/theme/images/tree-node-open.png


BIN
tripal/theme/images/tree-node-single-last.png


BIN
tripal/theme/images/tree-node-single.png


+ 60 - 0
tripal/theme/js/tripal.cv_lookup.js

@@ -0,0 +1,60 @@
+(function ($) {
+  
+  Drupal.behaviors.TripalCVLookup = {
+    attach: function (context, settings) {
+
+      $('.tree-node-closed').on("click", function(event) {
+        expandNode($(this));
+      });
+    }
+  }
+  
+  /**
+   * Collapses a node in the CV tree browser and removes its children.
+   */
+  function collapseNode(item) {
+    var parent = $(item).parent('li');
+    parent.children('i').removeClass('tree-node-open');
+    parent.children('i').addClass('tree-node-closed');
+    parent.children('ul').remove();
+    
+   // Add the click for expanding the node now that this node is expaded.
+    parent.children('i').unbind('click');
+    parent.children('i').on("click", function(event){
+      expandNode($(this));
+    }) 
+  }
+  
+  /**
+   * Expands a node in the CV tree browser and loads it's children via AJAX.
+   */
+  function expandNode(item){
+    
+    var parent = $(item).parent('li');
+    var vocabulary = parent.attr('vocabulary');
+    var accession = parent.attr('accession');
+    parent.children('i').removeClass('tree-node-closed');
+    parent.children('i').addClass('tree-node-loading');
+    
+    // Add the click for collapsing the node now that htis node is expaded.
+    parent.children('i').unbind('click');
+    parent.children('i').on("click", function(event){
+      collapseNode($(this));
+    }) 
+    
+    $.ajax({
+      url : baseurl + '/cv/lookup/' + vocabulary + '/' + accession + '/children',
+    })
+    .done(function(data) {
+      parent.append(data.content);
+      parent.children('i').removeClass('tree-node-loading');
+      parent.children('i').addClass('tree-node-open');
+      // Add the click event to new DOM elements.
+      var nodes = parent.find('.tree-node-closed');
+      nodes.on("click", function(event) {
+        expandNode($(this));
+      });
+    })
+  }
+
+})(jQuery);

+ 10 - 1
tripal/tripal.module

@@ -287,7 +287,7 @@ function tripal_menu() {
 //   );
 
   $items['cv/lookup/%'] = array(
-    'title' => 'Vocabulary Lookup',
+    'title' => 'Vocabulary Details',
     'description' => t("Provides a tool to discover controlled vocabularies"),
     'access arguments' => array('access content'),
     'page callback' => 'tripal_vocabulary_lookup_page',
@@ -308,6 +308,15 @@ function tripal_menu() {
     'type' => MENU_CALLBACK,
   );
 
+  $items['cv/lookup/%/%/children'] = array(
+    'access arguments' => array('access content'),
+    'page callback' => 'tripal_vocabulary_lookup_term_children_ajax',
+    'page arguments' => array(2, 3),
+    'file' => 'includes/tripal.term_lookup.inc',
+    'file path' => drupal_get_path('module', 'tripal'),
+    'type' => MENU_CALLBACK,
+  );
+
   // Adds a +Check for new fields link on the 'Tripal Content Types' page.
   $items['admin/structure/bio_data/manage/%/fields/check'] = array(
     'title' => 'Check for new fields',

+ 9 - 0
tripal_chado/includes/TripalImporter/OBOImporter.inc

@@ -406,6 +406,15 @@ class OBOImporter extends TripalImporter {
    */
   public function postRun() {
 
+    // Update the cv_root_mview materiailzed view.
+    $this->logMessage("Updating the cv_root_mview materialized view...");
+    $mview_id = tripal_get_mview_id('cv_root_mview');
+    tripal_populate_mview($mview_id);
+
+    $this->logMessage("Updating the db2cv_mview materialized view...");
+    $mview_id = tripal_get_mview_id('db2cv_mview');
+    tripal_populate_mview($mview_id);
+
     // Upate the cvtermpath table for each newly added CV.
     $this->logMessage("Updating cvtermpath table.  This may take a while...");
     foreach ($this->newcvs as $namespace => $cvid) {

+ 55 - 4
tripal_chado/includes/setup/tripal_chado.chado_vx_x.inc

@@ -112,7 +112,6 @@ function tripal_chado_add_tripal_gffprotein_temp_table() {
 /**
  * Creates a temporary table to store obo details while loading an obo file
  *
- * @ingroup tripal_cv
  */
 function tripal_chado_add_tripal_obo_temp_table() {
   // the tripal_obo_temp table is used for temporary housing of records when loading OBO files
@@ -409,9 +408,61 @@ function tripal_chado_add_analysis_organism_mview() {
 }
 
 /**
- * Add a materialized view of root terms for all chado cvs. This is needed for viewing cv trees
+ * Add a materialized view that maps cv to db records.
+ *
+ * This is needed for viewing cv trees
+ *
+ */
+function tripal_chado_add_db2cv_mview_mview() {
+  $mv_name = 'db2cv_mview';
+  $comment = 'A table for quick lookup of the vocabularies and the databases they are associated with.';
+  $schema = array(
+    'table' => $mv_name,
+    'description' => $comment,
+    'fields' => array (
+      'cv_id' => array (
+        'type' => 'int',
+        'not null' => true,
+      ),
+      'cvname' => array (
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => true,
+      ),
+      'db_id' => array (
+        'type' => 'int',
+        'not null' => true,
+      ),
+      'dbname' => array (
+        'type' => 'varchar',
+        'length' => '255',
+        'not null' => true,
+      ),
+    ),
+    'indexes' => array (
+      'cv_id_idx'  => array ('cv_id'),
+      'cvname_idx'    => array ('cvname'),
+      'db_id_idx' => array ('db_id'),
+      'dbname_idx'    => array ('db_id'),
+    ),
+  );
+
+  $sql = "
+   SELECT DISTINCT CV.cv_id, CV.name as cvname, DB.db_id, DB.name as dbname
+   FROM cv CV
+     INNER JOIN cvterm CVT on CVT.cv_id = CV.cv_id
+     INNER JOIN dbxref DBX on DBX.dbxref_id = CVT.dbxref_id
+     INNER JOIN db DB on DB.db_id = DBX.db_id
+  ";
+
+  // Create the MView
+  tripal_add_mview($mv_name, 'tripal_chado', $schema, $sql, $comment);
+}
+/**
+ * Add a materialized view of root terms for all chado cvs.
+ *
+ * This is needed for viewing cv trees
  *
- * @ingroup tripal_cv
  */
 function tripal_chado_add_cv_root_mview_mview() {
   $mv_name = 'cv_root_mview';
@@ -457,6 +508,6 @@ function tripal_chado_add_cv_root_mview_mview() {
   ";
 
   // Create the MView
-  tripal_add_mview($mv_name, 'tripal_cv', $schema, $sql, $comment);
+  tripal_add_mview($mv_name, 'tripal_chado', $schema, $sql, $comment);
 }
 

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

@@ -205,6 +205,15 @@ function tripal_chado_prepare_chado($job = NULL) {
     drush_print("Loading Ontologies...");
     tripal_chado_load_ontologies();
 
+    // Populate the mviews based on controlled vocabularies.
+    drush_print('Populating materialized view db2cv_mview...');
+    $mview_id = tripal_get_mview_id('db2cv_mview');
+    tripal_populate_mview($mview_id);
+
+    drush_print('Populating materialized view cv_root_mview...');
+    $mview_id = tripal_get_mview_id('cv_root_mview');
+    tripal_populate_mview($mview_id);
+
     if ($report_progress) {
       $job->setProgress(50);
     }
@@ -527,6 +536,7 @@ function tripal_chado_add_vx_x_custom_tables(){
   tripal_chado_add_organism_feature_count_mview();
   tripal_chado_add_analysis_organism_mview();
   tripal_chado_add_cv_root_mview_mview();
+  tripal_chado_add_db2cv_mview_mview();
 }
 
 /**

+ 103 - 8
tripal_chado/includes/tripal_chado.vocab_storage.inc

@@ -29,14 +29,12 @@ function tripal_chado_vocab_get_vocabulary($vocabulary) {
     return FALSE;
   }
   $sql = "
-     SELECT DB.name as short_name, CV.name as name, DB.description, DB.url, DB.urlprefix
+     SELECT DB.name as short_name, DB.description, DB.url, DB.urlprefix,
+       string_agg(DBCVM.cvname, ', ') as name
      FROM {db} DB
-      LEFT JOIN {dbxref} DBX on DBX.db_id = DB.db_id
-      LEFT JOIN {cvterm} CVT on CVT.dbxref_id = DBX.dbxref_id
-      LEFT JOIN {cv} CV on CV.cv_id = CVT.cv_id
-     WHERE
-      DB.name = :name
-     LIMIT 1 OFFSET 0
+      INNER JOIN {db2cv_mview} DBCVM ON DBCVM.db_id = DB.db_id
+     WHERE DB.name = :name
+     GROUP BY DB.name, DB.description, DB.url, DB.urlprefix
   ";
   $result = chado_query($sql, array(':name' => $vocabulary));
   $result = $result->fetchAssoc();
@@ -51,10 +49,96 @@ function tripal_chado_vocab_get_vocabulary($vocabulary) {
     $sw_url = url($sw_url, array('absolute' => TRUE));
   }
   $result['sw_url'] = $sw_url;
-  unset($result['short_name']);
   return $result;
 }
 
+
+/**
+ * Implements hook_vocab_get_root_terms().
+ *
+ * This hook is created by the Tripal module and is not a Drupal hook.
+ */
+function tripal_chado_vocab_get_root_terms($vocabulary) {
+  $terms = array();
+
+
+  // It's possible that Chado is not available (i.e. it gets renamed
+  // for copying) but Tripal has already been prepared and the
+  // entities exist.  If this is the case we don't want to run the
+  // commands below.
+  if (!chado_table_exists('db')) {
+    return FALSE;
+  }
+
+
+  // Get the list of CV's that belong to this vocabulary and get their
+  // roots.
+  $sql = "
+    SELECT *
+    FROM {db2cv_mview} WHERE dbname = :dbname
+  ";
+  $cvs = chado_query($sql, array(':dbname' => $vocabulary));
+  while ($cv = $cvs->fetchObject()) {
+    $sql = "
+      SELECT cvterm_id
+      FROM {cv_root_mview} CRM
+      WHERE CRM.cv_id = :cv_id
+    ";
+    $results = chado_query($sql, array(':cv_id' => $cv->cv_id));
+    while($cvterm_id = $results->fetchField()) {
+      $match = array('cvterm_id' => $cvterm_id);
+      $cvterm = chado_generate_var('cvterm', $match);
+      $terms[] = _tripal_chado_format_term_description($cvterm);
+    }
+  }
+  return $terms;
+}
+/**
+ * Implements hook_vocab_get_term_children().
+ *
+ * This hook is created by the Tripal module and is not a Drupal hook.
+ */
+function tripal_chado_vocab_get_term_children($vocabulary, $accession) {
+  $terms = array();
+
+  // It's possible that Chado is not available (i.e. it gets renamed
+  // for copying) but Tripal has already been prepared and the
+  // entities exist.  If this is the case we don't want to run the
+  // commands below.
+  if (!chado_table_exists('cvtermpath')) {
+    return FALSE;
+  }
+
+  // Get the parent cvterm.
+  $match = array(
+    'dbxref_id' => array(
+      'db_id' => array(
+        'name' => $vocabulary,
+      ),
+      'accession' => $accession,
+    ),
+  );
+  $cvterm = chado_generate_var('cvterm', $match);
+  if (!$cvterm) {
+    return FALSE;
+  }
+  $cvterm = chado_expand_var($cvterm, 'field', 'cvterm.definition');
+
+
+  // Get the children
+  $sql = "
+    SELECT subject_id
+    FROM {cvterm_relationship} CVTR
+    WHERE object_id = :object_id
+  ";
+  $results = chado_query($sql, array(':object_id' => $cvterm->cvterm_id));
+  while($cvterm_id = $results->fetchField()) {
+    $match = array('cvterm_id' => $cvterm_id);
+    $cvterm = chado_generate_var('cvterm', $match);
+    $terms[] = _tripal_chado_format_term_description($cvterm);
+  }
+  return $terms;
+}
 /**
  * Implements hook_vocab_get_term().
  *
@@ -69,6 +153,7 @@ function tripal_chado_vocab_get_term($vocabulary, $accession) {
   if (!chado_table_exists('cvterm')) {
     return FALSE;
   }
+
   $match = array(
     'dbxref_id' => array(
       'db_id' => array(
@@ -83,6 +168,16 @@ function tripal_chado_vocab_get_term($vocabulary, $accession) {
   }
   $cvterm = chado_expand_var($cvterm, 'field', 'cvterm.definition');
 
+  return _tripal_chado_format_term_description($cvterm);
+}
+
+/**
+ * A helper functions for the hook_vocab_xxx functions.
+ *
+ * @param $cvterm
+ *   A cvterm object.
+ */
+function _tripal_chado_format_term_description($cvterm) {
   $url = $cvterm->dbxref_id->db_id->url;
   $urlprefix = $cvterm->dbxref_id->db_id->urlprefix;
 

+ 22 - 0
tripal_chado/tripal_chado.install

@@ -1467,5 +1467,27 @@ function tripal_chado_update_7322() {
     throw new DrupalUpdateException('Could not perform update: '. $error);
   }
 }
+/**
+ * Adding the db2cv materialized view.
+ */
+function tripal_chado_update_7323() {
+  try {
+    module_load_include('inc', 'tripal_chado', 'includes/setup/tripal_chado.chado_vx_x');
+    tripal_chado_add_db2cv_mview_mview();
+
+    drupal_set_message('Populating materialized view db2cv_mview...');
+    $mview_id = tripal_get_mview_id('db2cv_mview');
+    tripal_populate_mview($mview_id);
+
+    drupal_set_message('Populating materialized view cv_root_mview...');
+    $mview_id = tripal_get_mview_id('cv_root_mview');
+    tripal_populate_mview($mview_id);
+  }
+  catch (\PDOException $e) {
+    $error = $e->getMessage();
+    throw new DrupalUpdateException('Could not perform update: '. $error);
+  }
+}
+
 
 

+ 1 - 1
tripal_ws/includes/TripalFields/remote__data/remote__data_widget.inc

@@ -79,7 +79,7 @@ class remote__data_widget extends WebServicesFieldWidget {
     $tokens = tripal_get_entity_tokens($bundle_info);
     // If the field already has a value then it will come through the $items
     // array.  This happens when editing an existing record.
-    dpm($items);
+
     // FORM PROPER
     $widget['#prefix'] =  "<span id='$field_name-remote_data-$delta'>";
     $widget['#suffix'] =  "</span>";