function chado_node_sync_records

2.x tripal_core.chado_nodes.api.inc chado_node_sync_records($base_table, $max_sync = FALSE, $organism_id = FALSE, $types = array(), $ids = array(), $linking_table = FALSE, $node_type = FALSE, $job_id = NULL)

Generic function for syncing records in Chado with Drupal nodes.

Parameters

$base_table: The name of the Chado table containing the record that should be synced

$max_sync: Optional: A numeric value to indicate the maximum number of records to sync.

$organism_id: Optional: Limit the list of records to be synced to only those that are associated with this organism_id. If the record is not assocaited with an organism then this field is not needed.

$types: Optional: Limit the list of records to be synced to only those that match the types listed in this array.

$ids: Optional: Limit the list of records to bye synced to only those whose primary key value matches the ID provided in this array.

$linking_table: Optional: Tripal maintains "linking" tables in the Drupal schema to link Drupal nodes with Chado records. By default these tables are named as 'chado_' . $base_table. But if for some reason the linking table is not named in this way then it can be provided by this argument.

$node_type: Optional: Tripal maintains "linking" tables in the Drupal schema to link Drupal nodes with Chado records. By default, Tripal expects that the node_type and linking table are named the same. However, if this is not the case, you can provide the node type name here.

$job_id: Optional. Used by the Trpial Jobs system when running this function as a job. It is not needed othewise.

Related topics

8 calls to chado_node_sync_records()
drush_tripal_phylogeny_trp_insert_phylotree in tripal_phylogeny/tripal_phylogeny.drush.inc
Deletes a phylotree record.
drush_tripal_phylogeny_trp_update_phylotree in tripal_phylogeny/tripal_phylogeny.drush.inc
tripal_core_chado_node_sync_records in tripal_core/api/tripal_core.DEPRECATED.api.inc
tripal_execute_active_pub_importers in tripal_pub/includes/tripal_pub.pub_importers.inc
Imports all publications for all active import setups.
tripal_execute_pub_importer in tripal_pub/includes/tripal_pub.pub_importers.inc
Imports all publications for a given publication import setup.

... See full list

3 string references to 'chado_node_sync_records'
chado_node_sync_form_submit in tripal_core/api/tripal_core.chado_nodes.api.inc
Generic Sync Form Submit
hook_chado_node_sync_form_submit in tripal_core/api/tripal_core.chado_nodes.api.inc
Bypass chado node api sync form submit.
tripal_core_chado_node_sync_records in tripal_core/api/tripal_core.DEPRECATED.api.inc

File

tripal_core/api/tripal_core.chado_nodes.api.inc, line 787
API to handle much of the common functionality implemented when creating a drupal node type.

Code

function chado_node_sync_records($base_table, $max_sync = FALSE, 
$organism_id = FALSE, $types = array(), $ids = array(), 
$linking_table = FALSE, $node_type = FALSE, $job_id = NULL) {

  global $user;
  $base_table_id = $base_table . '_id';

  if (!$linking_table) {
    $linking_table = 'chado_' . $base_table;
  }
  if (!$node_type) {
    $node_type = 'chado_' . $base_table;
  }

  print "\nSync'ing $base_table records.  ";

  // START BUILDING QUERY TO GET ALL RECORD FROM BASE TABLE THAT MATCH
  $select = array("$base_table.*");
  $joins = array();
  $where_clauses = array();
  $where_args = array();

  // If types are supplied then handle them
  $restrictions = '';
  if (count($types) > 0) {
    $restrictions .= "  Type(s): " . implode(', ', $types) . "\n";

    $select[] = 'cvterm.name as cvtname';
    $joins[] = "LEFT JOIN {cvterm} cvterm ON $base_table.type_id = cvterm.cvterm_id";
    foreach ($types as $type) {
      $sanitized_type = str_replace(' ', '_', $type);
      $where_clauses['type'][] = "cvterm.name = :type_name_$sanitized_type";
      $where_args['type'][":type_name_$sanitized_type"] = $type;
    }
  }

  // if IDs have been supplied
  if ($ids) {
    $restrictions .= "  Specific Records: " . count($ids) . " recored(s) specified.\n";
    foreach ($ids as $id) {
      $where_clauses['id'][] = "$base_table.$base_table_id = :id_$id";
      $where_args['id'][":id_$id"] = $id;
    }
  }

  // If Organism is supplied
  if ($organism_id) {
    $organism = chado_select_record('organism', array('*'), array('organism_id' => $organism_id));
    $restrictions .= "  Organism: " . $organism[0]->genus . " " . $organism[0]->species . "\n";

    $select[] = 'organism.*';
    $joins[] = "LEFT JOIN {organism} organism ON organism.organism_id = $base_table.organism_id";
    $where_clauses['organism'][] = 'organism.organism_id = :organism_id';
    $where_args['organism'][':organism_id'] = $organism_id;
  }

  // Allow module to add to query
  $hook_query_alter = $node_type . '_chado_node_sync_select_query';
  if (function_exists($hook_query_alter)) {
    $update = call_user_func($hook_query_alter, array(
      'select' => $select,
      'joins' => $joins,
      'where_clauses' => $where_clauses,
      'where_args' => $where_args,
    ));
    // Now add in any new changes
    if ($update and is_array($update)) {
      $select = $update['select'];
      $joins = $update['joins'];
      $where_clauses = $update['where_clauses'];
      $where_args = $update['where_args'];
    }
  }
  // Build Query, we do a left join on the chado_xxxx table in the Drupal schema
  // so that if no criteria are specified we only get those items that have not
  // yet been synced.
  // @todo: re-write to support external chado databases.
  $query = "
    SELECT " . implode(', ', $select) . ' ' .
    'FROM {' . $base_table . '} ' . $base_table . ' ' . implode(' ', $joins) . ' ' .
    "  LEFT JOIN [$linking_table] CT ON CT.$base_table_id = $base_table.$base_table_id " .
    "WHERE CT.$base_table_id IS NULL ";

  // extend the where clause if needed
  $where = '';
  $sql_args = array();
  foreach ($where_clauses as $category => $items) {
    $where .= ' AND (';
    foreach ($items as $item) {
      $where .= $item . ' OR ';
    }
    $where = substr($where, 0, -4); // remove the trailing 'OR'
    $where .= ') ';
    $sql_args = array_merge($sql_args, $where_args[$category]);
  }

  if ($where) {
    $query .= $where;
  }
  $query . - " ORDER BY " . $base_table_id;

  // If Maximum number to Sync is supplied
  if ($max_sync) {
    $query .= " LIMIT $max_sync";
    $restrictions .= "  Limited to $max_sync records.\n";
  }

  if ($restrictions) {
    print "Records matching these criteria will be synced: \n$restrictions";
  }
  else {
    print "\n";
  }

  // execute the query
  $results = chado_query($query, $sql_args);

  // Iterate through records that need to be synced
  $count = $results->rowCount();
  $interval = intval($count * 0.01);
  if ($interval < 1) {
    $interval = 1;
  }

  print "\n$count $base_table records found.\n";

  $i = 0;
  //$transaction = db_transaction();
  print "\nNOTE: Syncing is performed using a database transaction. \n" .
    "If the sync fails or is terminated prematurely then the entire set of \n" .
    "synced items is rolled back and will not be found in the database\n\n";
  try {
    $percent = 0;
    foreach ($results as $record) {
      // Update the job status every 1% features.
      if ($job_id and $i % $interval == 0) {
        $percent = sprintf("%.2f", (($i + 1) / $count) * 100);
        print "Syncing $base_table " . ($i + 1) . " of $count (" . $percent . "%). Memory: " . number_format(memory_get_usage()) . " bytes.\r";
        tripal_set_job_progress($job_id, intval(($i / $count) * 100));
      }

      // Check if the record is already in the chado linking table
      // (ie: check to see if it is already linked to a node).
      $result = db_select($linking_table, 'lnk')
        ->fields('lnk', array('nid'))
        ->condition($base_table_id, $record->{$base_table_id}, '=')
        ->execute()
        ->fetchObject();

      if (empty($result)) {
        // Create generic new node.
        $new_node = new stdClass();
        $new_node->type = $node_type;
        $new_node->uid = $user->uid;
        $new_node->{$base_table_id} = $record->{$base_table_id};
        $new_node->$base_table = $record;
        $new_node->language = LANGUAGE_NONE;

        // TODO: should we get rid of this hook and use hook_node_presave() instead?
        // allow base module to set additional fields as needed
        $hook_create_new_node = $node_type . '_chado_node_sync_create_new_node';
        if (function_exists($hook_create_new_node)) {
          $new_node = call_user_func($hook_create_new_node, $new_node, $record);
        }

        // Validate and Save New Node
        $form = array();
        $form_state = array();
        node_validate($new_node, $form, $form_state);

        if (!form_get_errors()) {
          $node = node_submit($new_node);
          // If there are memory leaks on the node_save it is probably
          // caused by the hook_node_insert() function.
          node_save($node);
        }
        else {
          throw new Exception(t("Failed to insert $base_table: %title", array('%title' => $new_node->title)));
        }
      }
      $i++;
    }
    print "\n\nComplete!\n";
  }

  catch (Exception $e) {
    $transaction->rollback();
    print "\n"; // make sure we start errors on new line
    watchdog_exception('trp-fsync', $e);
    print "FAILED: Rolling back database changes...\n";
  }
}