瀏覽代碼

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

Chun-Huai Cheng 8 年之前
父節點
當前提交
4ac66817c9

+ 7 - 0
tripal/includes/TripalEntityViewsController.inc

@@ -49,6 +49,13 @@ class TripalEntityViewsController extends EntityDefaultViewsController {
     unset($data['tripal_entity']['term_id']);
     unset($data['tripal_entity']['type']);
 
+
+    // This should not be a base table. We're not going to allow
+    // for views based on TripalEntity content types or the list of
+    // fields would become outrageously overwhelming. Instead we will
+    // provide views by bundle.
+    unset($data['tripal_entity']['table']['base']);
+
     return $data;
   }
 

+ 1 - 0
tripal/includes/TripalFieldQuery.inc

@@ -8,6 +8,7 @@ class TripalFieldQuery extends EntityFieldQuery {
 
   protected $field_storage = array();
 
+
   public function execute() {
     // Give a chance for other modules to alter the query.
     drupal_alter('entity_query', $this);

+ 48 - 2
tripal/includes/TripalFields/TripalField.inc

@@ -25,6 +25,13 @@ class TripalField {
   // changed.
   public static $default_settings = array(
     'storage' => 'tripal_no_storage',
+    // It is expected that all fields set a 'value' in the load() function.
+    // In many cases, the value may be an associative array of key/value pairs.
+    // In order for Tripal to provide context for all data, the keys should
+    // be a controlled vocabulary term (e.g. rdfs:type). Keys in the load()
+    // function that are supported by the query() function should be
+    // listed here.
+    'searchable_keys' => array(),
   );
 
   // Provide a list of instance specific settings. These can be access within
@@ -67,6 +74,7 @@ class TripalField {
   // and field_create_instance().
   public static $no_ui = TRUE;
 
+
   // --------------------------------------------------------------------------
   //              PROTECTED CLASS MEMBERS -- DO NOT OVERRIDE
   // --------------------------------------------------------------------------
@@ -111,7 +119,6 @@ class TripalField {
         $accession = $instance['settings']['term_accession'];
         $term = tripal_get_term_details($vocabulary, $accession);
         if (!$term) {
-          dpm(debug_backtrace());
           throw new Error(t('Cannot create TripalField of type "%term" as that
               term does not exist.', array('%term' => "$vocabulary:$accession")));
         }
@@ -288,7 +295,7 @@ class TripalField {
         'click sortable' => TRUE,
       ),
       'filter' => array(
-        'handler' => 'views_handler_filter_string',
+        'handler' => 'tripal_views_handler_filter_string',
       ),
       'sort' => array(
         'handler' => 'views_handler_sort',
@@ -370,4 +377,43 @@ class TripalField {
 
   }
 
+  /**
+   * Used to filter records that match a given condition.
+   *
+   * Entities can be filtered using the fields.  This function should be
+   * implemented if the field  supports filtering.  To provide filtering,
+   * the $query object should be updated to including any joins and
+   * conditions necessary. The following rules should be followed when
+   * implementing this function:
+   * - Any keys from the value array that support filtering should be set
+   *   in the $default_settings['searchable_keys'] array of this class file.
+   * - Implement support for every key in the
+   *   $default_settings['searchable_keys'] array.
+   * - However, avoid making filteres for non-indexed database columns.
+   * - This function should never set the fields that should be returned
+   *   nor ordering or group by.
+   *
+   * @param $query
+   *   A query object appropriate for the data storage backend. For example,
+   *   The Tripal Chado module will provide a SelectQuery object.
+   * @param $condition
+   *   The field specific condition as set in the TripalFieldQuery object.
+   */
+  public function query($query, $condition) {
+
+  }
+
+  /**
+   * Used to sort records that have been filtered.
+   *
+   * @param $query
+   *   A query object appropriate for the data storage backend. For example,
+   *   The Tripal Chado module will provide a SelectQuery object.
+   * @param $order
+   *   The field ordering as set in the TripalFieldQuery object.  This function
+   *   should handle the ordering request as specified by this object.
+   */
+  public function queryOrder($query, $order) {
+
+  }
 }

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

@@ -49,7 +49,7 @@ function tripal_field_storage_load($entity_type, $entities, $age,
       $field_module = $field['module'];
 
       // Get the instnace for this field
-      $instance = field_info_instance($entity_type, $field_name, $entity->bundle); 
+      $instance = field_info_instance($entity_type, $field_name, $entity->bundle);
 
       // Allow the creating module to alter the value if desired.  The
       // module should do this if the field has any other form elements

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

@@ -478,7 +478,6 @@ function tripal_field_instance_settings_form_alter_process($element, &$form_stat
     $term_name = $instance['settings']['term_name'];
     $term = tripal_get_term_details($vocabulary, $accession);
   }
-  dpm($instance);
 
   // Construct a table for the vocabulary information.
   $headers = array();

+ 4 - 1
tripal/tripal.info

@@ -10,12 +10,15 @@ stylesheets[all][] = theme/css/tripal.css
 scripts[]          = theme/js/tripal.js
 
 files[] = views_handlers/tripal_views_handler_field.inc
-files[] = views_handlers/tripal_views_handler_filter_string_selectbox.inc
 files[] = views_handlers/tripal_views_handler_field_entity.inc
 files[] = views_handlers/tripal_views_handler_field_entity_status.inc
 files[] = views_handlers/tripal_views_handler_field_entity_default_formatter.inc
+files[] = views_handlers/tripal_views_handler_filter.inc
+files[] = views_handlers/tripal_views_handler_filter_string.inc
 files[] = views_handlers/tripal_views_handler_filter_entity_string.inc
+files[] = views_handlers/tripal_views_handler_filter_string_selectbox.inc
 files[] = views_handlers/tripal_views_handler_sort_entity_string.inc
+
 files[] = tripal_views_query.inc
 
 dependencies[] = views

+ 1 - 2
tripal/tripal.views.inc

@@ -33,7 +33,6 @@ function tripal_views_data() {
   tripal_entity_views_data($data);
   tripal_views_data_fields($data);
 
-  dpm($data);
   return $data;
 }
 
@@ -104,7 +103,7 @@ function tripal_entity_views_data(&$data) {
         'handler' => 'tripal_views_handler_field_entity',
       ),
       'filter' => array(
-        'handler' => 'views_handler_filter_numeric',
+        'handler' => 'tripal_views_handler_filter',
       ),
       'sort' => array(
         'handler' => 'views_handler_sort',

+ 41 - 15
tripal/tripal_views_query.inc

@@ -9,6 +9,32 @@ class tripal_views_query extends views_plugin_query {
 
   var $filters;
 
+
+  /**
+   * Ensure a table exists in the queue.
+   *
+   * This function overrides the views_plugin_query version of the function
+   * but does nothing other than return the "table" (or bundle) name as
+   * we won't be using aliases for bundles.
+   *
+   * @param $table
+   *   The unaliased name of the table to ensure.
+   * @param $relationship
+   *   The relationship to ensure the table links to. Each relationship will
+   *   get a unique instance of the table being added. If not specified, will
+   *   be the primary table.
+   * @param $join
+   *   A views_join object (or derived object) to join the alias in.
+   *
+   * @return
+   *   The alias used to refer to this specific table, or NULL if the table
+   *   cannot be ensured.
+   */
+  public function ensure_table($table, $relationship = NULL, $join = NULL) {
+    // Because we are not querying a table, we're querying a TripalFieldQuery
+    // object we don't need to ensure the table.
+    return $table;
+  }
   /**
    *
    */
@@ -38,11 +64,23 @@ class tripal_views_query extends views_plugin_query {
   }
 
   /**
+   * Add a simple WHERE clause to the query.
    *
    * @param $group
+   *   The WHERE group to add these to; groups are used to create AND/OR
+   *   sections. Groups cannot be nested. Use 0 as the default group. If the
+   *   group does not yet exist it will be created as an AND group.
    * @param $field
+   *   The name of the field to check.
    * @param $value
+   *   The value to test the field against. In most cases, this is a scalar.
+   *   For more complex options, it is an array. The meaning of each element
+   *   in the array is dependent on the $operator.
    * @param $operator
+   *   The comparison operator, such as =, <, or >=. It also accepts more
+   *   complex options such as IN, LIKE, or BETWEEN. Defaults to IN if $value
+   *   is an array = otherwise. If $field is a string you have to use 'formula'
+   *   here.
    */
   public function add_where($group, $field_name, $value = NULL, $operator = NULL) {
     // Remove the preceeding period from the $field_name
@@ -84,7 +122,6 @@ class tripal_views_query extends views_plugin_query {
       $entities = array($entity_id => $stub);
       $view->result[$i] = new stdClass();
       $view->result[$i]->entity = $stub;
-      $view->result[$i]->entity_id = $entity_id;
       foreach ($this->fields as $details) {
         $field_name = $details['field_name'];
         $field = field_info_field($field_name);
@@ -92,24 +129,13 @@ class tripal_views_query extends views_plugin_query {
             $entities, FIELD_LOAD_CURRENT, array($field['id'] => array($entity_id)));
         $view->result[$i]->$field_name = $entities[$entity_id]->$field_name['und'][0]['value'];
       }
+      $view->result[$i]->entity_id = $stub->id;
       $i++;
     }
     $view->execute_time = microtime(TRUE) - $start;
     $view->current_page = 0;
-    dpm($view->query);
-    dpm($view->result);
+    //dpm($view->query);
+    //dpm($view->result);
   }
 
-  /**
-   * Generate a query and a countquery from all of the information supplied
-   * to the object.
-   *
-   * @param $get_count
-   *   Provide a countquery if this is true, otherwise provide a normal query.
-   *
-   * @return SelectQuery
-   *   A SelectQuery object.
-   */
-  function query($get_count = FALSE) {
-  }
 }

+ 13 - 1
tripal/views_handlers/tripal_views_handler_field.inc

@@ -9,7 +9,9 @@
  */
 class tripal_views_handler_field extends views_handler_field {
 
-
+  /**
+   *
+   */
   function query() {
     parent::query();
     // We need to add an alias to our TripalFields so that the
@@ -33,6 +35,16 @@ class tripal_views_handler_field extends views_handler_field {
    */
   function get_value($values, $field = NULL) {
     $alias = isset($field) ? $this->aliases[$field] : $this->field_alias;
+
+    // For some reason the alias isn't being added to the $this->aliases
+    // variable when the user clicks the checkbox 'Link this field to the
+    // original piece of content'.  That may need to be investigated and is
+    // probably a side effect of using the  views_handler_field as a parent
+    // class that is expecting something more for SQL. We don't use aliases
+    // for fields so the following if statement will fix the problem.
+    if (!$alias) {
+      $alias = $this->field_alias;
+    }
     if (isset($values->{$alias})) {
       return $values->{$alias};
     }

+ 1 - 1
tripal/views_handlers/tripal_views_handler_field_entity.inc

@@ -12,7 +12,7 @@
  *
  * @ingroup views_field_handlers
  */
-class tripal_views_handler_field_entity extends views_handler_field {
+class tripal_views_handler_field_entity extends tripal_views_handler_field {
 
   function init(&$view, &$options) {
     parent::init($view, $options);

+ 17 - 0
tripal/views_handlers/tripal_views_handler_filter.inc

@@ -0,0 +1,17 @@
+<?php
+
+class tripal_views_handler_filter extends views_handler_filter {
+
+  /**
+   * Add this filter to the query.
+   *
+   * Due to the nature of fapi, the value and the operator have an unintended
+   * level of indirection. You will find them in $this->operator
+   * and $this->value respectively.
+   */
+  function query() {
+    $this->ensure_my_table();
+    $this->query->add_where($this->options['group'], $this->real_field, $this->value, $this->operator);
+  }
+
+}

+ 1 - 1
tripal/views_handlers/tripal_views_handler_filter_select_string.inc

@@ -323,7 +323,7 @@ class tripal_views_handler_filter_string_selectbox extends views_handler_filter_
     }
 
     $this->ensure_my_table();
-    $field = $this->table_alias . "." . $this->real_field;
+    $field = $this->real_field;
     $table = $this->query->get_table_info($this->table);
 
     $this->options['values_form_type'] = (isset($this->options['values_form_type'])) ? $this->options['values_form_type'] : 'textfield';

+ 326 - 0
tripal/views_handlers/tripal_views_handler_filter_string.inc

@@ -0,0 +1,326 @@
+<?php
+class tripal_views_handler_filter_string extends tripal_views_handler_filter {
+  // exposed filter options
+  var $always_multiple = TRUE;
+
+  function option_definition() {
+    $options = parent::option_definition();
+
+    $options['expose']['contains']['required'] = array('default' => FALSE, 'bool' => TRUE);
+
+    return $options;
+  }
+
+  /**
+   * This kind of construct makes it relatively easy for a child class
+   * to add or remove functionality by overriding this function and
+   * adding/removing items from this array.
+   */
+  function operators() {
+    $operators = array(
+      '=' => array(
+        'title' => t('Is equal to'),
+        'short' => t('='),
+        'method' => 'op_equal',
+        'values' => 1,
+      ),
+      '!=' => array(
+        'title' => t('Is not equal to'),
+        'short' => t('!='),
+        'method' => 'op_equal',
+        'values' => 1,
+      ),
+      'contains' => array(
+        'title' => t('Contains'),
+        'short' => t('contains'),
+        'method' => 'op_contains',
+        'values' => 1,
+      ),
+      'word' => array(
+        'title' => t('Contains any word'),
+        'short' => t('has word'),
+        'method' => 'op_word',
+        'values' => 1,
+      ),
+      'allwords' => array(
+        'title' => t('Contains all words'),
+        'short' => t('has all'),
+        'method' => 'op_word',
+        'values' => 1,
+      ),
+      'starts' => array(
+        'title' => t('Starts with'),
+        'short' => t('begins'),
+        'method' => 'op_starts',
+        'values' => 1,
+      ),
+      'not_starts' => array(
+        'title' => t('Does not start with'),
+        'short' => t('not_begins'),
+        'method' => 'op_not_starts',
+        'values' => 1,
+      ),
+      'ends' => array(
+        'title' => t('Ends with'),
+        'short' => t('ends'),
+        'method' => 'op_ends',
+        'values' => 1,
+      ),
+      'not_ends' => array(
+        'title' => t('Does not end with'),
+        'short' => t('not_ends'),
+        'method' => 'op_not_ends',
+        'values' => 1,
+      ),
+      'not' => array(
+        'title' => t('Does not contain'),
+        'short' => t('!has'),
+        'method' => 'op_not',
+        'values' => 1,
+      ),
+      'shorterthan' => array(
+        'title' => t('Length is shorter than'),
+        'short' => t('shorter than'),
+        'method' => 'op_shorter',
+        'values' => 1,
+      ),
+      'longerthan' => array(
+        'title' => t('Length is longer than'),
+        'short' => t('longer than'),
+        'method' => 'op_longer',
+        'values' => 1,
+      ),
+    );
+    // if the definition allows for the empty operator, add it.
+    if (!empty($this->definition['allow empty'])) {
+      $operators += array(
+        'empty' => array(
+          'title' => t('Is empty (NULL)'),
+          'method' => 'op_empty',
+          'short' => t('empty'),
+          'values' => 0,
+        ),
+        'not empty' => array(
+          'title' => t('Is not empty (NOT NULL)'),
+          'method' => 'op_empty',
+          'short' => t('not empty'),
+          'values' => 0,
+        ),
+      );
+    }
+    // Add regexp support for MySQL.
+    if (Database::getConnection()->databaseType() == 'mysql') {
+      $operators += array(
+        'regular_expression' => array(
+          'title' => t('Regular expression'),
+          'short' => t('regex'),
+          'method' => 'op_regex',
+          'values' => 1,
+        ),
+      );
+    }
+
+    return $operators;
+  }
+
+  /**
+   * Build strings from the operators() for 'select' options
+   */
+  function operator_options($which = 'title') {
+    $options = array();
+    foreach ($this->operators() as $id => $info) {
+      $options[$id] = $info[$which];
+    }
+
+    return $options;
+  }
+
+  function admin_summary() {
+    if ($this->is_a_group()) {
+      return t('grouped');
+    }
+    if (!empty($this->options['exposed'])) {
+      return t('exposed');
+    }
+
+    $options = $this->operator_options('short');
+    $output = '';
+    if (!empty($options[$this->operator])) {
+      $output = check_plain($options[$this->operator]);
+    }
+    if (in_array($this->operator, $this->operator_values(1))) {
+      $output .= ' ' . check_plain($this->value);
+    }
+    return $output;
+  }
+
+  function operator_values($values = 1) {
+    $options = array();
+    foreach ($this->operators() as $id => $info) {
+      if (isset($info['values']) && $info['values'] == $values) {
+        $options[] = $id;
+      }
+    }
+
+    return $options;
+  }
+
+  /**
+   * Provide a simple textfield for equality
+   */
+  function value_form(&$form, &$form_state) {
+    // We have to make some choices when creating this as an exposed
+    // filter form. For example, if the operator is locked and thus
+    // not rendered, we can't render dependencies; instead we only
+    // render the form items we need.
+    $which = 'all';
+    if (!empty($form['operator'])) {
+      $source = ($form['operator']['#type'] == 'radios') ? 'radio:options[operator]' : 'edit-options-operator';
+    }
+    if (!empty($form_state['exposed'])) {
+      $identifier = $this->options['expose']['identifier'];
+
+      if (empty($this->options['expose']['use_operator']) || empty($this->options['expose']['operator_id'])) {
+        // exposed and locked.
+        $which = in_array($this->operator, $this->operator_values(1)) ? 'value' : 'none';
+      }
+      else {
+        $source = 'edit-' . drupal_html_id($this->options['expose']['operator_id']);
+      }
+    }
+
+    if ($which == 'all' || $which == 'value') {
+      $form['value'] = array(
+        '#type' => 'textfield',
+        '#title' => t('Value'),
+        '#size' => 30,
+        '#default_value' => $this->value,
+      );
+      if (!empty($form_state['exposed']) && !isset($form_state['input'][$identifier])) {
+        $form_state['input'][$identifier] = $this->value;
+      }
+
+      if ($which == 'all') {
+        $form['value'] += array(
+          '#dependency' => array($source => $this->operator_values(1)),
+        );
+      }
+    }
+
+    if (!isset($form['value'])) {
+      // Ensure there is something in the 'value'.
+      $form['value'] = array(
+        '#type' => 'value',
+        '#value' => NULL
+      );
+    }
+  }
+
+  function operator() {
+    return $this->operator == '=' ? 'LIKE' : 'NOT LIKE';
+  }
+
+  /**
+   * Add this filter to the query.
+   *
+   * Due to the nature of fapi, the value and the operator have an unintended
+   * level of indirection. You will find them in $this->operator
+   * and $this->value respectively.
+   */
+  function query() {
+    $this->ensure_my_table();
+    $field = $this->real_field;
+
+    $info = $this->operators();
+    if (!empty($info[$this->operator]['method'])) {
+      $this->{$info[$this->operator]['method']}($field);
+    }
+  }
+
+  function op_equal($field) {
+    $this->query->add_where($this->options['group'], $field, $this->value, $this->operator());
+  }
+
+  function op_contains($field) {
+    $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value) . '%', 'LIKE');
+  }
+
+  function op_word($field) {
+    $where = $this->operator == 'word' ? db_or() : db_and();
+
+    // Don't filter on empty strings.
+    if (empty($this->value)) {
+      return;
+    }
+
+    preg_match_all('/ (-?)("[^"]+"|[^" ]+)/i', ' ' . $this->value, $matches, PREG_SET_ORDER);
+    foreach ($matches as $match) {
+      $phrase = false;
+      // Strip off phrase quotes
+      if ($match[2]{0} == '"') {
+        $match[2] = substr($match[2], 1, -1);
+        $phrase = true;
+      }
+      $words = trim($match[2], ',?!();:-');
+      $words = $phrase ? array($words) : preg_split('/ /', $words, -1, PREG_SPLIT_NO_EMPTY);
+      foreach ($words as $word) {
+        $placeholder = $this->placeholder();
+        $where->condition($field, '%' . db_like(trim($word, " ,!?")) . '%', 'LIKE');
+      }
+    }
+
+    if (!$where) {
+      return;
+    }
+
+    // previously this was a call_user_func_array but that's unnecessary
+    // as views will unpack an array that is a single arg.
+    $this->query->add_where($this->options['group'], $where);
+  }
+
+  function op_starts($field) {
+    $this->query->add_where($this->options['group'], $field, db_like($this->value) . '%', 'LIKE');
+  }
+
+  function op_not_starts($field) {
+    $this->query->add_where($this->options['group'], $field, db_like($this->value) . '%', 'NOT LIKE');
+  }
+
+  function op_ends($field) {
+    $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value), 'LIKE');
+  }
+
+  function op_not_ends($field) {
+    $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value), 'NOT LIKE');
+  }
+
+  function op_not($field) {
+    $this->query->add_where($this->options['group'], $field, '%' . db_like($this->value) . '%', 'NOT LIKE');
+  }
+
+  function op_shorter($field) {
+    $placeholder = $this->placeholder();
+    $this->query->add_where_expression($this->options['group'], "LENGTH($field) < $placeholder", array($placeholder => $this->value));
+  }
+
+  function op_longer($field) {
+    $placeholder = $this->placeholder();
+    $this->query->add_where_expression($this->options['group'], "LENGTH($field) > $placeholder", array($placeholder => $this->value));
+  }
+
+  function op_regex($field) {
+    $this->query->add_where($this->options['group'], $field, $this->value, 'RLIKE');
+  }
+
+  function op_empty($field) {
+    if ($this->operator == 'empty') {
+      $operator = "IS NULL";
+    }
+    else {
+      $operator = "IS NOT NULL";
+    }
+
+    $this->query->add_where($this->options['group'], $field, NULL, $operator);
+  }
+
+}

+ 5 - 23
tripal_chado/includes/TripalFields/ChadoField.inc

@@ -48,27 +48,15 @@ class ChadoField extends TripalField {
   public static $module = 'tripal_chado';
 
   /**
-   * Used to filter records that match a given condition.
+   * @see TripalField::query()
+   *
+   * In addition to the rules to follow for the TripalField::query function
+   * these should also be followed for the ChadoField::query implementation.
    *
-   * Entities can be filtered using the fields.  This function should be
-   * implemented if the field  supports filtering.  To provide filtering,
-   * the $query object should be updated to including any joins and
-   * conditions necessary. The following rules should be followed when
-   * implementing this function:
-   * - Try to implement a filter for every element of the 'value' array
-   *   returned by the load() function.
-   * - However, avoid making filteres for non-indexed database columns.
    * - When giving alias to joined tables be sure to use aliases that are
    *   unique to avoid conflicts with other fields.
    * - When joining with the base table its alias is 'base'.
-   * - This function should never set the fields that should be returned
-   *   nor ordering or group by.
    * - You may join to materialized views if need be to help speed queries.
-   *
-   * @param $query
-   *   A SelectQuery object.
-   * @param $condition
-   *   The field specific condition as set in the TripalFieldQuery object.
    */
   public function query($query, $condition) {
     // If we are here it is because the child class did not implement the
@@ -94,13 +82,7 @@ class ChadoField extends TripalField {
   }
 
   /**
-   * Used to sort records that have been filtered.
-   *
-   * @param $query
-   *   A SelectQuery object.
-   * @param $order
-   *   The field ordering as set in the TripalFieldQuery object.  This function
-   *   should handle the ordering request as specified by this object.
+   * @see TripalField::queryOrder()
    */
   public function queryOrder($query, $order) {
 

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

@@ -415,7 +415,7 @@ function tripal_chado_field_storage_write_merge_fields($fields, $entity_type, $e
  * Implements hook_field_storage_query().
  */
 function tripal_chado_field_storage_query($query) {
-
+dpm($query);
   // Initialize the result array.
   $result = array(
     'TripalEntity' => array()

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

@@ -1680,7 +1680,7 @@ function tripal_chado_bundle_create_instances_linker(&$info, $entity_type, $bund
  *
  * A priviledged user has the ability to add new fields to the bundle. The
  * chado_linker__prop and chado_linker__cvterm fields are allowed to be
- * added dynamically by the user.  But, Drupal doesn't know whot to deal with
+ * added dynamically by the user.  But, Drupal doesn't know how to deal with
  * it, so this function is called for any field attached to a TripalEntity
  * bundle type. Any fields whose TripalField::$module argument is set to
  * 'tripal_chado' and that can be added dynamically will result in a call