| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768 | <?php/** * @file * Provides an application programming interface (API) to manage data withing the Chado database. */require_once 'tripal_core.schema_v1.2.api.inc';require_once 'tripal_core.schema_v1.11.api.inc';/** * @defgroup tripal_chado_api Chado API * @ingroup tripal_core_api * @{ * Provides an application programming interface (API) to manage data withing the Chado database. * * This includes functions for selecting, inserting, updating and deleting records * in Chado tables.  The functions will ensure proper integrity contraints are met * for inserts and updates. * * Also, a set of functions is provided for creating template variables.  First, * is the chado_generate_var which is used to select one ore more * records from a table and return an array with foreign key relationships fully * populated.  For example, if selecting a feature, the organism_id and type_id * would be present in the returned array as a nested array with their respective * foreign keys also nested.  The only fields that are not included are text * fields (which may be very large) or many-to-many foreign key relationships. * However, these fields and relationships can be expanded using the * chado_expand_var. * * When a row from a chado table is selected using these two functions, it provides * a way for users who want to cutomize Drupal template files to access all data * associate with a specific record. * * Finally, the property tables in Chado generally follow the same format.  Therefore * there is a set of functions for inserting, updating and deleting properties for * any table.  This provides quick lookup of properties (provided the CV term is * known). * * @} * *//** * Set the Tripal Database * * The chado_set_active function is used to prevent namespace collisions * when Chado and Drupal are installed in the same database but in different * schemas. It is also used when using Drupal functions such as * db_table_exists(). * * The connection settings can be altered through the hook * hook_chado_connection_alter. * * Current active connection name is stored in the global variable * $GLOBALS['chado_active_db']. * * @see hook_chado_connection_alter() * * @ingroup tripal_chado_api */function chado_set_active($dbname = 'default') {  // Check if the chado_active_db has been set yet.  if (!array_key_exists('chado_active_db', $GLOBALS)) {    $GLOBALS['chado_active_db'] = 'default';  }  $previous_db = $active_db = $GLOBALS['chado_active_db'];  $search_path = 'public';  // Change only if 'chado' has been specified.  if ($dbname == 'chado') {    $active_db = 'chado';    $search_path = 'chado,public';  }  $settings = array(    'dbname'          => $dbname,    'new_active_db'   => &$active_db,    'new_search_path' => &$search_path,  );  // Will call all modules implementing hook_chado_search_path_alter  // note: hooks can alter $active_db and $search_path.  drupal_alter('chado_connection', $settings);  // set chado_active_db to remember active db  $GLOBALS['chado_active_db'] = $active_db;  // set PostgreSQL search_path  db_query('SET search_path TO ' . $search_path);  return $previous_db;}/** * Alter Chado connection settings. * * This hook is useful for multi-chado instances. Tripal core functions * call the chado_set_active() function (e.g. chado_query) but there is no * opportunity elsewhere to set the active database.  This is useful in two * cases:  1) Users are managed at the database level as in the case of * SouthGreen Bioinformatics Platform tools (e.g. Banana Genone Hub). * This allows custom modules to change the database connections on a per-user * basis, and each user permissions is managed at the database level.  Users * are managed at the database level to provid the same access restrictions * across various tools that use Chado (e,g, Artemis) 2) When there are * simply two Chado instances housed in different Chado databases and the * module needs to control which one is being used at any given time. * * @param $settings *   An array containing * * @see chado_set_active() * * @ingroup tripal_chado_api */function hook_chado_connection_alter(&$settings) {  // This example shows how we could make sure no table of the 'public' schema  // would be allowed in the coming queries: to do so, the caller will call  // "chado_set_active('chado_only');" and the hook will remove 'public' from  // the search path.  if ('chado_only' == $settings['dbname']) {    $settings['new_active_db']   = 'chado';    // We don't include 'public' in search path.    $settings['new_search_path'] = 'chado';  }}/** * Get max rank for a given set of criteria * This function was developed with the many property tables in chado in mind but will * work for any table with a rank * * @params tablename: the name of the chado table you want to select the max rank from *    this table must contain a rank column of type integer * @params where_options: array( *                          <column_name> => array( *                            'type' => <type of column: INT/STRING>, *                            'value' => <the value you want to filter on>, *                            'exact' => <if TRUE use =; if FALSE use ~>, *                          ) *        ) *     where options should include the id and type for that table to correctly *     group a set of records together where the only difference are the value and rank * @return the maximum rank * * @ingroup tripal_chado_api */function chado_get_table_max_rank($tablename, $where_options) {  $where_clauses = array();  $where_args = array();  //generate the where clause from supplied options  // the key is the column name  $i = 0;  $sql = "    SELECT max(rank) as max_rank, count(rank) as count    FROM {".$tablename."}    WHERE  ";  foreach ($where_options as $key => $value) {    $where_clauses[] = "$key = :$key";    $where_args[":$key"] = $value;  }  $sql .= implode($where_clauses, ' AND ');  $result = chado_query($sql, $where_args)->fetchObject();  if ($result->count > 0) {    return $result->max_rank;  }  else {    return -1;  }}/** * Retrieve a property for a given base table record. * * @param $record *   An array used to identify the record to which the property is associated. *   The following keys must be used: *     -table: The base table for which the property should be updated. *         Thus to update a property for a feature the base_table=feature. *     -id: The primary key value of the base table. The property will be *         associated with the record that matches this id. *     -prop_id: The primary key in the [table]prop table.  If this value *         is supplied then the 'table' and 'id' keys are not needed. * @param $property *   An associative array used to specify the property to be selected.  It can *   contain the following keys. The keys must be specified to uniquely identify *   the term to be applied.  If the options identify more than one CV term *   then an error will occur. *     -type_name: The cvterm name to be selected. *     -type_id: The cvterm_id of the term to be selected. *     -cv_id: The cv_id of the CV that contains the term. *     -cv_name: The name of the CV that contains the term. *     -value: The specific value for the property. *     -rank: The specific rank for the property. * @return *   An array in the same format as that generated by the function *   chado_generate_var().  If only one record is returned it *   is a single object.  If more than one record is returned then it is an array *   of objects * * @ingroup tripal_chado_api */function chado_get_property($record, $property) {  $base_table  = array_key_exists('table', $record) ? $record['table'] : '';  $base_id     = array_key_exists('id', $record) ? $record['id'] : '';  $prop_id     = array_key_exists('prop_id', $record) ? $record['prop_id'] : '';  $type_name   = array_key_exists('type_name', $property) ? $property['type_name'] : '';  $type_id     = array_key_exists('type_id', $property) ? $property['type_id'] : '';  $cv_name     = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';  $cv_id       = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';  $value       = array_key_exists('value', $property) ? $property['value'] : '';  $rank        = array_key_exists('rank', $property) ? $property['rank'] : 0;  // Build the values array for checking if the CVterm exists and for  // retrieving the term as a property.  $type = array();  if ($cv_id) {    $type['cv_id'] = $cv_id;  }  if ($cv_name) {    $type['cv_id'] = array(      'name' => $cv_name,    );  }  if ($type_name) {    $type['name'] = $type_name;  }  if ($type_id) {    $type['cvterm_id'] = $type_id;  }  // Make sure the CV term exists;  $options = array();  $term = chado_select_record('cvterm', array('cvterm_id'), $type, $options);  if (!$term or count($term) == 0) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_get_property: " .        "Cannot find the term described by: %property.",        array('%property' => print_r($property, TRUE)));        return FALSE;  }  if (count($term) > 1) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_get_property: " .        "Multiple terms found. Cannot add the property. Property was described " .        "by: %property.",        array('%property' => print_r($property, TRUE)));    return FALSE;  }  // get the foreign key for this property table  $table_desc = chado_get_schema($base_table . 'prop');  $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);  // construct the array of values to be selected  $values = array(    $fkcol => $base_id,    'type_id' => $type,  );  // if we have the unique property_id make sure to add that to the values  if ($prop_id) {    $property_pkey = $table_desc['primary key'][0];    $values[$property_pkey] = $prop_id;  }  $results = chado_generate_var($base_table . 'prop', $values);  if ($results) {    $results = chado_expand_var($results, 'field', $base_table . 'prop.value');  }  return $results;}/** * Insert a property for a given base table. * * By default if the property already exists a new property is added with the * next available rank.  If the option 'update_if_present' is specified then * the record will be updated if it exists rather than adding a new property. * * @param $record *   An associative array used to identify the record to which the property *   should be assigned.  The following keys must be used: *     -table: The base table for which the property should be inserted. *         Thus to insert a property for a feature the base_table=feature and *         property is inserted into featureprop *     -id: The primary key value of the base table. The property will be *         associated with the record that matches this id. * @param $property *   An associative array used to specify the property to be added.  It can *   contain the following keys. The keys must be specified to uniquely identify *   the term to be applied.  If the options identify more than one CV term *   then an error will occur. *     -type_name: The cvterm name to be selected. *     -type_id: The cvterm_id of the term to be selected. *     -cv_id: The cv_id of the CV that contains the term. *     -cv_name: The name of the CV that contains the term. *     -value: The specific value for the property. *     -rank: The specific rank for the property. * @param $options *   An associative array containing the following keys: *     -update_if_present:  A boolean indicating whether an existing record *        should be updated. If the property already exists and this value is *        not specified or is zero then a new property will be added with the *        next largest rank. *     -force_rank:  If the specified rank is already used by another property *        recrod for the same base_id, then set force_rank to TRUE to require *        that only the specified rank can be used. Otherwise, the next *        available rank will be used.  If 'update_if_present' is FALSE and *        'force_rank' is set then an error will occur. * * @return *   Return TRUE if successful and FALSE otherwise * * @ingroup tripal_chado_api */function chado_insert_property($record, $property, $options = array()) {  $base_table  = array_key_exists('table', $record) ? $record['table'] : '';  $base_id     = array_key_exists('id', $record) ? $record['id'] : '';  $type_name   = array_key_exists('type_name', $property) ? $property['type_name'] : '';  $type_id     = array_key_exists('type_id', $property) ? $property['type_id'] : '';  $cv_name     = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';  $cv_id       = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';  $value       = array_key_exists('value', $property) ? $property['value'] : '';  $rank        = array_key_exists('rank', $property) ? $property['rank'] : 0;  $update_if_present = array_key_exists('update_if_present', $options) ? $options['update_if_present'] : FALSE;  $force_rank = array_key_exists('force_rank', $options) ? $options['force_rank'] : FALSE;  // First see if the property is already assigned to the record. I  $props = chado_get_property($record, $property);  if (!is_array($props)) {    if ($props) {      $props = array($props);    }    else {      $props = array();    }  }  if (count($props) > 0) {    // The property is already assigned, so, see if we should update it.    if ($update_if_present) {      return chado_update_property($record, $property);    }    else {      if (!$force_rank) {        // iterate through the properties returned and check to see if the        // property with this value already exists if not, get the largest rank        // and insert the same property but with this new value        foreach ($props as $prop) {          if ($prop->rank > $rank) {            $rank = $prop->rank;          }          if (strcmp($prop->value, $value) == 0) {            return TRUE;          }        }        // now add 1 to the rank        $rank++;      }      else {        tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_insert_property: " .         "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)));        return FALSE;      }    }  }  // Build the values array for checking if the CVterm exists and for  // inserting the term as a property.  $values = array();  if ($cv_id) {    $values['cv_id'] = $cv_id;  }  if ($cv_name) {    $values['cv_id'] = array(      'name' => $cv_name,    );  }  if ($type_name) {    $values['name'] = $type_name;  }  if ($type_id) {    $values['cvterm_id'] = $type_id;  }  // Make sure the CV term exists;  $options = array();  $term = chado_select_record('cvterm', array('cvterm_id'), $values, $options);  if (!$term or count($term) == 0) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_insert_property: " .      "Cannot find the term described by: %property.",      array('%property' => print_r($property, TRUE)));    return FALSE;  }  if (count($term) > 1) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_insert_property: " .      "Multiple terms found. Cannot add the property. Property was described " .      "by: %property.",      array('%property' => print_r($property, TRUE)));    return FALSE;  }  // Get the foreign key for this property table  $table_desc = chado_get_schema($base_table . 'prop');  $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);  // Add the property to the record.  $values = array(    $fkcol => $base_id,    'type_id' => $values,    'value' => $value,    'rank' => $rank,  );  $result = chado_insert_record($base_table . 'prop', $values);  return $result;}/** * Update a property for a given base table record and property name. * * @param $record *   An associative array used to identify the record to which the property *   should be updated.  The following keys must be used: *     -table: The base table for which the property should be updated. *         Thus to update a property for a feature the base_table=feature. *     -id: The primary key value of the base table. The property will be *         associated with the record that matches this id. *     -prop_id: The primary key in the [table]prop table.  If this value *         is supplied then the 'table' and 'id' keys are not needed. * @param $property *   An associative array used to specify the property to be updated.  It can *   contain the following keys. The keys must be specified to uniquely identify *   the term to be applied.  If the options identify more than one CV term *   then an error will occur. *     -type_name: The cvterm name to be selected. *     -type_id: The cvterm_id of the term to be selected. *     -cv_id: The cv_id of the CV that contains the term. *     -cv_name: The name of the CV that contains the term. *     -value: The specific value for the property. *     -rank: The specific rank for the property. * @param $options *   An associative array containing the following keys: *     -insert_if_missing: A boolean indicating whether a record should be *         inserted if one doesn't exist to update. * * * @return *   Return TRUE on Update/Insert and FALSE otherwise * * @ingroup tripal_chado_api */function chado_update_property($record, $property, $options = array()) {  $base_table  = array_key_exists('table', $record) ? $record['table'] : '';  $base_id     = array_key_exists('id', $record) ? $record['id'] : '';  $prop_id     = array_key_exists('prop_id', $record) ? $record['prop_id'] : '';  $type_name   = array_key_exists('type_name', $property) ? $property['type_name'] : '';  $type_id     = array_key_exists('type_id', $property) ? $property['type_id'] : '';  $cv_name     = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';  $cv_id       = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';  $value       = array_key_exists('value', $property) ? $property['value'] : '';  $rank        = array_key_exists('rank', $property) ? $property['rank'] : 0;  $insert_if_missing = array_key_exists('insert_if_missing', $options) ? $options['insert_if_missing'] : FALSE;  // first see if the property is missing (we can't update a missing property  $prop = chado_get_property($record, $property);  if (count($prop) == 0) {    if ($insert_if_missing) {      return chado_insert_property($record, $property);    }    else {      return FALSE;    }  }  // Build the values array for checking if the CVterm exists.  $type = array();  if ($cv_id) {    $type['cv_id'] = $cv_id;  }  if ($cv_name) {    $type['cv_id'] = array(      'name' => $cv_name,    );  }  if ($type_name) {    $type['name'] = $type_name;  }  if ($type_id) {    $type['cvterm_id'] = $type_id;  }  // Make sure the CV term exists;  $options = array();  $term = chado_select_record('cvterm', array('cvterm_id'), $type, $options);  if (!$term or count($term) == 0) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .        "Cannot find the term described by: %property.",        array('%property' => print_r($property, TRUE)));    return FALSE;  }  if (count($term) > 1) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .        "Multiple terms found. Cannot add the property. Property was described " .        "by: %property.",        array('%property' => print_r($property, TRUE)));    return FALSE;  }  // Get the foreign key for this property table  $table_desc = chado_get_schema($base_table . 'prop');  $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);  // construct the array that will match the exact record to update  $match = array(    $fkcol => $base_id,    'type_id' => $type,  );  // If we have the unique property_id, make sure to use it in the match to  // ensure we get the exact record. Doesn't rely on there only being one  // property of that type.  if ($prop_id) {    $property_pkey = $table_desc['primary key'][0];    $match = array(      $property_pkey => $prop_id,    );  }  // Construct the array of values to be updated.  $values = array();  $values['value'] = $value;  if ($rank) {    $values['rank'] = $rank;  }  // If we have the unique property_id then we can also update the type  // thus add it to the values to be updated  if ($prop_id) {    $values['type_id'] = $type;  }  return chado_update_record($base_table . 'prop', $match, $values);}/** * Deletes a property for a given base table record using the property name * * @param $record *   An associative array used to identify the record to which the property *   should be deleted.  The following keys must be used: *     -table: The base table for which the property should be deleted. *         Thus to update a property for a feature the base_table=feature. *     -id: The primary key value of the base table. The property will be *         deleted from the record that matches this id. *     -prop_id: The primary key in the [table]prop table to be deleted.  If *         this value is supplied then the 'table' and 'id' keys are not needed. * @param $property *   An associative array used to specify the property to be updated.  It can *   contain the following keys. The keys must be specified to uniquely identify *   the term to be applied.  If the options identify more than one CV term *   then an error will occur. *     -type_name: The cvterm name to be selected. *     -type_id: The cvterm_id of the term to be selected. *     -cv_id: The cv_id of the CV that contains the term. *     -cv_name: The name of the CV that contains the term. *     -value: The specific value for the property. *     -rank: The specific rank for the property. * * @return *   Return TRUE on successful deletion and FALSE otherwise * * @ingroup tripal_chado_api */function chado_delete_property($record, $property) {  $base_table  = array_key_exists('table', $record) ? $record['table'] : '';  $base_id     = array_key_exists('id', $record) ? $record['id'] : '';  $prop_id     = array_key_exists('prop_id', $record) ? $record['prop_id'] : '';  $type_name   = array_key_exists('type_name', $property) ? $property['type_name'] : '';  $type_id     = array_key_exists('type_id', $property) ? $property['type_id'] : '';  $cv_name     = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';  $cv_id       = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';  $value       = array_key_exists('value', $property) ? $property['value'] : '';  $rank        = array_key_exists('rank', $property) ? $property['rank'] : 0;  // Build the values array for checking if the CVterm exists  $type = array();  if ($cv_id) {    $type['cv_id'] = $cv_id;  }  if ($cv_name) {    $type['cv_id'] = array(      'name' => $cv_name,    );  }  if ($type_name) {    $type['name'] = $type_name;  }  if ($type_id) {    $type['cvterm_id'] = $type_id;  }  // Make sure the CV term exists;  $options = array();  $term = chado_select_record('cvterm', array('cvterm_id'), $type, $options);  if (!$term or count($term) == 0) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_delete_property: " .        "Cannot find the term described by: %property.",        array('%property' => print_r($property, TRUE)));        return FALSE;  }  if (count($term) > 1) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_delete_property: " .        "Multiple terms found. Cannot add the property. Property was described " .        "by: %property.",        array('%property' => print_r($property, TRUE)));    return FALSE;  }  // get the foreign key for this property table  $table_desc = chado_get_schema($base_table . 'prop');  $fkcol = key($table_desc['foreign keys'][$base_table]['columns']);  // If we have the unique property_id, make sure to use it in the match to ensure  // we get the exact record. Doesn't rely on there only being one property of that type  if ($prop_id) {    $property_pkey = $table_desc['primary key'][0];    $match = array(      $property_pkey => $prop_id    );  }  // construct the array that will match the exact record to update  else {    $match = array(      $fkcol => $record_id,      'type_id' => $type,    );  }  return chado_delete_record($base_table . 'prop', $match);}/** * Get all records in the base table assigned one or more properties. * * The property or properties of interest are specified using the $property * argument. * * @param $record *   An associative array used to identify the table and subset of records to *   to be searched: *     -table: The base table for which the property should be updated. *         Thus to update a property for a feature the base_table=feature. *     -base_records: An array in the format accepted by the chado_select_record *         for specifying a subset of records in the base table. * @param $property *   An associative array used to specify the property to be selected for. It *   can contain the following keys. The keys must be specified to uniquely *   identify the term to be searched.  If the options identify more than one *   CV term then an error will occur. *     -type_name: The cvterm name to be selected. *     -type_id: The cvterm_id of the term to be selected. *     -cv_id: The cv_id of the CV that contains the term. *     -cv_name: The name of the CV that contains the term. *     -value: The specific value for the property. *     -rank: The specific rank for the property. * @param $options *   An array of options supported by chado_generate_var(). These keys *   are used for generating the cvterm objects returned by this function. * * @return *   An array of chado variables with the given property * * @ingroup tripal_chado_api */function chado_get_record_with_property($record, $property, $options = array()) {  $base_table  = array_key_exists('table', $record) ? $record['table'] : '';  $base_records= array_key_exists('base_records', $record) ? $record['base_records'] : array();  $type_name   = array_key_exists('type_name', $property) ? $property['type_name'] : '';  $type_id     = array_key_exists('type_id', $property) ? $property['type_id'] : '';  $cv_name     = array_key_exists('cv_name', $property) ? $property['cv_name'] : '';  $cv_id       = array_key_exists('cv_id', $property) ? $property['cv_id'] : '';  $value       = array_key_exists('value', $property) ? $property['value'] : '';  $rank        = array_key_exists('rank', $property) ? $property['rank'] : '';  $property_table = $base_table . 'prop';  $foreignkey_name = $base_table . '_id';  // Build the values array for checking if the CVterm exists and for  // inserting the term as a property.  $type = array();  if ($cv_id) {    $type['cv_id'] = $cv_id;  }  if ($cv_name) {    $type['cv_id'] = array(      'name' => $cv_name,    );  }  if ($type_name) {    $type['name'] = $type_name;  }  if ($type_id) {    $type['cvterm_id'] = $type_id;  }  // Make sure the CV term exists;  $term = chado_select_record('cvterm', array('cvterm_id'), $type);  if (!$term or count($term) == 0) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .        "Cannot find the term described by: %property.",        array('%property' => print_r($property, TRUE)));        return FALSE;  }  if (count($term) > 1) {    tripal_report_error('tripal_core', TRIPAL_ERROR, "chado_update_property: " .        "Multiple terms found. Cannot add the property. Property was described " .        "by: %property.",        array('%property' => print_r($property, TRUE)));    return FALSE;  }  // Build the array for identifying the property.  $values = array();  $values['type_id'] = $type;  if ($rank) {    $values['rank'] = $rank;  }  if ($value) {    $values['value'] = $value;  }  // Add the base records details to the values array.  if (!empty($base_records)) {    $values[$foreignkey_name] = $base_records;  }  // Now select the ids of the base table that have the properties we want that match.  $select = chado_select_record($property_table, array($foreignkey_name), $values);  // For each of these ids, pull out the full base records  $records = array();  foreach ($select as $s) {    $id = $s->{$foreignkey_name};    $values = array($foreignkey_name => $id);    $records[$id] = chado_generate_var($base_table, $values, $options);  }  return $records;}
 |