t('Publication'),
'base' => 'chado_pub',
'description' => t('A publication from the Chado database'),
'has_title' => TRUE,
'locked' => TRUE,
'chado_node_api' => array(
'base_table' => 'pub',
'hook_prefix' => 'chado_pub',
'record_type_title' => array(
'singular' => t('Publication'),
'plural' => t('Publications')
),
'sync_filters' => array(
'type_id' => FALSE,
'organism_id' => FALSE,
),
),
);
return $nodes;
}
/**
* Implements hook_form().
*
* @ingroup tripal_legacy_pub
*/
function chado_pub_form($node, $form_state) {
$form = array();
// Check to make sure that the tripal_pub vocabulary is loaded. If not, then
// warn the user that they should load it before continuing.
$pub_cv = chado_select_record('cv', array('cv_id'), array('name' => 'tripal_pub'));
if (count($pub_cv) == 0) {
drupal_set_message(t('The Tripal Pub vocabulary is currently not loaded. ' .
'This vocabulary is required to be loaded before adding ' .
'publications.
Please !import',
array('!import' => l('load the Tripal Publication vocabulary', 'admin/tripal/loaders/chado_vocabs/obo_loader'))), 'warning');
}
// Default values can come in the following ways:
//
// 1) as elements of the $node object. This occurs when editing an existing pub
// 2) in the $form_state['values'] array which occurs on a failed validation or
// ajax callbacks from non submit form elements
// 3) in the $form_state['input'] array which occurs on ajax callbacks from submit
// form elements and the form is being rebuilt
//
// set form field defaults
$pub_id = null;
$title = '';
$pyear = '';
$uniquename = '';
$type_id = '';
$is_obsolete = '';
// some of the fields in the pub table should show up in the properties
// form elements to make the form more seemless. We will add them
// to this array.
$more_props = array();
// if we are editing an existing node then the pub is already part of the node
if (property_exists($node, 'pub')) {
$pub = $node->pub;
$pub = chado_expand_var($pub, 'field', 'pub.title');
$pub = chado_expand_var($pub, 'field', 'pub.volumetitle');
$pub = chado_expand_var($pub, 'field', 'pub.uniquename');
$pub_id = $pub->pub_id;
$title = $pub->title;
$pyear = $pub->pyear;
$uniquename = $pub->uniquename;
$type_id = $pub->type_id->cvterm_id;
$is_obsolete = $pub->is_obsolete;
// if the obsolete value is set by the database then it is in the form of
// 't' or 'f', we need to convert to 1 or 0
$is_obsolete = $is_obsolete == 't' ? 1 : $is_obsolete;
$is_obsolete = $is_obsolete == 'f' ? 0 : $is_obsolete;
// set the organism_id in the form
$form['pub_id'] = array(
'#type' => 'value',
'#value' => $pub->pub_id,
);
// get fields from the pub table and convert them to properties. We will add these to the $more_props
// array which gets passed in to the tripal_core_properties_form() API call further down
if ($pub->volumetitle) {
$cvterm = tripal_get_cvterm(array(
'name' => 'Volume Title',
'cv_id' => array('name' => 'tripal_pub')
));
$more_props[] = array('cvterm' => $cvterm, 'value' => $pub->volumetitle);
}
if ($pub->volume) {
$cvterm = tripal_get_cvterm(array(
'name' => 'Volume',
'cv_id' => array('name' => 'tripal_pub')
));
$more_props[] = array('cvterm' => $cvterm, 'value' => $pub->volume);
}
if ($pub->series_name) {
switch ($pub->type_id->name) {
case 'Journal Article':
$cvterm = tripal_get_cvterm(array(
'name' => 'Journal Name',
'cv_id' => array('name' => 'tripal_pub')
));
$more_props[] = array('cvterm' => $cvterm, 'value' => $pub->series_name);
break;
case 'Conference Proceedings':
$cvterm = tripal_get_cvterm(array(
'name' => 'Conference Name',
'cv_id' => array('name' => 'tripal_pub')
));
$more_props[] = array('cvterm' => $cvterm, 'value' => $pub->series_name);
break;
default:
$cvterm = tripal_get_cvterm(array(
'name' => 'Series Name',
'cv_id' => array('tripal_pub')
));
$more_props[] = array('cvterm' => $cvterm, 'value' => $pub->series_name);
}
}
if ($pub->issue) {
$cvterm = tripal_get_cvterm(array(
'name' => 'Issue',
'cv_id' => array('name' => 'tripal_pub')
));
$more_props[] = array('cvterm' => $cvterm, 'value' => $pub->issue);
}
if ($pub->pages) {
$cvterm = tripal_get_cvterm(array(
'name' => 'Pages',
'cv_id' => array('name' => 'tripal_pub')
));
$more_props[] = array('cvterm' => $cvterm, 'value' => $pub->pages);
}
if ($pub->miniref) {
// not sure what to do with this one
}
if ($pub->publisher) {
$cvterm = tripal_get_cvterm(array(
'name' => 'Publisher',
'cv_id' => array('name' => 'tripal_pub')
));
$more_props[] = array('cvterm' => $cvterm, 'value' => $pub->publisher);
}
if ($pub->pubplace) {
$cvterm = tripal_get_cvterm(array(
'name' => 'Published Location',
'cv_id' => array('name' => 'tripal_pub')
));
$more_props[] = array('cvterm' => $cvterm, 'value' => $pub->pages);
}
}
// if we are re constructing the form from a failed validation or ajax callback
// then use the $form_state['values'] values
if (array_key_exists('values', $form_state) and isset($form_state['values']['pubtitle'])) {
$title = $form_state['values']['pubtitle'];
$pyear = $form_state['values']['pyear'];
$uniquename = $form_state['values']['uniquename'];
$type_id = $form_state['values']['type_id'];
$is_obsolete = $form_state['values']['is_obsolete'];
}
// if we are re building the form from after submission (from ajax call) then
// the values are in the $form_state['input'] array
if (array_key_exists('input', $form_state) and !empty($form_state['input'])) {
$title = $form_state['input']['pubtitle'];
$uniquename = $form_state['input']['uniquename'];
$type_id = $form_state['input']['type_id'];
$is_obsolete = array_key_exists('is_obsolete', $form_state['input']) ? $form_state['input']['is_obsolete'] : '';
}
$form['pubtitle'] = array(
'#type' => 'textarea',
'#title' => t('Publication Title'),
'#default_value' => $title,
'#required' => TRUE,
);
$type_cv = tripal_get_default_cv('pub', 'type_id');
if ($type_cv and $type_cv->name == 'tripal_pub') {
// get the list of publication types. In the Tripal publication
// ontologies these are all grouped under the term 'Publication Type'
// we want the default to be 'Journal Article'
$sql = "
SELECT
CVTS.cvterm_id, CVTS.name
FROM {cvtermpath} CVTP
INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id
INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id
INNER JOIN {cv} ON CVTO.cv_id = CV.cv_id
WHERE
CV.name = 'tripal_pub' AND CVTO.name = 'Publication Type' AND
NOT CVTS.is_obsolete = 1
ORDER BY CVTS.name ASC
";
$results = chado_query($sql);
$pub_types = array();
while ($pub_type = $results->fetchObject()) {
$pub_types[$pub_type->cvterm_id] = $pub_type->name;
// if we don't have a default type then set the default to be 'Journal Article'
if (strcmp($pub_type->name,"Journal Article") == 0 and !$type_id) {
$type_id = $pub_type->cvterm_id;
}
}
}
else {
$pub_types = tripal_get_cvterm_default_select_options('pub', 'type_id', 'publication types');
$pub_types[0] = 'Select a Type';
}
$form['type_id'] = array(
'#type' => 'select',
'#title' => t('Publication Type'),
'#options' => $pub_types,
'#required' => TRUE,
'#default_value' => $type_id,
);
$form['pyear'] = array(
'#type' => 'textfield',
'#title' => t('Publication Year'),
'#default_value' => $pyear,
'#required' => TRUE,
'#size' => 5,
'#description' => t('Enter the year of publication. Also, if available, please add a Publication Date property to specify the full date of publication.'),
);
$form['uniquename'] = array(
'#type' => 'textarea',
'#title' => t('Citation'),
'#default_value' => $uniquename,
'#description' => t('All publications must have a unique citation.
Please enter the full citation for this publication or leave blank and one will be generated
automatically if possible. For PubMed style citations list
the last name of the author followed by initials. Each author should be separated by a comma. Next comes
the title, followed by the series title (e.g. journal name), publication date (4 digit year, 3 character Month, day), volume, issue and page numbers. You may also use HTML to provide a link in the citation.
Below is an example:
Medeiros PM, Ladio AH, Santos AM, Albuquerque UP. Does the selection of medicinal plants by Brazilian local populations suffer taxonomic influence? J Ethnopharmacol. 2013 Apr 19; 146(3):842-52.'), ); $form['is_obsolete'] = array( '#type' => 'checkbox', '#title' => t('Is Obsolete? (Check for Yes)'), '#default_value' => $is_obsolete, ); // Properties Form // ---------------------------------- $select_options = array(); $prop_cv = tripal_get_default_cv('pubprop', 'type_id'); $cv_id = $prop_cv ? $prop_cv->cv_id : NULL; // if the poperty cv is 'tripal_pub' then we need to pass in our own select_options // for only a subset of the vocabulary if ($prop_cv and $prop_cv->name == 'tripal_pub') { $select_options[] = 'Select a Property'; $sql = " SELECT DISTINCT CVTS.cvterm_id, CVTS.name, CVTS.definition FROM {cvtermpath} CVTP INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id INNER JOIN {cv} ON CVTO.cv_id = CV.cv_id WHERE CV.name = 'tripal_pub' and (CVTO.name = 'Publication Details' OR CVTS.name = 'Publication Type') AND NOT CVTS.is_obsolete = 1 ORDER BY CVTS.name ASC "; $prop_types = chado_query($sql); while ($prop = $prop_types->fetchObject()) { // add all properties except the Citation. That property is set via the uniquename field if ($prop->name == 'Citation') { continue; } // Publication Dbxref's are handled by the dbxref form addition below if ($prop->name == 'Publication Dbxref') { continue; } $select_options[$prop->cvterm_id] = $prop->name; } } $details = array( 'property_table' => 'pubprop', 'chado_id' => $pub_id, 'cv_id' => $cv_id, 'select_options' => $select_options, 'default_properties' => $more_props, ); chado_add_node_form_properties($form, $form_state, $details); // RELATIONSHIPS FORM //--------------------------------------------- $relationship_cv = tripal_get_default_cv('pub_relationship', 'type_id'); $cv_id = $relationship_cv ? $relationship_cv->cv_id : NULL; $details = array( 'relationship_table' => 'pub_relationship', // the name of the _relationship table 'base_table' => 'pub', // the name of your chado base table 'base_foreign_key' => 'pub_id', // the name of the key in your base chado table 'base_key_value' => $pub_id, // the value of pub_id for this record 'nodetype' => 'pub', // the human-readable name of your node type 'cv_id' => $cv_id, // the cv.cv_id of the cv containing the relationships 'base_name_field' => 'uniquename', // the base table field you want to be used as the name ); // Adds the form elements to your current form chado_add_node_form_relationships($form, $form_state, $details); // ADDITIONAL DBXREFS FORM //--------------------------------------------- $details = array( 'linking_table' => 'pub_dbxref', // the name of the _dbxref table 'base_foreign_key' => 'pub_id', // the name of the key in your base chado table 'base_key_value' => $pub_id // the value of pub_id for this record ); // Adds the form elements to your current form chado_add_node_form_dbxrefs($form, $form_state, $details); return $form; } /** * Implements hook_validate(). * * @ingroup tripal_legacy_pub */ function chado_pub_validate($node, $form, &$form_state) { // We only want to validate when the node is saved. // Since this validate can be called on AJAX and Deletion of the node // we need to make this check to ensure queries are not executed // without the proper values. if(property_exists($node, "op") and $node->op != 'Save') { return; } // we are syncing if we do not have a node ID but we do have a pub_id. We don't // need to validate during syncing so just skip it. if (!property_exists($node, 'nid') and property_exists($node, 'pub_id') and $node->pub_id != 0) { return; } // get the submitted values $title = property_exists($node, 'pubtitle') ? trim($node->pubtitle) : ''; $pyear = property_exists($node, 'pyear') ? trim($node->pyear) : ''; $uniquename = property_exists($node, 'uniquename') ? trim($node->uniquename) : ''; $is_obsolete = property_exists($node, 'is_obsolete') ? trim($node->is_obsolete) : 0; $type_id = property_exists($node, 'type_id') ? trim($node->type_id) : ''; $pub = array(); // make sure the year is four digits if(!preg_match('/^\d{4}$/', $pyear)){ form_set_error('pyear', t('The publication year should be a 4 digit year.')); return; } // get the type of publication $values = array('cvterm_id' => $type_id); $cvterm = chado_select_record('cvterm', array('name'), $values); if (count($cvterm) == 0) { $message = t('Invalid publication type.'); form_set_error('type_id', $message); return; } // Get the media name looking at the properties $series_name = ''; $properties = chado_retrieve_node_form_properties($node); foreach ($properties as $key => $prop_values) { $values = array('cvterm_id' => $key); $prop_type = chado_select_record('cvterm', array('name'), $values); if ($prop_type[0]->name == 'Conference Name' or $prop_type[0]->name == 'Journal Name' or $prop_type[0]->name == 'Series Name') { $v = array_values($prop_values); $series_name = $v[0]; } if ($prop_type[0]->name == 'Citation') { $v = array_values($prop_values); $uniquename = $v[0]; } if (count($prop_values) == 1) { $v = array_values($prop_values); $pub[$prop_type[0]->name] = $v[0]; } else { $pub[$prop_type[0]->name] = $prop_values; } } // if the citation is missing then try to generate one if (!$uniquename) { $pub['Title'] = $title; $pub['Publication Type'][0] = $cvterm[0]->name; $pub['Year'] = $pyear; $uniquename = tripal_pub_create_citation($pub); if (!$uniquename) { form_set_error('uniquename', "Cannot automatically generate a citation for this publication type. Please add one manually."); } } $skip_duplicate_check = 0; // if this publication is a Patent then skip the validation below. Patents can have the title // name and year but be different if (strcmp($cvterm[0]->name,'Patent') == 0) { $skip_duplicate_check = 1; } // Validating for an update if (!is_null($node->nid)) { $pub_id = $node->pub_id; // check to see if a duplicate publication already exists if (!$skip_duplicate_check) { chado_pub_validate_check_duplicate($title, $pyear, $series_name, $cvterm[0], $pub_id); } chado_pub_validate_check_uniquename($uniquename, $pub_id); } // Validating for an insert else { chado_pub_validate_check_duplicate($title, $pyear, $series_name, $cvterm[0]); chado_pub_validate_check_uniquename($uniquename); } } /** * Validate the publication uniquename. To be called from hook_validate(). * * @param $uniquename * The uniquename of the publication * @param $pub_id * If an update, provide the pub_id so we don't check for a matching * uniquename of the pub we are editing * * @ingroup tripal_legacy_pub */ function chado_pub_validate_check_uniquename($uniquename, $pub_id = NULL) { // check to see if a pub exists with this uniquename $pub = tripal_get_publication(array('uniquename' => $uniquename)); if ($pub) { // if a $pub_id is provided to the function then this is an update // if the pub_id's don't match then a different pub with the same // uniquename already exists. if ($pub->pub_id != $pub_id) { $message = t('A publication with this unique citation already exists.'); form_set_error('uniquename', $message); } } } /** * Check for duplicate publications. To be called from hook_validate(). Sets * the form error if a duplicate * * @param $title * The title of the publication * @param $pyear * The year the publication was published * @param $series_name * The series name of the publication * @param $cvterm * The type of publication * @param $pub_id * the unique id of the publication * * * @ingroup tripal_legacy_pub */ function chado_pub_validate_check_duplicate($title, $pyear, $series_name, $cvterm, $pub_id = NULL) { $pub_details = array( 'Title' => $title, 'Year' => $pyear, 'Series Name' => $series_name, 'Publication Type' => $cvterm->name, ); // TODO: need to include the Publication Dbxref in the $pub_details as well $pub_ids = tripal_publication_exists($pub_details); // if we found only one publication and it is our publication then return, we're good. if (count($pub_ids) == 1 and in_array($pub_id, $pub_ids)) { return; } if (count($pub_ids) == 0) { // there is no match so return return; } // return an appropriate message based on the unique constraint settings $import_dups_check = variable_get('tripal_pub_import_duplicate_check', 'title_year_media'); switch ($import_dups_check) { case 'title_year': $message = t('A publication with this title and publication year already exists.'); form_set_error('pubtitle', $message); break; case 'title_year_type': $message = t('A publication with this title, type and publication year already exists.'); form_set_error('pubtitle', $message); break; case 'title_year_media': $message = t('A publication with this title, media name (e.g. Journal Name) and publication year already exists.'); form_set_error('pubtitle', $message); break; } } /** * Implement hook_node_access(). * * This hook allows node modules to limit access to the node types they define. * * @param $node * The node on which the operation is to be performed, or, if it does not yet exist, the * type of node to be created * * @param $op * The operation to be performed * * @param $account * A user object representing the user for whom the operation is to be performed * * @return * If the permission for the specified operation is not set then return FALSE. If the * permission is set then return NULL as this allows other modules to disable * access. The only exception is when the $op == 'create'. We will always * return TRUE if the permission is set. * * @ingroup tripal_legacy_pub */ function tripal_pub_node_access($node, $op, $account) { $node_type = $node; if (is_object($node)) { $node_type = $node->type; } if($node_type == 'chado_pub') { if ($op == 'create') { if (!user_access('create chado_pub content', $account)) { return NODE_ACCESS_DENY; } return NODE_ACCESS_ALLOW; } if ($op == 'update') { if (!user_access('edit chado_pub content', $account)) { return NODE_ACCESS_DENY; } } if ($op == 'delete') { if (!user_access('delete chado_pub content', $account)) { return NODE_ACCESS_DENY; } } if ($op == 'view') { if (!user_access('access chado_pub content', $account)) { return NODE_ACCESS_DENY; } } return NODE_ACCESS_IGNORE; } } /** * Implements hook_insert(). * * @ingroup tripal_legacy_pub */ function chado_pub_insert($node) { $pub_id = ''; // if there is an pub_id in the $node object then this must be a sync so // we can skip adding the pub as it is already there, although // we do need to proceed with insertion into the chado/drupal linking table. if (!property_exists($node, 'pub_id')) { $node->pubtitle = trim($node->pubtitle); $node->pyear = trim($node->pyear); $node->uniquename = trim($node->uniquename); $is_obsolete = $node->is_obsolete; $type_id = $node->type_id; // we need an array suitable for the tripal_pub_create_citation() function // to automatically generate a citation if a uniquename doesn't already exist $pub_arr = array(); // Stores all of the properties we need to add. $properties = array(); // Stores any cross references for this publication. $cross_refs = array(); // get the properties from the form $properties = chado_retrieve_node_form_properties($node); // get the list of properties for easy lookup (without doing lots of database queries $properties_list = array(); $sql = " SELECT CVTS.cvterm_id, CVTS.name, CVTS.definition FROM {cvtermpath} CVTP INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id INNER JOIN {cv} ON CVTO.cv_id = CV.cv_id WHERE CV.name = 'tripal_pub' and CVTO.name = 'Publication Details' and NOT CVTS.is_obsolete = 1 ORDER BY CVTS.name ASC "; $prop_types = chado_query($sql); while ($prop = $prop_types->fetchObject()) { $properties_list[$prop->cvterm_id] = $prop->name; // The 'Citation' term is special because it serves // both as a property and as the uniquename for the // pub and we want it stored in both the pub table and the pubprop table if ($prop->name == 'Citation') { $citation_id = $prop->cvterm_id; if (!empty($node->uniquename)) { $properties[$citation_id][0] = $node->uniquename; } } } // iterate through all of the properties and remove those that really are // part of the pub table fields $volume = ''; $volumetitle = ''; $issue = ''; $pages = ''; $publisher = ''; $series_name = ''; $pubplace = ''; $miniref = ''; $cross_refs = array(); foreach ($properties as $type_id => $element) { foreach ($element as $index => $value) { $name = $properties_list[$type_id]; // populate our $pub_array for building a citation $pub_arr[$name] = $value; // remove properties that are stored in the pub table if ($name == "Volume") { $volume = $value; unset($properties[$type_id]); } elseif ($name == "Volume Title") { $volumetitle = $value; unset($properties[$type_id]); } elseif ($name == "Issue") { $issue = $value; unset($properties[$type_id]); } elseif ($name == "Pages") { $pages = $value; unset($properties[$type_id]); } elseif ($name == "Publisher") { $publisher = $value; unset($properties[$type_id]); } elseif ($name == "Series Name" or $name == "Journal Name" or $name == "Conference Name") { $series_name = $value; unset($properties[$type_id]); } elseif ($name == "Journal Country" or $name == "Published Location") { $pubplace = $value; // allow this property to go into the pubprop table so we don't loose info // so don't unset it. But it will also go into the pub.pubplace field } elseif ($name == "Publication Dbxref") { // we will add the cross-references to the pub_dbxref table // but we also want to keep the property in the pubprop table so don't unset it $cross_refs[] = $value; } } } // generate a citation for this pub if one doesn't already exist if (!$node->uniquename and !array_key_exists($citation_id, $properties)) { $pub_type = tripal_get_cvterm(array('cvterm_id' => $node->type_id)); $pub_arr['Title'] = $node->pubtitle; $pub_arr['Publication Type'][0] = $pub_type->name; $pub_arr['Year'] = $node->pyear; $node->uniquename = tripal_pub_create_citation($pub_arr); $properties[$citation_id][0] = $node->uniquename; } // insert the pub record $values = array( 'title' => $node->pubtitle, 'series_name' => substr($series_name, 0, 255), 'type_id' => $node->type_id, 'pyear' => $node->pyear, 'is_obsolete' => $node->is_obsolete ? 'true' : 'false', 'uniquename' => $node->uniquename, 'volumetitle' => $volumetitle, 'volume' => $volume, 'issue' => $issue, 'pages' => $pages, 'miniref' => substr($miniref, 0, 255), 'publisher' => substr($publisher, 0, 255), 'pubplace' => substr($pubplace, 0, 255), ); $pub = chado_insert_record('pub', $values); if (!$pub) { drupal_set_message("Error inserting publication", "error"); watchdog('tripal_pub', "Error inserting publication", array(), WATCHDOG_ERROR); return; } $pub_id = $pub['pub_id']; // now add in the properties // Only adds in those not used in the pub record $details = array( 'property_table' => 'pubprop', 'base_table' => 'pub', 'foreignkey_name' => 'pub_id', 'foreignkey_value' => $pub_id ); chado_update_node_form_properties($node, $details, $properties); // * Relationships Form * $details = array( 'relationship_table' => 'pub_relationship', // name of the _relationship table 'foreignkey_value' => $pub_id // value of the pub_id key ); chado_update_node_form_relationships($node, $details); // add in any database cross-references foreach ($cross_refs as $index => $ref) { $dbxref = array(); if(preg_match('/^(.*?):(.*?)$/', trim($ref), $matches)) { $dbxref['db_name'] = $matches[1]; $dbxref['accession'] = $matches[2]; } $success = chado_associate_dbxref('pub', $pub['pub_id'], $dbxref); if (!$success) { drupal_set_message("Error cannot add publication cross reference: $ref", "error"); watchdog('tripal_pub', "Error cannot add publication cross reference: %ref", array('%ref' => $ref), WATCHDOG_ERROR); } } // * Additional DBxrefs Form * $details = array( 'linking_table' => 'pub_dbxref', // the name of your _dbxref table 'foreignkey_name' => 'pub_id', // the name of the key in your base table 'foreignkey_value' => $pub_id // the value of the pub_id key ); chado_update_node_form_dbxrefs($node, $details); } else { $pub_id = $node->pub_id; } // Make sure the entry for this pub doesn't already exist in the // chado_pub table if it doesn't exist then we want to add it. $check_org_id = chado_get_id_from_nid('pub', $node->nid); if (!$check_org_id) { $record = new stdClass(); $record->nid = $node->nid; $record->vid = $node->vid; $record->pub_id = $pub_id; drupal_write_record('chado_pub', $record); } } /** * Implements hook_update(). * * The purpose of the function is to allow the module to take action when an edited node is being * updated. It updates any name changes to the database tables that werec reated upon registering a Publication. * As well, the database will be changed, so the user changed information will be saved to the database. * * @param $node * The node being updated * * @ingroup tripal_legacy_pub */ function chado_pub_update($node) { $node->pubtitle = trim($node->pubtitle); $node->pyear = trim($node->pyear); $node->uniquename = trim($node->uniquename); $is_obsolete = $node->is_obsolete; $type_id = $node->type_id; // we need an array suitable for the tripal_pub_create_citation() function // to automatically generate a citation if a uniquename doesn't already exist $pub_arr = array(); // get the publication ID for this publication $pub_id = chado_get_id_from_nid('pub', $node->nid) ; $properties = array(); // stores all of the properties we need to add $cross_refs = array(); // stores any cross references for this publication // get the properties from the form $properties = chado_retrieve_node_form_properties($node); // get the list of properties for easy lookup (without doing lots of database queries $properties_list = array(); $sql = " SELECT DISTINCT CVTS.cvterm_id, CVTS.name, CVTS.definition FROM {cvtermpath} CVTP INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id INNER JOIN {cv} ON CVTO.cv_id = CV.cv_id WHERE CV.name = 'tripal_pub' and (CVTO.name = 'Publication Details' or CVTS.name = 'Publication Type') and NOT CVTS.is_obsolete = 1 ORDER BY CVTS.name ASC "; $prop_types = chado_query($sql); while ($prop = $prop_types->fetchObject()) { $properties_list[$prop->cvterm_id] = $prop->name; // The 'Citation' term is special because it serves // both as a property and as the uniquename for the // pub and we want it stored in both the pub table and the pubprop table if ($prop->name == 'Citation') { $citation_id = $prop->cvterm_id; if (!empty($node->uniquename)) { $properties[$citation_id][0] = $node->uniquename; } } } // iterate through all of the properties and remove those that really are // part of the pub table fields $volume = ''; $volumetitle = ''; $issue = ''; $pages = ''; $publisher = ''; $series_name = ''; $pubplace = ''; $miniref = ''; $cross_refs = array(); foreach ($properties as $type_id => $element) { foreach ($element as $index => $value) { $name = $properties_list[$type_id]; // populate our $pub_array for building a citation $pub_arr[$name] = $value; // remove properties that are stored in the pub table if ($name == "Volume") { $volume = $value; unset($properties[$type_id]); } elseif ($name == "Volume Title") { $volumetitle = $value; unset($properties[$type_id]); } elseif ($name == "Issue") { $issue = $value; unset($properties[$type_id]); } elseif ($name == "Pages") { $pages = $value; unset($properties[$type_id]); } elseif ($name == "Publisher") { $publisher = $value; unset($properties[$type_id]); } elseif ($name == "Journal Name" or $name == "Conference Name") { $series_name = $value; unset($properties[$type_id]); } elseif ($name == "Journal Country" or $name == "Published Location") { $pubplace = $value; // allow this property to go into the pubprop table so we don't loose info // so don't unset it. But it will also go into the pub.pubplace field } elseif ($name == "Publication Dbxref") { // we will add the cross-references to the pub_dbxref table // but we also want to keep the property in the pubprop table so don't unset it $cross_refs[] = $value; } } } // generate a citation for this pub if one doesn't already exist if (!$node->uniquename) { $pub_type = tripal_get_cvterm(array('cvterm_id' => $node->type_id)); $pub_arr['Title'] = $node->pubtitle; $pub_arr['Publication Type'][0] = $pub_type->name; $pub_arr['Year'] = $node->pyear; $node->uniquename = tripal_pub_create_citation($pub_arr); $properties[$citation_id][0] = $node->uniquename; } // update the pub record $match = array( 'pub_id' => $pub_id, ); $values = array( 'title' => $node->pubtitle, 'type_id' => $node->type_id, 'pyear' => $node->pyear, 'is_obsolete' => $node->is_obsolete ? 'true' : 'false', 'uniquename' => $node->uniquename, 'series_name' => substr($series_name, 0, 255), 'volumetitle' => $volumetitle, 'volume' => $volume, 'issue' => $issue, 'pages' => $pages, 'miniref' => substr($miniref, 0, 255), 'publisher' => substr($publisher, 0, 255), 'pubplace' => substr($pubplace, 0, 255), ); $status = chado_update_record('pub', $match, $values); if (!$status) { drupal_set_message("Error updating publication", "error"); watchdog('tripal_pub', "Error updating publication", array(), WATCHDOG_ERROR); return; } // now add in the properties by first removing any the publication // already has and adding the ones we have $details = array( 'property_table' => 'pubprop', 'base_table' => 'pub', 'foreignkey_name' => 'pub_id', 'foreignkey_value'=> $pub_id ); chado_update_node_form_properties($node, $details, $properties); // * Relationships Form * $details = array( 'relationship_table' => 'pub_relationship', // name of the _relationship table 'foreignkey_value' => $pub_id // value of the pub_id key ); chado_update_node_form_relationships($node, $details); // add in any database cross-references after first removing chado_delete_record('pub_dbxref', array('pub_id' => $pub_id)); foreach ($cross_refs as $index => $ref) { $dbxref = array(); if(preg_match('/^(.*?):(.*?)$/', trim($ref), $matches)) { $dbxref['db_name'] = $matches[1]; $dbxref['accession'] = $matches[2]; } $success = chado_associate_dbxref('pub', $pub_id, $dbxref); if (!$success) { drupal_set_message("Error cannot add publication cross reference: $ref", "error"); watchdog('tripal_pub', "Error cannot add publication cross reference: %ref", array('%ref' => $ref), WATCHDOG_ERROR); } } // * Additional DBxrefs Form * $details = array( 'linking_table' => 'pub_dbxref', // the name of your _dbxref table 'foreignkey_name' => 'pub_id', // the name of the key in your base table 'foreignkey_value' => $pub_id // the value of the pub_id key ); chado_update_node_form_dbxrefs($node, $details); } /** * Implements hook_load(). * * @param $node * The node that is to be loaded * * @return $node * The node with the information to be loaded into the database * * @ingroup tripal_legacy_pub */ function chado_pub_load($nodes) { foreach ($nodes as $nid => $node) { // find the pub and add in the details $pub_id = chado_get_id_from_nid('pub', $nid); // if the nid does not have a matching record then skip this node. // this can happen with orphaned nodes. if (!$pub_id) { continue; } // get the pub $values = array('pub_id' => $pub_id); $pub = chado_generate_var('pub', $values); // expand the 'text' fields as those aren't included by default // and they really shouldn't be so large to cause problems $pub = chado_expand_var($pub, 'field', 'pub.title'); $pub = chado_expand_var($pub, 'field', 'pub.volumetitle'); $pub = chado_expand_var($pub, 'field', 'pub.uniquename'); // set the URL path $nodes[$nid]->path = "pub/$pub_id"; $nodes[$nid]->pub = $pub; // Now get the title $node->title = chado_get_node_title($node); } } /** * Implements hook_delete(). * * This function takes a node and if the delete button has been chosen by the user, the publication * and it's details will be removed.Following,given the node-ID, the instance will be deleted from * the 'chado_pub' table. * * @parm $node * Then node to be deleted * * @ingroup tripal_legacy_pub */ function chado_pub_delete(&$node) { $pub_id = chado_get_id_from_nid('pub', $node->nid); // if we don't have a pub id for this node then this isn't a node of // type chado_pub or the entry in the chado_pub table was lost. if (!$pub_id) { return; } // Remove data from {chado_pub}, {node} and {node_revision} tables of // drupal database $sql_del = "DELETE FROM {chado_pub} WHERE nid = :nid AND vid = :vid"; db_query($sql_del, array(':nid' => $node->nid, ':vid' => $node->vid)); $sql_del = "DELETE FROM {node_revision} WHERE nid = :nid AND vid = :vid"; db_query($sql_del, array(':nid' => $node->nid, ':vid' => $node->vid)); $sql_del = "DELETE FROM {node} WHERE nid = :nid AND vid = :vid"; db_query($sql_del, array(':nid' => $node->nid, ':vid' => $node->vid)); // Remove data from pub and pubprop tables of chado database as well chado_query("DELETE FROM {pubprop} WHERE pub_id = :pub_id", array(':pub_id' => $pub_id)); chado_query("DELETE FROM {pub} WHERE pub_id = :pub_id", array(':pub_id' => $pub_id)); } /** * Implements hook_node_view(). Acts on all content types. * * @ingroup tripal_legacy_pub */ function tripal_pub_node_view($node, $view_mode, $langcode) { switch ($node->type) { case 'chado_pub': // Show feature browser and counts if ($view_mode == 'full') { $node->content['tripal_pub_authors'] = array( '#theme' => 'tripal_pub_authors', '#node' => $node, '#tripal_toc_id' => 'authors', '#tripal_toc_title' => 'Author Details', ); $node->content['tripal_pub_base'] = array( '#theme' => 'tripal_pub_base', '#node' => $node, '#tripal_toc_id' => 'base', '#tripal_toc_title' => 'Overview', '#weight' => -100, ); $node->content['tripal_pub_featuremaps'] = array( '#theme' => 'tripal_pub_featuremaps', '#node' => $node, '#tripal_toc_id' => 'featuremaps', '#tripal_toc_title' => 'Maps', ); $node->content['tripal_pub_features'] = array( '#theme' => 'tripal_pub_features', '#node' => $node, '#tripal_toc_id' => 'features', '#tripal_toc_title' => 'Features', ); $node->content['tripal_pub_libraries'] = array( '#theme' => 'tripal_pub_libraries', '#node' => $node, '#tripal_toc_id' => 'libraries', '#tripal_toc_title' => 'Libraries', ); $node->content['tripal_pub_projects'] = array( '#theme' => 'tripal_pub_projects', '#node' => $node, '#tripal_toc_id' => 'projects', '#tripal_toc_title' => 'Projects', ); $node->content['tripal_pub_properties'] = array( '#theme' => 'tripal_pub_properties', '#node' => $node, '#tripal_toc_id' => 'properties', '#tripal_toc_title' => 'Properties', ); $node->content['tripal_pub_references'] = array( '#theme' => 'tripal_pub_references', '#node' => $node, '#tripal_toc_id' => 'references', '#tripal_toc_title' => 'Cross References', ); $node->content['tripal_pub_relationships'] = array( '#theme' => 'tripal_pub_relationships', '#node' => $node, '#tripal_toc_id' => 'relationships', '#tripal_toc_title' => 'Relationships', ); $node->content['tripal_pub_stocks'] = array( '#theme' => 'tripal_pub_stocks', '#node' => $node, '#tripal_toc_id' => 'stocks', '#tripal_toc_title' => 'Stocks', ); } if ($view_mode == 'teaser') { $node->content['tripal_pub_teaser'] = array( '#theme' => 'tripal_pub_teaser', '#node' => $node, ); } break; } } /** * Implements hook_node_insert(). Acts on all content types. * * We want the publications to always have a URL of http://[base url]/pub/[pub id] * where [pub id] is the Chado publication ID. This will allow for easy linking * into the publication without needing to know the node. Of course if you know the * node that will still work too (e.g. http://[base url]/node/[node id] * so the nodeapi function ensures that the URL path is set after insert or update * of the node and when the node is loaded if it hasn't yet been set. * * @ingroup tripal_legacy_pub */ function tripal_pub_node_insert($node) { if ($node->type == 'chado_pub') { // get the pub $pub_id = chado_get_id_from_nid('pub', $node->nid); $values = array('pub_id' => $pub_id); $pub = chado_generate_var('pub', $values); // expand the 'text' fields as those aren't included by default // and they really shouldn't be so large to cause problems $pub = chado_expand_var($pub, 'field', 'pub.title'); $pub = chado_expand_var($pub, 'field', 'pub.volumetitle'); $pub = chado_expand_var($pub, 'field', 'pub.uniquename'); $node->pub = $pub; // Now get the title $node->title = chado_get_node_title($node); tripal_pub_set_pub_url($node, $pub_id); } } /** * Implements hook_node_load(). Acts on all content types. * * We want the publications to always have a URL of http://[base url]/pub/[pub id] * where [pub id] is the Chado publication ID. This will allow for easy linking * into the publication without needing to know the node. Of course if you know the * node that will still work too (e.g. http://[base url]/node/[node id] * so the nodeapi function ensures that the URL path is set after insert or update * of the node and when the node is loaded if it hasn't yet been set. * * @ingroup tripal_legacy_pub */ function tripal_pub_node_load($nodes, $types) { if (count(array_intersect(array('chado_pub'), $types))) { foreach ($nodes as $nid => $node) { if ($node->type == 'chado_pub' and !drupal_lookup_path('alias', 'node/' . $nid)) { $pub_id = chado_get_id_from_nid('pub', $node->nid); $path = tripal_pub_set_pub_url($node, $pub_id); } } } } /** * Implements hook_node_update(). Acts on all content types. * * We want the publications to always have a URL of http://[base url]/pub/[pub id] * where [pub id] is the Chado publication ID. This will allow for easy linking * into the publication without needing to know the node. Of course if you know the * node that will still work too (e.g. http://[base url]/node/[node id] * so the nodeapi function ensures that the URL path is set after insert or update * of the node and when the node is loaded if it hasn't yet been set. * * @ingroup tripal_legacy_pub */ function tripal_pub_node_update($node) { if ($node->type == 'chado_pub') { // get the pub $pub_id = chado_get_id_from_nid('pub', $node->nid); $values = array('pub_id' => $pub_id); $pub = chado_generate_var('pub', $values); // expand the 'text' fields as those aren't included by default // and they really shouldn't be so large to cause problems $pub = chado_expand_var($pub, 'field', 'pub.title'); $pub = chado_expand_var($pub, 'field', 'pub.volumetitle'); $pub = chado_expand_var($pub, 'field', 'pub.uniquename'); $node->pub = $pub; // Now get the title $node->title = chado_get_node_title($node); tripal_pub_set_pub_url($node, $pub_id); } } /** * Implements hook_node_presave(). Acts on all content types. * * @ingroup tripal_legacy_pub */ function tripal_pub_node_presave($node) { switch ($node->type) { // This step is for setting the title for the Drupal node. This title // is permanent and thus is created to be unique. Title changes provided // by tokens are generated on the fly dynamically, but the node title // seen in the content listing needs to be set here. Do not call // the chado_get_node_title() function here to set the title as the node // object isn't properly filled out and the function will fail. case 'chado_pub': // when syncing the details are not present in the $node object // as they are when submitted via the form. Therefore, if we do // not see any field values from the form, we assume this fucntion // is being called for syncing, so we must set the title accordingly if (property_exists($node, 'title')) { // do nothing, the title is set } else if (property_exists($node, 'pub')) { // in Drupal a node title can only be 255 characters so we truncate // it just in case $node->title = substr($node->pub->title, 0, 255); } break; } } /** * Implements [content_type]_chado_node_default_title_format(). * * Defines a default title format for the Chado Node API to set the titles on * Chado pub nodes based on chado fields. */ function chado_pub_chado_node_default_title_format() { return '[pub.title]'; } /** * Implements [content_type]_chado_node_sync_select_query(). * * Adds a where clause to the query to exclude the NULL pub. */ function chado_pub_chado_node_sync_select_query($query) { $query['where_clauses']['title'][] = 'pub.title <> :pub_title_null'; $query['where_args']['title'][':pub_title_null'] = 'NULL'; return $query; }