Browse Source

Improvements to performance for views integration of TripalFields

Stephen Ficklin 6 years ago
parent
commit
496cb4e680

+ 0 - 39
tripal/includes/tripal.fields.inc

@@ -82,45 +82,6 @@ function tripal_field_widget_info_alter(&$info) {
 
 }
 
-/**
- * Implements hook_field_views_data();
- */
-function tripal_field_views_data($field) {
-  $data = array();
-
-  // Skip fields that aren't attached to TripalEntity entities.
-  if (!array_key_exists('TripalEntity', $field['bundles'])) {
-    return $data;
-  }
-
-  if (!array_key_exists('tripal_storage_api', $field['storage']['settings'])) {
-    return $data;
-  }
-
-  $field_type = $field['type'];
-  $field_types = tripal_get_field_types();
-
-  // Iterate through the bundles to which this field is attached and
-  // if it is a TripalField field then we'll call the viewsDataAlater function.
-  $bundles = $field['bundles']['TripalEntity'];
-  foreach ($bundles as $bundle_name) {
-    $instance = field_info_instance('TripalEntity', $field['field_name'], $bundle_name);
-    if (in_array($field_type, $field_types)) {
-      $tfield = new $field_type($field, $instance);
-
-      // Fields should be associated with the bundle's term identifier
-      // (i.e. [vocab]__[accession].
-      $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
-      $term = tripal_load_term_entity(array('term_id' => $bundle->term_id));
-      $view_base_id = $term->vocab->vocabulary . '__' . $term->accession;
-
-      $data += $tfield->viewsData($view_base_id);
-    }
-  }
-
-  return $data;
-}
-
 /**
  * Implements hook_field_formatter_info().
  */

+ 67 - 34
tripal/tripal.views.inc

@@ -28,9 +28,11 @@ function tripal_views_plugins() {
  */
 function tripal_views_data() {
   $data = array();
-  // Job Management System
+  // Job Management System.
   tripal_views_data_jobs($data);
-  tripal_views_data_tripal_entity($data);
+  // Add all TripalEntity bundles. 
+  tripal_views_data_tripal_bundles($data);
+  // Add all the TripalFields for each bundle.
   tripal_views_data_fields($data);
 
   $data['views']['tripal_area_collections'] = array(
@@ -116,60 +118,91 @@ function tripal_views_data_alter(&$data) {
  * Integreates the Tripal fields with Views.
  */
 function tripal_views_data_fields(&$data) {
-
+  
+  // Get the bundle details so we only look this up once.
+  $all_bundles = [];
+  $sql = "
+    SELECT TB.name, TV.vocabulary, TT.accession
+    FROM {tripal_bundle} TB
+      INNER JOIN {tripal_term} TT on TT.id = TB.term_id
+      INNER JOIN {tripal_vocab} TV on TV.id = TT.vocab_id
+  ";
+  $results = db_query($sql, [':bundle_name' => $bundle_name]);
+  while ($bundle = $results->fetchObject()) {
+    $all_bundles[$bundle->name] = $bundle;
+  }
+  
+  // Get all of the TripalField types.
+  $tripal_field_types = tripal_get_field_types();
+  
   // Iterate through the fields.
   $fields = field_info_fields();
   foreach ($fields as $field) {
+    $field_type = $field['type'];
 
     // Skip fields that aren't attached to TripalEntity entities.
     if (!array_key_exists('TripalEntity', $field['bundles'])) {
       continue;
     }
 
-    // Fields that don't connect to the Tripal Storage API should be added differently
+    // Fields that don't connect to the Tripal Storage API should be added 
+    // differently
     if (!array_key_exists('tripal_storage_api', $field['storage']['settings'])) {
       continue;
-    }
+    }    
+
+    // Get the field data for views.
+    $fdata = [];    
 
-    // TODO: do we really need this hook? Just substitute the code here
-    // for what that hook does... it's only called in one plac.e
-    // Call the hook_field_views_data() but only for the tripal module.
-    // Otherwise the other modules will expect that this is an SQL-based
-    // view.
-    $result = (array) module_invoke('tripal', 'field_views_data', $field);
-
-    // Set defaults for the field if no data array was returned.
-    if (empty($result)) {
-      // Iterate through the bundles to which this field is attached and
-      // if it is a TripalField field then we'll call the viewsData function.
-      $bundles = $field['bundles']['TripalEntity'];
-      $result = array();
-      foreach ($bundles as $bundle_name) {
-        $field_name = $field['field_name'];
-
-        // Fields should be associated with the bundle's term identifier
-        // (i.e. [vocab]__[accession].
-        $bundle = tripal_load_bundle_entity(array('name' => $bundle_name));
-        $term = tripal_load_term_entity(array('term_id' => $bundle->term_id));
-        $view_base_id = $term->vocab->vocabulary . '__' . $term->accession;
-
-        $instance = field_info_instance('TripalEntity', $field['field_name'], $bundle_name);
+    // Iterate through the bundles to which this field is attached. If the field
+    // is attached to only one bundle then it comes as a scalar and we need
+    // to make it an array.
+    $bundles = $field['bundles']['TripalEntity'];
+    if (!is_array($bundles)) {
+      $bundles = [$bundles];
+    }
+    foreach ($bundles as $bundle_name) {
+      
+      // Sometimes a field may be attached to a bundle that may have been
+      // deleted.  Let's skip those.
+      if (!in_array($bundle_name, array_keys($all_bundles))) {
+        continue;
+      }        
+
+      // Fields should be associated with the bundle's term identifier
+      // (i.e. [vocab]__[accession].
+      $vocabulary = $all_bundles[$bundle_name]->vocabulary;
+      $accession = $all_bundles[$bundle_name]->accession;
+      $view_base_id = $vocabulary . '__' . $accession;
+            
+      // Fields that aren't a TripalField class should be handled using the 
+      // generic TripalField::viewsData function.
+      $instance = field_info_instance('TripalEntity', $field['field_name'], $bundle_name);
+      if (!in_array($field_type, $tripal_field_types)) {
         $tfield = new TripalField($field, $instance);
-        $result += $tfield->viewsData($view_base_id);
+        $fdata += $tfield->viewsData($view_base_id);
+      }
+      // Fields that are a TripalField class can call the viewsData function
+      // for that class.
+      else {
+        $tfield = new $field_type($field, $instance);
+        $fdata += $tfield->viewsData($view_base_id);
       }
     }
 
-    drupal_alter('field_views_data', $result, $field, $module);
+    // Call the hook_field_views_data_alter function.
+    drupal_alter('field_views_data', $fdata, $field);
 
-    if (is_array($result)) {
-      $data = drupal_array_merge_deep($result, $data);
+    if (is_array($fdata)) {
+      $data = drupal_array_merge_deep($fdata, $data);
     }
   }
 }
+
 /**
- * Integrates the TripalEntity entities with Drupal Views.
+ * Integrates the TripalEntity bundles with Drupal Views.
  */
-function tripal_views_data_tripal_entity(&$data) {
+function tripal_views_data_tripal_bundles(&$data) {
 
   // Get the list of all of the bundles (entity types) and add them
   // as "base tables" for views.

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

@@ -3180,7 +3180,7 @@ function tripal_chado_form_tripalbundle_form_alter(&$form, $form_state) {
 /**
  * Implements hook_field_views_data_alter();
  */
-function tripal_chado_field_views_data_alter(&$result, $field, $module) {
+function tripal_chado_field_views_data_alter(&$result, $field) {
 
   // This module creates the data__image field for managing images on
   // bio_data content types. But we want it to render correctly

+ 0 - 131
tripal_chado/tripal_chado.views.inc

@@ -22,137 +22,6 @@ function tripal_chado_views_data() {
   return $data;
 }
 
-// /**
-//  * Implements hook_views_data_alter().
-//  */
-// function tripal_chado_views_data_alter(&$data) {
-
-//   // Adds integration for chado-based fields.
-//   tripal_chado_add_field_views_data($data);
-
-//   return $data;
-// }
-
-// /**
-//  * Adds integration for chado-based fields.
-//  *
-//  * We can't use hook_field_view_data since this only works when the
-//  * storage engine is of type 'field_sql_storage' and of course,
-//  * ours is not. Thus we create our own implementation of field_views_data()
-//  * for our storage engine.
-//  */
-// function tripal_chado_add_field_views_data(&$data) {
-//   foreach (field_info_fields() as $field) {
-//     if ($field['storage']['type'] != 'field_chado_storage') {
-//       continue;
-//     }
-
-//     $field_name = $field['field_name'];
-//     $field_type = $field['type'];
-
-
-//     // Currently, we only handle integration of chado fields with TripalEntity.
-//     // @todo: extend this to work with other entities in the future.
-//     if (isset($field['bundles']['TripalEntity']) AND isset($field['settings']['chado_column'])) {
-
-//       // We currently don't support prop tables for views integration due
-//       // in part to the multiple values but also b/c we can't indicate which
-//       // type of property to show. Thus, instead of warning the user,
-//       // we just won't integrate it at this time.
-//       // @todo: Handle property fields.
-//       if (preg_match('/prop$/', $field['settings']['chado_table'])) {
-//         continue;
-//       }
-
-//       // Get some information about the chado table in order to make good
-//       // default choices for handlers.
-//       $table_desc = chado_get_schema($field['settings']['chado_table']);
-//       $field_defn = $table_desc['fields'][ $field['settings']['chado_column'] ];
-
-//       // We also need to know if this field is a foreign key.
-//       $fk_defn = FALSE;
-//       foreach ($table_desc['foreign keys'] as $details) {
-//         foreach ($details['columns'] as $left_field => $right_field) {
-//           if ($left_field == $field['settings']['chado_column']) {
-//             $fk_defn = array(
-//               'left_table' => $field['settings']['chado_table'],
-//               'left_field' => $left_field,
-//               'right_table' => $details['table'],
-//               'right_field' => $right_field,
-//             );
-//           }
-//         }
-//       }
-
-//       // Unfortunatly we can't use the field label since that is set at the
-//       // instance level and fields are integrated at the field level (independant of bundle).
-//       // Thus we will simply make the most readable and informative field name we can.
-//       $data['tripal_entity'][$field_name]['title'] = ucfirst(str_replace('_',' ',$field['settings']['chado_table']))
-//         . ': ' .ucfirst(str_replace('_',' ',$field['settings']['chado_column']));
-
-//       // The help should be 'Appears in: TripalEntity: gene, organism'
-//       // so that users know where they can use it. This requires a little extra work since all
-//       // we have access to at this point is bio_data_2, bio_data_4 but since that's not very
-//       // informative, extra work is worth it ;-).
-//       $entity_info = entity_get_info('TripalEntity');
-//       $bundle_labels = array();
-//       foreach ($field['bundles']['TripalEntity'] as $bundle_id) {
-//         $bundle_labels[] = $entity_info['bundles'][$bundle_id]['label'];
-//       }
-//       $data['tripal_entity'][$field_name]['help'] = 'Appears in: TripalEntity:' . implode(', ', $bundle_labels);
-
-//       // Define the field.
-//       $data['tripal_entity'][$field_name]['field']['chado_field'] = $field['settings']['chado_column'];
-//       $data['tripal_entity'][$field_name]['field']['chado_table'] = $field['settings']['chado_table'];
-//       $data['tripal_entity'][$field_name]['field']['field_name'] = $field['field_name'];
-//       $data['tripal_entity'][$field_name]['field']['entity_table'] = 'tripal_entity';
-//       $data['tripal_entity'][$field_name]['field']['entity_type'] = 'TripalEntity';
-//       $data['tripal_entity'][$field_name]['field']['bundles'] = $field['bundles']['TripalEntity'];
-//       $data['tripal_entity'][$field_name]['field']['handler'] = 'chado_views_handler_field';
-//       $data['tripal_entity'][$field_name]['field']['click sortable'] = FALSE;
-
-//       // Define the Filter.
-//       $data['tripal_entity'][$field_name]['filter']['chado_field'] = $field['settings']['chado_column'];
-//       $data['tripal_entity'][$field_name]['filter']['chado_table'] = $field['settings']['chado_table'];
-//       $data['tripal_entity'][$field_name]['filter']['field_name'] = $field['field_name'];
-//       $data['tripal_entity'][$field_name]['filter']['entity_table'] = 'tripal_entity';
-//       $data['tripal_entity'][$field_name]['filter']['entity_type'] = 'TripalEntity';
-//       $data['tripal_entity'][$field_name]['filter']['bundles'] = $field['bundles']['TripalEntity'];
-//       $data['tripal_entity'][$field_name]['filter']['handler'] = 'chado_views_handler_filter_string';
-
-//       // Define sorting.
-//       $data['tripal_entity'][$field_name]['sort']['chado_field'] = $field['settings']['chado_column'];
-//       $data['tripal_entity'][$field_name]['sort']['chado_table'] = $field['settings']['chado_table'];
-//       $data['tripal_entity'][$field_name]['sort']['field_name'] = $field['field_name'];
-//       $data['tripal_entity'][$field_name]['sort']['entity_table'] = 'tripal_entity';
-//       $data['tripal_entity'][$field_name]['sort']['entity_type'] = 'TripalEntity';
-//       $data['tripal_entity'][$field_name]['sort']['bundles'] = $field['bundles']['TripalEntity'];
-//       $data['tripal_entity'][$field_name]['sort']['handler'] = 'chado_views_handler_sort';
-
-//       // Specify special handlers.
-//       if ($fk_defn) {
-//         $data['tripal_entity'][$field_name]['filter']['handler'] = 'chado_views_handler_filter_fk';
-//         $data['tripal_entity'][$field_name]['filter']['foreign_key'] = $fk_defn;
-//       }
-//       if ($field_defn['type'] == 'boolean') {
-//         $data['tripal_entity'][$field_name]['filter']['handler'] = 'chado_views_handler_filter_boolean';
-//         $data['tripal_entity'][$field_name]['filter']['label'] = $field['settings']['chado_column'];
-//         $data['tripal_entity'][$field_name]['filter']['type'] = 'yes-no';
-//       }
-//       elseif ($field_defn['type'] == 'datetime') {
-//         $data['tripal_entity'][$field_name]['filter']['handler'] = 'chado_views_handler_filter_date';
-//       }
-
-//       // Allow the fields to alter the default selections from above.
-//       tripal_load_include_field_type($field_type);
-//       if (preg_match('/^chado/', $field_type) and class_exists($field_type)) {
-//         $field_obj = new $field_type($field);
-//         $field_obj->views_data_alter($data['tripal_entity'][$field_name], $field, $entity_info);
-//       }
-//     }
-//   }
-// }
-
 /**
  * Provides the data array for the tripal custom tables management
  *