array( 'name' => t('Blast Database'), 'base' => 'blastdb', 'description' => t('Registers a BLAST Database for use with the BLAST UI.'), ), ); } /** * Implements hook_node_access(). */ function blastdb_node_access($node, $op, $account) { $node_type = $node; if (is_object($node)) { $node_type = $node->type; } if($node_type == 'blastdb') { if ($op == 'create') { if (!user_access('create Blast Database', $account)) { return NODE_ACCESS_DENY; } return NODE_ACCESS_ALLOW; } if ($op == 'update') { if (!user_access('edit Blast Database', $account)) { return NODE_ACCESS_DENY; } } if ($op == 'delete') { if (!user_access('delete Blast Database', $account)) { return NODE_ACCESS_DENY; } } if ($op == 'view') { if (!user_access('access Blast Database', $account)) { return NODE_ACCESS_DENY; } } return NODE_ACCESS_IGNORE; } } /** * Form constructor for the blastdb node * * @see blastdb_insert() * @see blastdb_update() * @see blastdb_delete() * @see blastdb_load() */ function blastdb_form($node, &$form_state) { $form = array(); $form['#validate'] = array('blastdb_form_validate'); $form['#attached']['css'] = array( drupal_get_path('module', 'blast_ui') . '/theme/css/form.css', ); $form['core'] = array( '#type' => 'fieldset', '#title' => 'General' ); $form['core']['db_name']= array( '#type' => 'textfield', '#title' => t('Human-readable Name for Blast database'), '#required' => TRUE, '#default_value' => isset($node->db_name) ? $node->db_name : '', ); $form['core']['db_path']= array( '#type' => 'textfield', '#title' => t('File Prefix including Full Path'), '#description' => t('The full path to your blast database including the file name but not the file type suffix. For example, /var/www/website/sites/default/files/myblastdb'), '#required' => TRUE, '#default_value' => isset($node->db_path) ? $node->db_path : '', ); $form['core']['db_dbtype'] = array( '#type' => 'radios', '#title' => t('Type of the blast database'), '#options' => array( 'nucleotide' => t('Nucleotide'), 'protein' => t('Protein'), ), '#required' => TRUE, '#default_value' => isset($node->db_dbtype) ? $node->db_dbtype : 'n', ); $form['dbxref'] = array( '#type' => 'fieldset', '#title' => 'Link-outs', '#description' => 'These settings will be used to transform the hit name into a link to additional information.', ); $types = module_invoke_all('blast_linkout_info'); $options = array(); foreach ($types as $machine_name => $details) { $options[$machine_name] = (isset($details['name'])) ? $details['name'] : $machine_name; } $linkout_type = (isset($node->linkout->type)) ? $node->linkout->type : 'none'; $linkout_type = (isset($form_state['values'])) ? $form_state['values']['dbxref_linkout_type'] : $linkout_type; $form['dbxref']['dbxref_linkout_type'] = array( '#type' => 'radios', '#title' => 'Link-out Type', '#description' => 'This determines how the URL to be linked to is formed. Make sure the database chosen supports this type of link (ie: the database should point to a GBrowse instance if you choose GBrowse here).', '#options' => $options, '#default_value' => $linkout_type, '#ajax' => array( 'callback' => 'ajax_blast_ui_node_linkout_custom_callback', 'wrapper' => 'link-outs', ) ); $form['dbxref']['details'] = array( '#prefix' => '', ); // Add information about each format to the description. if ($linkout_type) { $form['dbxref']['details']['dbxref_linkout_description'] = array( '#type' => 'item', '#markup' => '

' .''.$types[$linkout_type]['name'].': ' .$types[$linkout_type]['help'] .'

', '#prefix' => '', ); } if ($types[$linkout_type]['require_regex']) { $regex = array( 'default' => array( 'title' => 'Generic', 'help' => 'A single word followed by a free-text definition. ' . 'The first word contains only alphanumeric characters and optionally ' . 'underscores and will be used as the ID of the sequence.' ), 'genbank' => array( 'title' => 'NCBI GenBank', 'help' => 'Follows the same format as the first option ' . 'except that the first "word" is of the following form: ' . 'gb|accession|locus. The accession will be used as the ID of the sequence.' ), 'embl' => array( 'title' => 'EMBL Data Library', 'help' => 'Follows the same format as the first option ' . 'except that the first "word" is of the following form: ' . 'emb|accession|locus. The accession will be used as the ID of the sequence.' ), 'swissprot' => array( 'title' => 'SWISS-PROT', 'help' => 'Follows the same format as the first option ' . 'except that the first "word" is of the following form: ' . 'sp|accession|entry name. The accession will be used as the ID of the sequence.' ), 'custom' => array( 'title' => 'Custom Format', 'help' => 'Allows you to use a regular expression (define one below) to ' . 'extract a specifc portion of the FASTA header to be used as the ID.' ), ); $regex_type = (isset($node->linkout->regex_type)) ? $node->linkout->regex_type : 'default'; $regex_type = (isset($form_state['values'])) ? $form_state['values']['dbxref_id_type'] : $regex_type; $form['dbxref']['details']['dbxref_id_type'] = array( '#type' => 'radios', '#title' => 'FASTA header format', '#description' => 'Choose the format that matches the format of the FASTA ' . 'headers in this BLAST database or choose custom to define your own ' . 'using regular expressions. This ID will be used to create the URL for the link-out.', '#options' => array( 'default' => '' . $regex['default']['title'] . '', 'genbank' => '' . $regex['genbank']['title'] . '', 'embl' => '' . $regex['embl']['title'] . '', 'swissprot' => '' . $regex['swissprot']['title'] . '', 'custom' => '' . $regex['custom']['title'] . '', ), '#default_value' => $regex_type, '#required' => TRUE, '#ajax' => array( 'callback' => 'ajax_blast_ui_node_linkout_custom_callback', 'wrapper' => 'link-outs', ) ); // Add information about each format to the description. if ($regex_type) { $form['dbxref']['details']['dbxref_id_type']['#description'] .= '

'.$regex[$regex_type]['title'].': '.$regex[$regex_type]['help'].'

'; } if ($regex_type == 'custom') { $form['dbxref']['details']['regex'] = array( '#type' => 'textfield', '#title' => 'Regular Expression', '#description' => t('A PHP Regular expression with curved brackets ' . 'surrounding the ID that should be used in the URL to provide a link-' . 'out to additional information. See PHP.net Regular ' . 'Expression Documentation for more information. Be sure ' . 'to include the opening and closing slashes. This is only ' . 'available if custom was choosen for the FASTA header format above.', array('@url' => 'http://php.net/manual/en/reference.pcre.pattern.syntax.php')), '#required' => TRUE, '#default_value' => (isset($node->linkout->regex)) ? $node->linkout->regex : '' ); } } if ($types[$linkout_type]['require_db']) { $db_options = tripal_get_db_select_options(); $db_options[0] = ''; asort($db_options); $form['dbxref']['details']['db_id'] = array( '#type' => 'select', '#title' => 'External Database', '#description' => 'The external database you would like to link-out to. ' . 'Note that this list includes all Tripal Databases and if the database ' . 'you would like to link-out to is not included you can add it through ' . l('Administration > Tripal > Data Loaders > Chado Databases','admin/tripal/loaders/chado_db/add', array('attributes' => array('target' => '_blank'))) . '.', '#options' => $db_options, '#required' => TRUE, '#default_value' => (isset($node->linkout->db_id->db_id)) ? $node->linkout->db_id->db_id : 0 ); } // CViTjs settings, if enabled if (variable_get('blast_ui_cvitjs_enabled', false)) { $form['cvitjs'] = array( '#type' => 'fieldset', '#title' => 'Whole Genome Visualization', '#description' => 'Settings for the display of BLAST hits on an entire genome assembly using CViTjs.', '#prefix' => '
', '#suffix' => '
', ); $form['cvitjs']['cvitjs_enabled'] = array( '#type' => 'checkbox', '#title' => t('Show BLAST hits on the genome in the results page.'), '#description' => t('Uses CViTjs to display BLAST hits on the entire genome'), '#default_value' => (isset($node->cvitjs_enabled)) ? $node->cvitjs_enabled : false, ); $cvitjs_msg_class = 'blastdb-extra-info'; $cvitjs_msg = 'Target Genome Configuration should be under [data.'.$node->db_name.'] in the main cvit.conf.'; $conf_section = blast_ui_get_cvit_conf_text('data.'.$node->db_name); if (!$conf_section) { $cvitjs_msg_class .= ' messages warning'; $cvitjs_msg .= '

There is no section for this genome target defined in the CViTjs configuration file. No genome visualization will be shown until you define a configuration section, "[data.'.$form_state['values']['db_name'].']", at ' .l('Admin > Tripal > Extensions > Tripal BLAST > BLAST UI', 'admin/tripal/extension/tripal_blast') .'.'; } else { $cvitjs_msg .= '

Current Configuration:
'.$conf_section.'
'; } $form['cvitjs']['cvitjs_enabled']['#description'] .= '
'.$cvitjs_msg.'

'; } return $form; } function blastdb_form_validate($form, $form_state) { if (isset($form_state['values']['regex']) AND !empty($form_state['values']['regex'])) { // Check that any supplied regex includes //. if (!preg_match('/\/.*\//', $form_state['values']['regex'])) { form_set_error('regex', 'Regular Expressions require opening and closing slashes to delinate them. For example, /^(\s+) .*/'); } // Check that the supplied regex is valid. elseif (@preg_match($form_state['values']['regex'], NULL) === FALSE) { form_set_error('regex', 'Regular Expression not valid. See ' . 'PHP.net Regular ' . 'Expression Documentation for more information.'); } } // Check that the supplied db actually contains a URL prefix. if (isset($form_state['values']['db_id'])) { $db = tripal_get_db(array('db_id' => $form_state['values']['db_id'])); if (empty($db)) { form_set_error('db_id', 'The database chosen no longer exists.'); } if (empty($db->urlprefix)) { form_set_error('db_id', 'The database choosen does not have a URL prefix ' . 'listed which means a link-out could not be created for BLAST hits. ' . 'Please edit the database ' . l('here', 'admin/tripal/chado/tripal_db/edit/' . $db->db_id, array('attributes' => array('target' => '_blank'))) . ' to include a URL prefix before continuing' ); } } // Check that there is a cvitjs section for the current if (isset($form_state['values']['cvitjs_enabled']) AND $form_state['values']['cvitjs_enabled']) { $conf_section = blast_ui_get_cvit_conf_text('data.'.$form_state['values']['db_name']); if (!$conf_section) { drupal_set_message('There is no section for this genome target defined in the CViTjs configuration file. No genome visualization will be shown until you define a configuration section, "[data.'.$form_state['values']['db_name'].']", at ' .l('Admin > Tripal > Extensions > Tripal BLAST > BLAST UI', 'admin/tripal/extension/tripal_blast') .'.', 'warning'); } } } /** * Implements hook_insert(). */ function blastdb_insert($node) { // Handle Link-out Rules. $regex = ''; if (isset($node->dbxref_id_type)) { if ($node->dbxref_id_type == 'custom') { $regex = $node->regex; } else { $regex = $node->dbxref_id_type; } } $db_id = 0; if (isset($node->db_id)) { $db_id = $node->db_id; } if (!$node->dbxref_linkout_type) { $node->dbxref_linkout_type = 'none'; } if (!isset($node->cvitjs_enabled)) { $node->cvitjs_enabled = 0; } // Actually insert the record. db_insert('blastdb')->fields(array( 'nid' => $node->nid, 'name' => $node->db_name, 'path' => trim($node->db_path), 'dbtype' => $node->db_dbtype, 'dbxref_id_regex' => $regex, 'dbxref_db_id' => $db_id, 'dbxref_linkout_type' => $node->dbxref_linkout_type, 'cvitjs_enabled' => $node->cvitjs_enabled, ))->execute(); } /** * Implements hook_node_insert(). * This function acts on ALL NODES */ function blast_ui_node_insert($node) { if ($node->type == 'blastdb') { $node->title = $node->db_name; } } /** * Implements hook_update(). */ function blastdb_update($node) { // Handle Link-out Rules. $regex = ''; if (isset($node->dbxref_id_type)) { if ($node->dbxref_id_type == 'custom') { $regex = $node->regex; } else { $regex = $node->dbxref_id_type; } } $db_id = 0; if (isset($node->db_id)) { $db_id = $node->db_id; } if (!$node->cvitjs_enabled) { $node->cvitjs_enabled = 0; } if (!$node->dbxref_linkout_type) { $node->dbxref_linkout_type = 'none'; } // Update the record. db_update('blastdb')->fields(array( 'name' => $node->db_name, 'path' => $node->db_path, 'dbtype' => $node->db_dbtype, 'dbxref_id_regex' => $regex, 'dbxref_db_id' => $db_id, 'dbxref_linkout_type' => $node->dbxref_linkout_type, 'cvitjs_enabled' => $node->cvitjs_enabled, ))->condition('nid', $node->nid)->execute(); } /** * Implements hook_node_update(). * This function acts on ALL NODES */ function blast_ui_node_update($node) { if ($node->type == 'blastdb') { $node->title = $node->db_name; } } /** * Implements hook_delete(). */ function blastdb_delete($node) { db_delete('blastdb')->condition('nid',$node->nid)->execute(); } /** * Implements hook_load(). */ function blastdb_load($nodes) { $sql = " SELECT nid, name, path, dbtype, dbxref_id_regex, dbxref_db_id, dbxref_linkout_type, cvitjs_enabled FROM {blastdb} WHERE nid IN (:nids)"; $result = db_query($sql, array(':nids' => array_keys($nodes))); foreach ($result as $record) { // Add basic blast node information. $nodes[$record->nid]->db_name = $record->name; $nodes[$record->nid]->db_path = $record->path; $nodes[$record->nid]->title = $record->name; $nodes[$record->nid]->db_dbtype = $record->dbtype; // CViTjs status $nodes[$record->nid]->cvitjs_enabled = $record->cvitjs_enabled; // Determine the type of link-out chosen. $types = module_invoke_all('blast_linkout_info'); $type = NULL; if (isset($types[ $record->dbxref_linkout_type ])) { $type = $types[ $record->dbxref_linkout_type ]; } else { tripal_report_error( 'blast_ui', TRIPAL_ERROR, 'Unable to find details on the type of link-out choosen (%type). Have you defined hook_blast_linkout_info()? Make sure to clear the cache once you do so.', array('%type' => $record->dbxref_linkout_type) ); } // Now determine if this node meets the requirements for the linkout // chosen before adding linkout information. $add_linkout = TRUE; if (!$type OR $record->dbxref_linkout_type == 'none') { $add_linkout = FALSE; } else { if ($type['require_regex'] AND !$record->dbxref_id_regex) { $add_linkout = FALSE; } if ($type['require_db'] AND !$record->dbxref_db_id) { $add_linkout = FALSE; } } // Add information related to link-outs to the node. if ($add_linkout) { $nodes[$record->nid]->linkout = new stdClass(); // If the link-out type requires a regex then provide one. if ($type['require_regex']) { if (preg_match('/\/.*\//', $record->dbxref_id_regex)) { $nodes[$record->nid]->linkout->regex_type = 'custom'; $nodes[$record->nid]->linkout->regex = $record->dbxref_id_regex; } else { $nodes[$record->nid]->linkout->regex_type = $record->dbxref_id_regex; $nodes[$record->nid]->linkout->regex = get_blastdb_linkout_regex($nodes[$record->nid]); } } else { $nodes[$record->nid]->linkout->regex_type = 'none'; $nodes[$record->nid]->linkout->regex = NULL; } // If the link-out type requires a db then provide one. if (isset($type['require_db'])) { $nodes[$record->nid]->linkout->db_id = tripal_get_db(array('db_id' => $record->dbxref_db_id)); } else { $nodes[$record->nid]->linkout->db_id = NULL; } $nodes[$record->nid]->linkout->none = FALSE; // Support complex link-outs. $nodes[$record->nid]->linkout->type = $record->dbxref_linkout_type; $nodes[$record->nid]->linkout->url_function = $type['process function']; } // If there is no linkout then provide some defaults. else { $nodes[$record->nid]->linkout = new stdClass(); $nodes[$record->nid]->linkout->regex = ''; $nodes[$record->nid]->linkout->db_id = 0; $nodes[$record->nid]->linkout->none = TRUE; } } } /** * AJAX Callback: Update Node Link-out Regex Textfield. * * On BlastDB node form the Link-out (dbxref) options allow for settings of a * custom regex which should only be enabled when "Custom" is selected. This * callback refreshes the regex textfield so it can change (ie: become enabled) * when someone selects custom. */ function ajax_blast_ui_node_linkout_custom_callback($form, $form_state) { return $form['dbxref']['details']; }