function tripal_cv_add_cvterm

2.x tripal_cv.DEPRECATED.inc tripal_cv_add_cvterm($term, $defaultcv = '_global', $is_relationship = 0, $update = 1, $dbname = 'internal')
3.x tripal_cv.DEPRECATED.inc tripal_cv_add_cvterm($term, $defaultcv = '_global', $is_relationship = 0, $update = 1, $dbname = 'internal')
1.x tripal_cv.api.inc tripal_cv_add_cvterm($term, $defaultcv = '_global', $is_relationship = 0, $update = 1, $dbname = 'internal')

Add's a CV term to the cvterm table. If the parent CV does not exist then that too is added to the CV table. If the cvterm is a relationship term then the $is_relationship argument should be set. The function will try to first find the relationship in the relationship ontology for updating and if it can't be found will add the relationship to the __global CV. All terms must also have a corresponding database. This is specified in the term's ID just before the colon (e.g. GO:003824). If the database does not exist in the DB table then it will be added automatically. The accession (the value just after the colon in the term's ID) will be added to the dbxref table. If the CVterm already exists and $update is set (default) then the cvterm is updated. If the CVTerm already exists and $update is not set, then no changes are made and the CVTerm object is returned.

Parameters

$term: An associative array with the following keys: 'id', 'name' and 'namespace', 'is_obsolete', and 'def'. Where 'id' is the term accession, 'name' is the term name, 'namespace' is the CV name for the term, 'def' is the term definition and 'is_obsolete' is present and set to 1 if the term is defunct. The 'id' must be of the form <DB>:<ACCESSION>, where <DB> is the name of the database to which the cvterm belongs and the <ACCESSION> is the term's accession number in the database.

$defaultcv: Optional. The CV name to which the term belongs. If this arugment is null or not provided then the function tries to find a record in the CV table with the same name provided in the $term[namespace]. If this field is provided then it overrides what the value in $term[namespace]

$is_relationship: If this term is a relationship term then this value should be 1.

$update: By default this is set to 1. If the term exists it is automatically updated.

$dbname: In some cases the database name will not be part of the $term['id'] and it needs to be explicitly set. Use this argument only if the database name cannot be specififed in the term ID (e.g. <DB>:<ACCESSION>).

Return value

A CVTerm object

Related topics

14 calls to tripal_cv_add_cvterm()
tripal_analysis_add_cvterms in tripal_analysis/tripal_analysis.install
tripal_analysis_update_6001 in tripal_analysis/tripal_analysis.install
Provide update script for adding new cvterms
tripal_analysis_update_6101 in tripal_analysis/tripal_analysis.install
Update for Drupal 6.x, Tripal 1.1, Analysis Module 1.1 This update adds a new analysis_property cv and 'Analysis Type' cvterm
tripal_cv_cvterm_form_submit in tripal_cv/includes/tripal_cv_admin.inc
Purpose: Adds terms to an existing controlled vocabulary
tripal_cv_obo_add_cvterm_prop in tripal_cv/includes/obo_loader.inc
Add property to CVterm

... See full list

File

tripal_cv/api/tripal_cv.api.inc, line 479
Controlled Vocabulary API

Code

function tripal_cv_add_cvterm($term, $defaultcv = '_global', $is_relationship = 0, 
$update = 1, $dbname = 'internal') {

  // get the term properties
  $id = $term['id'];
  $name = '';
  $cvname = '';
  $definition = '';
  $is_obsolete = 0;
  $accession = '';

  if (array_key_exists('name', $term)) {
    $name = $term['name'];
  }
  else {
    $name = $id;
  }

  if (array_key_exists('namespace', $term)) {
    $cvname = $term['namespace'];
  }
  else {
    $cvname = $defaultcv;
  }
  if (array_key_exists('def', $term)) {
    $definition = preg_replace('/^\"(.*)\"/', '\1', $term['def']);
  }
  else {
    $definition = '';
  }
  if (array_key_exists('is_obsolete', $term)) {
    $is_obsolete = $term['is_obsolete'];
    if (strcmp($is_obsolete, 'true') == 0) {
      $is_obsolete = 1;
    }
  }
  if (!$name and !$id) {
    watchdog('tripal_cv', "Cannot find cvterm without 'id' or 'name'", NULL, WATCHDOG_WARNING);
    return 0;
  }
  if (!$id) {
    $id = $name;
  }

  // get the accession and the database from the cvterm id
  if ($dbname) {
    $accession = $id;
  }

  if (preg_match('/^.+?:.*$/', $id)) {
    $accession = preg_replace('/^.+?:(.*)$/', '\1', $id);
    $dbname = preg_replace('/^(.+?):.*$/', '\1', $id);
  }

  // check that we have a database name, give a different message if it's a relationship
  if ($is_relationship and !$dbname) {
    watchdog('tripal_cv', "A database name is not provided for this relationship term: $id", NULL, WATCHDOG_WARNING);
    return 0;
  }
  if (!$is_relationship and !$dbname) {
    watchdog('tripal_cv', "A database identifier is missing from the term: $id", NULL, WATCHDOG_WARNING);
    return 0;
  }

  // make sure the CV name exists
  $cv = tripal_cv_add_cv($cvname, '');
  if (!$cv) {
    watchdog('tripal_cv', "Cannot find namespace '$cvname' when adding/updating $id", NULL, WATCHDOG_WARNING);
    return 0;
  }

  // this SQL statement will be used a lot to find a cvterm so just set it
  // here for easy reference below.  Because CV terms can change their names
  // but accessions don't change, the following SQL finds cvterms based on
  // their accession rather than the name
  if (!tripal_core_is_sql_prepared('sel_cvterm_by_accession')) {
    $pcvtermsql = "
      PREPARE sel_cvterm_by_accession(text, text) AS
      SELECT CVT.name, CVT.cvterm_id, CV.cv_id, CV.name as cvname, 
        DB.name as dbname, DB.db_id, DBX.accession 
      FROM {cvterm} CVT
        INNER JOIN {dbxref} DBX on CVT.dbxref_id = DBX.dbxref_id
        INNER JOIN {db} DB on DBX.db_id = DB.db_id
        INNER JOIN {cv} CV on CV.cv_id = CVT.cv_id
      WHERE DBX.accession = $1 and DB.name = $2";
    if (!tripal_core_chado_prepare('sel_cvterm_by_accession', $pcvtermsql, array('text', 'text'))) {
      watchdog('tripal_cv', "Cannot prepare statement 'sel_cvterm_by_accession'", NULL, WATCHDOG_WARNING);
      return 0;
    }
  }
  $cvtermsql = "EXECUTE sel_cvterm_by_accession('%s','%s')";

  // add the database. The function will just return the DB object if the
  // database already exists.
  $db = tripal_db_add_db($dbname);
  if (!$db) {
    watchdog('tripal_cv', "Cannot find database '$dbname' in Chado.", NULL, WATCHDOG_WARNING);
    return 0;
  }

  // the cvterm table has two unique dependencies. We need to check both.
  // first check the (name, cv_id, is_obsolete) constraint
  $values = array(
    'name' => $name,
    'is_obsolete' => $is_obsolete,
    'cv_id' => array(
      'name' => $cvname,
    ),
  );
  $options = array('statement_name' => 'sel_cvterm_c1');
  $result = tripal_core_chado_select('cvterm', array('*'), $values, $options);

  // if the constraint is met then let's check it to see if
  // the database name matches the one we have been provided
  if (count($result) == 1) {
    $cvterm = $result[0];

    // get the dbxref record
    $values = array('dbxref_id' => $cvterm->dbxref_id);
    $options = array('statement_name' => 'sel_dbxref_id');
    $result = tripal_core_chado_select('dbxref', array('*'), $values, $options);
    $dbxref = $result[0];

    // get the db
    $values = array('db_id' => $dbxref->db_id);
    $options = array('statement_name' => 'sel_db_id');
    $result = tripal_core_chado_select('db', array('*'), $values, $options);
    $db_check = $result[0];

    // the database name for this existing term does not match that of the 
    // one provided to this function.  The CV name matches otherwise we
    // wouldn't have made it this far. So, let's swap the database for
    // this term
    if ($db_check->name != $db->name) {

      // look to see if the correct dbxref record already exists for this database
      $values = array(
        'db_id' => $db->db_id,
        'accession' => $accession,
      );
      $options = array('statement_name' => 'sel_dbxref_idac');
      $result = tripal_core_chado_select('dbxref', array('*'), $values, $options);

      // if we already have a good dbxref then we want to update our cvterm 
      // to use this dbxref
      if (count($result) > 0) {
        $dbxref = $result[0];
        $match = array('cvterm_id' => $cvterm->cvterm_id);
        $values = array('dbxref_id' => $dbxref->dbxref_id);
        $options = array('statement_name' => 'upd_cvterm_db');
        $success = tripal_core_chado_update('cvterm', $match, $values, $options);
        if (!$success) {
          watchdog('tripal_cv', "Failed to correct the dbxref id for the cvterm " .
            "'$name' (id: $accession), for database $dbname", NULL, WATCHDOG_WARNING);
          return 0;
        }
      }
      // if we don't have the record then we want to delete our cvterm and let the code
      // below recreate it with the correct info 
      else {
        $match = array('cvterm_id' => $cvterm->cvterm_id);
        $options = array('statement_name' => 'del_cvterm_cv');
        tripal_core_chado_delete('cvterm', $match, $options);
      }
    }

    // check that the accession matches.  Sometimes an OBO can define the same term 
    // multiple times but with different accessions.  If this is the case we
    // can't do an insert or it will violate the constraint in the cvterm table.
    // so we'll need to add the record to the cvterm_dbxref table instead
    if ($dbxref->accession != $accession) {

      // get/add the dbxref fort his term
      $dbxref_new = tripal_db_add_dbxref($db->db_id, $accession);
      if (!$dbxref_new) {
        watchdog('tripal_cv', "Failed to find or insert the dbxref record for cvterm, " .
          "$name (id: $accession), for database $dbname", NULL, WATCHDOG_WARNING);
        return 0;
      }

      // check to see if the cvterm_dbxref record already exists
      $values = array(
        'cvterm_id' => $cvterm->cvterm_id,
        'dbxref_id' => $dbxref_new->dbxref_id,
        'is_for_definition' => 1,
      );
      $options = array('statement_name' => 'sel_cvtermdbxref_cvdbis');
      $result = tripal_core_chado_select('cvterm_dbxref', array('*'), $values, $options);

      // if the cvterm_dbxref record does not exists then add it 
      if (count($result) == 0) {
        $options = array(
          'statement_name' => 'ins_cvtermdbxref_cvdbis',
          'return_record' => FALSE,
        );
        $success = tripal_core_chado_insert('cvterm_dbxref', $values, $options);
        if (!$success) {
          watchdog('tripal_cv', "Failed to find or insert the cvterm_dbxref record for a " .
            "duplicated cvterm:  $name (id: $accession), for database $dbname", NULL, WATCHDOG_WARNING);
          return 0;
        }
      }
      // get the original cvterm with the same name and return that.
      $cvterm = db_fetch_object(chado_query($cvtermsql, $dbxref->accession, $dbname));
      return $cvterm;
    }

    // continue on, we've fixed the record if the db_id did not match, 
    // we can now perform and updated if we need to.
  }

  // get the CVterm record
  $cvterm = db_fetch_object(chado_query($cvtermsql, $accession, $dbname));
  //print "$pcvtermsql\n$cvtermsql\n$accession, $dbname\n";
  //print "CVTERM:\n";
  //print_r($cvterm);
  if (!$cvterm) {

    // check to see if the dbxref exists if not, add it
    $dbxref = tripal_db_add_dbxref($db->db_id, $accession);
    if (!$dbxref) {
      watchdog('tripal_cv', "Failed to find or insert the dbxref record for cvterm, " .
        "$name (id: $accession), for database $dbname", NULL, WATCHDOG_WARNING);
      return 0;
    }

    // check to see if the dbxref already has an entry in the cvterm table
    // this is the second constraint in the cvterm table
    $values = array('dbxref_id' => $dbxref->dbxref_id);
    $options = array('statement_name' => 'sel_cvterm_db');
    $check = tripal_core_chado_select('cvterm', array('cvterm_id'), $values, $options);
    if (count($check) == 0) {
      // now add the cvterm
      $ins_values = array(
        'cv_id' => $cv->cv_id,
        'name' => $name,
        'definition' => $definition,
        'dbxref_id' => $dbxref->dbxref_id,
        'is_obsolete' => $is_obsolete,
        'is_relationshiptype' => $is_relationship,
      );
      $ins_options = array('statement_name' => 'ins_cvterm_all');
      $success = tripal_core_chado_insert('cvterm', $ins_values, $ins_options);
      if (!$success) {
        if (!$is_relationship) {
          watchdog('tripal_cv', "Failed to insert the term: $name ($dbname)", NULL, WATCHDOG_WARNING);
          return 0;
        }
        else {
          watchdog('tripal_cv', "Failed to insert the relationship term: $name (cv: " . $cvname . " db: $dbname)", NULL, WATCHDOG_WARNING);
          return 0;
        }
      }
    }
    // this dbxref already exists in the cvterm table 
    else {
      watchdog('tripal_cv', "The dbxref already exists for another cvterm record: $name (cv: " . $cvname . " db: $dbname)", NULL, WATCHDOG_WARNING);
      return 0;
    }
    $cvterm = db_fetch_object(chado_query($cvtermsql, $accession, $dbname));
  }
  // upate the cvterm
  elseif ($update) {
    $match = array('cvterm_id' => $cvterm->cvterm_id);
    $upd_values = array(
      'name' => $name,
      'definition' => $definition,
      'is_obsolete' => $is_obsolete,
      'is_relationshiptype' => $is_relationship,
    );
    $upd_options = array('statement_name' => 'upd_cvterm_nadeisis');
    $success = tripal_core_chado_update('cvterm', $match, $upd_values, $upd_options);
    if (!$success) {
      watchdog('tripal_cv', "Failed to update the term: $name", NULL, WATCHDOG_WARNING);
      return 0;
    }
    $cvterm = db_fetch_object(chado_query($cvtermsql, $accession, $dbname));
  }
  else {
    // do nothing, we have the cvterm but we don't want to update
  }
  // return the cvterm
  return $cvterm;
}