function tripal_core_generate_chado_var

2.x tripal_core.DEPRECATED.api.inc tripal_core_generate_chado_var($table, $values, $base_options = array())
3.x tripal_core.DEPRECATED.inc tripal_core_generate_chado_var($table, $values, $base_options = array())
1.x tripal_core_chado.api.inc tripal_core_generate_chado_var($table, $values, $base_options = array())

Generates an object containing the full details of a record(s) in chado.

This differs from the objects returned by tripal_core_chado_select in so far as all foreign key relationships have been followed meaning you have more complete details. Thus this function should be used whenever you need a full variable and tripal_core_chado_select should be used if you only case about a few columns.

  $values = array(
    'name' => 'Medtr4g030710'
  );
  $features = tripal_core_generate_chado_var('feature', $values);

This will return an object if there is only one feature with the name Medtr4g030710 or it will return an array of feature objects if more than one feature has that name.

Note to Module Designers: Fields can be excluded by default from these objects by implementing one of the following hooks:

  • hook_exclude_field_from_tablename_by_default (where tablename is the name of the table): This hook allows you to add fields to be excluded on a per table basis. Simply implement this hook to return an array of fields to be excluded. For example:
  mymodule_exclude_field_from_feature_by_default() {
    return array('residues' => TRUE);
  }

will ensure that feature.residues is ecluded from a feature object by default.

  • hook_exclude_type_by_default: This hook allows you to exclude fields from all tables that are of a given postgresql field type. Simply implement this hook to return an array of postgresql types mapped to criteria. Then all fields of that type where the criteria supplied returns TRUE will be excluded from any table. Tokens available in criteria are >field_value< and >field_name< . For example:
  mymodule_exclude_type_by_default() {
    return array('text' => 'length(>field_value< ) > 50');
  }

will exclude all text fields with a length > 50. Thus if $feature.residues is longer than 50 * it will be excluded, otherwise it will be added.

Parameters

$table: The name of the base table to generate a variable for

$values: A select values array that selects the records you want from the base table (this has the same form as tripal_core_chado_select)

$base_options: An array containing options for the base table. For example, an option of 'order_by' may be used to sort results in the base table if more than one are returned. The options must be compatible with the options accepted by the tripal_core_chado_select() function. Additionally, These options are available for this function: -return_array: can be provided to force the function to always return an array. Default behavior is to return a single record if only one record exists or to return an array if multiple records exist.

  • include_fk: an array of FK relationships to follow. By default, the tripal_core_chado_select function will follow all FK relationships but this may generate more queries then is desired slowing down this function call when there are lots of FK relationships to follow. Provide an array specifying the fields to include. For example, if expanding a property table (e.g. featureprop) and you want the CV and accession but do not want the DB the following array would work:

$table_options = array( 'include_fk' => array( 'type_id' => array( 'cv_id' => 1, 'dbxref_id' => 1, ) ) );

The above array will expand the 'type_id' of the property table but only further expand the cv_id and the dbxref_id and will go no further.

  • pager: Use this option if it is desired to return only a subset of results so that they may be shown within a Drupal-style pager. This should be an array with two keys: 'limit' and 'element'. The value of 'limit' should specify the number of records to return and 'element' is a unique integer to differentiate between pagers when more than one appear on a page. The 'element' should start with zero and increment by one for each pager. This only works when type is a 'table'.

Return value

Either an object (if only one record was selected from the base table) or an array of objects (if more than one record was selected from the base table). If the option 'return_array' is provided the function always returns an array.

Example Usage:

Related topics

15 calls to tripal_core_generate_chado_var()
chado_analysis_load in tripal_analysis/tripal_analysis.module
When a node is requested by the user this function is called to allow us to add auxiliary data to the node object.
chado_contact_load in tripal_contact/tripal_contact.module
Implementation of tripal_contact_load().
chado_featuremap_load in tripal_featuremap/tripal_featuremap.module
When a node is requested by the user this function is called to allow us to add auxiliary data to the node object.
chado_feature_load in tripal_feature/tripal_feature.module
When a node is requested by the user this function is called to allow us to add auxiliary data to the node object.
chado_library_load in tripal_library/tripal_library.module
When a node is requested by the user this function is called to allow us to add auxiliary data to the node object.

... See full list

File

tripal_core/api/tripal_core_chado.api.inc, line 1766
The Tripal Core API

Code

function tripal_core_generate_chado_var($table, $values, $base_options = array()) {
  $all = new stdClass();

  $return_array = 0;
  if (array_key_exists('return_array', $base_options)) {
    $return_array = 1;
  }
  $include_fk = 0;
  if (array_key_exists('include_fk', $base_options)) {
    $include_fk = $base_options['include_fk'];
  }
  $pager = array();
  if (array_key_exists('pager', $base_options)) {
    $pager = $base_options['pager'];
  }
  // get description for the current table----------------------------------------------------------
  $table_desc = tripal_core_get_chado_table_schema($table);
  if (!$table_desc or count($table_desc) == 0) {
    watchdog('tripal_core', "tripal_core_generate_chado_var: The table '%table' has not been defined. " .
      "and cannot be expanded. If this is a custom table, please add it using the Tripal " .
      "custom table interface.", array('%table' => $table), WATCHDOG_ERROR);
    if ($return_array) {
      return array();
    }
    return FALSE;
  }
  $table_primary_key = $table_desc['primary key'][0];
  $table_columns = array_keys($table_desc['fields']);

  // Expandable fields without value needed for criteria--------------------------------------------
  $all->expandable_fields = array();
  if ($table_desc['referring_tables']) {
    $all->expandable_tables = $table_desc['referring_tables'];
  }
  else {
    $all->expandable_tables = array();
  }
  $all->expandable_nodes = array();

  // Get fields to be removed by name.................................
  $fields_to_remove = module_invoke_all('exclude_field_from_' . $table . '_by_default');
  foreach ($fields_to_remove as $field_name => $criteria) {
    //replace >field_name<  with the current field name &
    $criteria = preg_replace('/>field_name< /', addslashes($field_name), $criteria);
    // if field_value needed we can't deal with this field yet
    if (preg_match('/>field_value< /', $criteria)) {
      break;
    }

    //if criteria then remove from query
    // @coder-ignore: only module designers can populate $criteria -not security risk
    $success = drupal_eval('<?php return ' . $criteria . '; ?>');
    //    watchdog('tripal_core',
    //      'Evaluating criteria (%criteria) for field %field in tripal_core_generate_chado_var for %table evaluated to %success',
    //      array('%table' => $table, '%criteria'=>$criteria, '%field' => $field_name, '%success'=>$success),
    //      WATCHDOG_NOTICE
    //    );
    if ($success) {
      unset($table_columns[array_search($field_name, $table_columns)]);
      unset($fields_to_remove[$field_name]);
      $all->expandable_fields[] = $table . '.' . $field_name;
    }
  }

  //Get fields to be removed by type................................
  $types_to_remove = module_invoke_all('exclude_type_by_default');
  $field_types = array();
  foreach ($table_desc['fields'] as $field_name => $field_array) {
    $field_types[$field_array['type']][] = $field_name;
  }
  foreach ($types_to_remove as $field_type => $criteria) {
    // if there are fields of that type to remove
    if (is_array($field_types[$field_type])) {
      //replace &gt;field_name&lt;  with the current field name &
      $criteria = preg_replace('/&gt;field_name&lt; /', addslashes($field_name), $criteria);
      foreach ($field_types[$field_type] as $field_name) {
        // if field_value needed we can't deal with this field yet
        if (preg_match('/&gt;field_value&lt; /', $criteria)) {
          $fields_to_remove[$field_name] = $criteria;
          continue;
        }
        // if field_value needed we can't deal with this field yet
        if (preg_match('/&gt;field_value&lt; /', $criteria)) {
          break;
        }
        //if criteria then remove from query
        // @coder-ignore: only module designers can populate $criteria -not security risk
        $success = drupal_eval('<?php return ' . $criteria . '; ?>');
        //        watchdog('tripal_core',
        //          'Evaluating criteria (%criteria) for field %field of $type in tripal_core_generate_chado_var for %table evaluated to %success',
        //          array('%table'=>$table, '%criteria'=>$criteria, '%field'=>$field_name, '%type'=>$field_type, '%success'=>$success),
        //          WATCHDOG_NOTICE
        //        );
        if ($success) {
          unset($table_columns[array_search($field_name, $table_columns)]);
          $all->expandable_fields[] = $table . '.' . $field_name;
        }
      } //end of foreach field of that type
    }
  } //end of foreach type to be removed

  // get the values for the record in the current table---------------------------------------------
  $results = tripal_core_chado_select($table, $table_columns, $values, $base_options);
  if ($results) {
    foreach ($results as $key => $object) {
      // Add empty expandable_x arrays
      $object->expandable_fields = $all->expandable_fields;
      $object->expandable_tables = $all->expandable_tables;
      $object->expandable_nodes = $all->expandable_nodes;
      // add curent table
      $object->tablename = $table;

      // check if the current table maps to a node type-----------------------------------------------
      // if this table is connected to a node there will be a chado_tablename table in drupal
      if (db_table_exists('chado_' . $table)) {
        // that has a foreign key to this one ($table_desc['primary key'][0]
        // and to the node table (nid)
        $sql = "SELECT %s, nid FROM {chado_%s} WHERE %s=%d";
        $mapping = db_fetch_object(db_query($sql, $table_primary_key, $table, 
        $table_primary_key, $object->{$table_primary_key}));
        if ($mapping->{$table_primary_key}) {
          $object->nid = $mapping->nid;
          $object->expandable_nodes[] = $table;
        }
      }

      // remove any fields where criteria need to be evalulated---------------------------------------
      foreach ($fields_to_remove as $field_name => $criteria) {
        if (!isset($object->{$field_name})) {
          break;
        }
        $criteria = preg_replace('/&gt;field_value&lt; /', addslashes($object->{$field_name}), $criteria);
        //if criteria then remove from query
        // @coder-ignore: only module designers can populate $criteria -not security risk
        $success = drupal_eval('<?php return ' . $criteria . '; ?>');
        //      watchdog('tripal_core',
        //        'Evaluating criteria (%criteria) for field %field in tripal_core_generate_chado_var for   %table evaluated to %success',
        //        array('%table' => $table, '%criteria'=>$criteria, '%field' => $field_name, '%success'=>$success),
        //        WATCHDOG_NOTICE
        //      );
        if ($success) {
          unset($object->{$field_name});
          $object->expandable_fields[] = $table . '.' . $field_name;
        }
      }

      // recursively follow foreign key relationships nesting objects as we go------------------------
      if ($table_desc['foreign keys']) {
        foreach ($table_desc['foreign keys'] as $foreign_key_array) {
          $foreign_table = $foreign_key_array['table'];
          foreach ($foreign_key_array['columns'] as $foreign_key => $primary_key) {
            // Note: Foreign key is the field in the current table whereas primary_key is the field in
            // the table referenced by the foreign key
            //Dont do anything if the foreign key is empty
            if (empty($object->{$foreign_key})) {
              continue;
            }

            if ($include_fk) {
              // don't recurse if the callee has supplied an $fk_include list and this
              // FK table is not in the list.
              if (is_array($include_fk) and !array_key_exists($foreign_key, $include_fk)) {
                continue;
              }
              // if we have the option but it is not an array then we don't recurse any furutehr
              if (!is_array($include_fk)) {
                continue;
              }
            }
            // get the record from the foreign table
            $foreign_values = array($primary_key => $object->{$foreign_key});
            $options = array();
            if (is_array($include_fk)) {
              $options['include_fk'] = $include_fk[$foreign_key];
            }
            $foreign_object = tripal_core_generate_chado_var($foreign_table, $foreign_values, $options);
            // add the foreign record to the current object in a nested manner
            $object->{$foreign_key} = $foreign_object;
            // Flatten expandable_x arrays so only in the bottom object
            if (is_array($object->{$foreign_key}->expandable_fields)) {
              $object->expandable_fields = array_merge(
              $object->expandable_fields, 
              $object->{$foreign_key}->expandable_fields
              );
              unset($object->{$foreign_key}->expandable_fields);
            }
            if (is_array($object->{$foreign_key}->expandable_tables)) {
              $object->expandable_tables = array_merge(
              $object->expandable_tables, 
              $object->{$foreign_key}->expandable_tables
              );
              unset($object->{$foreign_key}->expandable_tables);
            }
            if (is_array($object->{$foreign_key}->expandable_nodes)) {
              $object->expandable_nodes = array_merge(
              $object->expandable_nodes, 
              $object->{$foreign_key}->expandable_nodes
              );
              unset($object->{$foreign_key}->expandable_nodes);
            }
          }
        }
        $results[$key] = $object;
      }
    }
  }

  // check only one result returned
  if (!$return_array) {
    if (sizeof($results) == 1) {
      // add results to object
      return $results[0];
    }
    elseif (!empty($results)) {
      return $results;
    }
    else {
      // no results returned
    }
  }
  // the caller has requested results are always returned as
  // an array
  else {
    if (!$results) {
      return array();
    }
    else {
      return $results;
    }
  }
}