2.0, ); } /** * * @ingroup tripal_contact */ function tripal_contact_init() { drupal_add_css(drupal_get_path('theme', 'tripal') . '/css/tripal_contact.css'); } /** * Implementation of hook_tripal_contact_node_info(). * * This node_info, is a simple node that describes the functionallity of the module. * */ function tripal_contact_node_info() { return array( 'chado_contact' => array( 'name' => t('Contact'), 'base' => 'chado_contact', 'description' => t('A contact from the Chado database'), 'title_label' => t('Article Title'), 'body_label' => t('Abstract'), 'has_title' => TRUE, 'has_body' => FALSE, ), ); } /** * Tripal-contact-Menu * * Implemets hook_menu(): Adds menu items for the tripal_contact module menu. This section * gives the outline for the main menu of the Tripal-contact module * * @return * An array of menu items that is visible within the Drupal Menu, returned as soon * as the program is ran */ function tripal_contact_menu() { $items = array(); $items[ 'admin/tripal/tripal_contact' ]= array( 'title' => 'Contacts', 'description' => ('A module for interfacing the GMOD chado database with Drupal, providing viewing of contacts'), 'page callback' => 'theme', 'page arguments' => array('tripal_contact_admin'), 'access arguments' => array('administer tripal contacts'), 'type' => MENU_NORMAL_ITEM ); $items['admin/tripal/tripal_contact/configuration'] = array( 'title' => 'Configuration', 'description' => 'Integration of Chado contacts.', 'page callback' => 'drupal_get_form', 'page arguments' => array('tripal_contact_admin'), 'access arguments' => array('administer tripal contact'), 'type' => MENU_NORMAL_ITEM, ); $items['admin/tripal/tripal_contact/sync'] = array( 'title' => ' Sync Contacts', 'description' => 'Sync contacts in Chado with Drupal', 'page callback' => 'drupal_get_form', 'page arguments' => array('tripal_contact_sync_form'), 'access arguments' => array('administer tripal contacts'), 'type' => MENU_NORMAL_ITEM, ); // AJAX calls for adding/removing properties to a contact $items['tripal_contact/properties/add'] = array( 'page callback' => 'tripal_contact_property_add', 'access arguments' => array('edit chado_contact content'), 'type ' => MENU_CALLBACK, ); $items['tripal_contact/properties/description'] = array( 'page callback' => 'tripal_contact_property_get_description', 'access arguments' => array('edit chado_contact content'), 'type ' => MENU_CALLBACK, ); $items['tripal_contact/properties/minus/%/%'] = array( 'page callback' => 'tripal_contact_property_delete', 'page arguments' => array(3, 4), 'access arguments' => array('edit chado_contact content'), 'type ' => MENU_CALLBACK, ); return $items; } /** * Implements hook_theme(): Register themeing functions for this module * * * @return * An array of themeing functions to register * */ function tripal_contact_theme() { return array( 'tripal_contact_base' => array( 'arguments' => array('node' => NULL), 'template' => 'tripal_contact_base', ), 'tripal_contact_properties' => array( 'arguments' => array('node' => NULL), 'template' => 'tripal_contact_properties', ), 'tripal_contact_relationships' => array( 'arguments' => array('node' => NULL), 'template' => 'tripal_contact_relationships', ), 'tripal_contact_publications' => array( 'arguments' => array('node' => NULL), 'template' => 'tripal_contact_publications', ), 'tripal_contact_admin' => array( 'template' => 'tripal_contact_admin', 'arguments' => array(NULL), 'path' => drupal_get_path('module', 'tripal_contact') . '/theme' ), // Themed Forms 'chado_contact_node_form' => array( 'arguments' => array('form'), ), ); } /** * @ingroup tripal_library */ function tripal_contact_block_info() { $blocks['contbase']['info'] = t('Tripal Contact Details'); $blocks['contbase']['cache'] = DRUPAL_NO_CACHE; $blocks['contprops']['info'] = t('Tripal Contact Properties'); $blocks['contprops']['cache'] = DRUPAL_NO_CACHE; $blocks['contrels']['info'] = t('Tripal Contact Relationships'); $blocks['contrels']['cache'] = DRUPAL_NO_CACHE; $blocks['contpubs']['info'] = t('Tripal Cotact Publications'); $blocks['contpubs']['cache'] = DRUPAL_NO_CACHE; return $blocks; } /** * @ingroup tripal_library */ function tripal_contact_block_view($delta = '') { if (user_access('access chado_library content') and arg(0) == 'node' and is_numeric(arg(1))) { $nid = arg(1); $node = node_load($nid); $block = array(); switch ($delta) { case 'contbase': $block['subject'] = t('Details'); $block['content'] = theme('tripal_contact_base', $node); break; case 'contprops': $block['subject'] = t('Properties'); $block['content'] = theme('tripal_contact_properties', $node); break; case 'contrels': $block['subject'] = t('Relationships'); $block['content'] = theme('tripal_contact_relationships', $node); break; case 'contpubs': $block['subject'] = t('Publications'); $block['content'] = theme('tripal_contact_publications', $node); break; default : } return $block; } } /** * Implement hook_perm(). */ function tripal_contact_permissions() { return array( 'access chado_contact content' => array( 'title' => t('View Contacts'), 'description' => t('Allow users to view contact pages.'), ), 'create chado_contact content' => array( 'title' => t('Create Contacts'), 'description' => t('Allow users to create new contact pages.'), ), 'delete chado_contact content' => array( 'title' => t('Delete Contacts'), 'description' => t('Allow users to delete contact pages.'), ), 'edit chado_contact content' => array( 'title' => t('Edit Contacts'), 'description' => t('Allow users to edit contact pages.'), ), 'adminster tripal contact' => array( 'title' => t('Administer Contacts'), 'description' => t('Allow users to administer all contacts.'), ), ); } /** * Implement hook_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. * */ function chado_contact_node_access($node, $op, $account ) { if ($op == 'create') { if (!user_access('create chado_contact content', $account)) { return FALSE; } return TRUE; } if ($op == 'update') { if (!user_access('edit chado_contact content', $account)) { return FALSE; } } if ($op == 'delete') { if (!user_access('delete chado_contact content', $account)) { return FALSE; } } if ($op == 'view') { if (!user_access('access chado_contact content', $account)) { return FALSE; } } return NULL; } /** * Implementation of tripal_contact_insert(). * * This function inserts user entered information pertaining to the contact instance into the * 'contactauthor', 'contactprop', 'chado_contact', 'contact' talble of the database. * * @parm $node * Then node which contains the information stored within the node-ID * * */ function chado_contact_insert($node) { // if a contact_id already exists for this node then it already exists in Chado and // we get here because we are syncing the node. Therefore, we can skip the insert if ($node->contact_id) { $contact['contact_id'] = $node->contact_id; } else { // we don't want to store the description in the description field as it may be longer than // 255 characters, so we'll use a property to store this value. $values = array( 'name' => $node->title, 'description' => '', 'type_id' => $node->type_id ); $options = array('statement_name' => 'ins_contact_nadety'); $contact = tripal_core_chado_insert('contact', $values, $options); if (!$contact) { drupal_set_message(t('Could not add the contact'), 'error'); watchdog('tripal_contact','Could not add the contact', array(), WATCHDOG_ERROR); return FALSE; } // now add the properties $properties = array(); // stores all of the properties we need to add // get the list of properties for easy lookup (without doing lots of database queries $properties_list = array(); $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} CV ON CVTO.cv_id = CV.cv_id WHERE CV.name = 'tripal_contact' AND NOT CVTO.name = 'Contact Type' ORDER BY CVTS.name ASC "; $prop_types = chado_query($sql); while ($prop = $prop_types->fetchObject()) { $properties_list[$prop->cvterm_id] = $prop->name; } // get the properties that should be added. Properties are in one of two forms: // 1) prop_value-[type id]-[index] // 2) new_value-[type id]-[index] // 3) new_id, new_value foreach ($node as $name => $value) { if (preg_match('/^new_value-(\d+)-(\d+)/', $name, $matches)) { $type_id = $matches[1]; $index = $matches[2]; $name = $properties_list[$type_id]; $properties[$name][$index] = trim($value); } } if ($node->new_id and $node->new_value) { $type_id = $node->new_id; $index = count($properties[$name]); $name = $properties_list[$type_id]; $properties[$name][$index] = trim($node->new_value); } // now add in the properties foreach ($properties as $property => $elements) { foreach ($elements as $rank => $value) { $status = tripal_contact_insert_property($contact['contact_id'], $property, $value, FALSE); if (!$status) { drupal_set_message("Error cannot add property: $property", "error"); watchdog('t_contact', "Error cannot add property: %prop", array('%property' => $property), WATCHDOG_ERROR); } } } } // add the record to the chado_contact table in Drupal if ($contact) { // add the description property tripal_contact_insert_property($contact['contact_id'], 'contact_description', $node->description, TRUE); // make sure the entry for this contact doesn't already exist in the chado_contact table // if it doesn't exist then we want to add it. $contact_id = chado_get_id_for_node('contact', $node->nid) ; if (!$contact_id) { // next add the item to the drupal table $sql = "INSERT INTO {chado_contact} (nid, vid, contact_id) ". "VALUES (:nid, :vid, :contact_id)"; db_query($sql, array(':nid'=> $node->nid, ':vid' => $node->vid, ':contact_id' => $contact['contact_id'])); } } else { drupal_set_message(t('Unable to add contact.', 'warning')); watchdog('tripal_contact', 'Insert contact: Unable to create contact where values: %values', array('%values' => print_r($values, TRUE)), WATCHDOG_WARNING); } return TRUE; } /* * * 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 contact. * 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_contact */ function chado_contact_update($node) { if ($node->revision) { // there is no way to handle revisions in Chado but leave // this here just to make not we've addressed it. } $contact_id = chado_get_id_for_node('contact', $node->nid) ; // check to see if this contact name doens't already exists. $sql = "SELECT contact_id FROM {contact} WHERE NOT contact_id = :contact_id AND name = :name"; $contact = chado_query($sql, array(':contact_id' => $contact_id, ':name' => $node->contact_name))->fetchObject(); if ($contact) { drupal_set_message(t('A contact with this name already exists. Cannot perform update.'), 'warning'); return; } // update the contact record $match = array( 'contact_id' => $contact_id, ); $values = array( 'name' => $node->title, 'description' => '', 'type_id' => $node->type_id ); $status = tripal_core_chado_update('contact', $match, $values); if (!$status) { drupal_set_message("Error updating contact", "error"); watchdog('t_contact', "Error updating contact", array(), WATCHDOG_ERROR); return; } // now update the properties $properties = array(); // stores all of the properties we need to add // get the list of properties for easy lookup (without doing lots of database queries $properties_list = array(); $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} CV ON CVTO.cv_id = CV.cv_id WHERE CV.name = 'tripal_contact' AND NOT CVTO.name = 'Contact Type' ORDER BY CVTS.name ASC "; $prop_types = chado_query($sql); while ($prop = $prop_types->fetchObject()) { $properties_list[$prop->cvterm_id] = $prop->name; } // get the properties that should be added. Properties are in one of three forms: // 1) prop_value-[type id]-[index] // 2) new_value-[type id]-[index] // 3) new_id, new_value // dpm($node); foreach ($node as $key => $value) { if (preg_match('/^prop_value-(\d+)-(\d+)/', $key, $matches)) { $type_id = $matches[1]; $index = $matches[2]; $name = $properties_list[$type_id]; $properties[$name][$index] = trim($value); } if (preg_match('/^new_value-(\d+)-(\d+)/', $key, $matches)) { $type_id = $matches[1]; $index = $matches[2]; $name = $properties_list[$type_id]; $properties[$name][$index] = trim($value); } } if ($node->new_id and $node->new_value) { $type_id = $node->new_id; $name = $properties_list[$type_id]; $index = count($properties[$name]); $properties[$name][$index] = trim($node->new_value); } // now add in the properties by first removing any the contact // already has and adding the ones we have tripal_core_chado_delete('contactprop', array('contact_id' => $contact_id)); foreach ($properties as $property => $elements) { foreach ($elements as $rank => $value) { $status = tripal_contact_insert_property($contact_id, $property, $value, FALSE); if (!$status) { drupal_set_message("Error cannot add property: '$property'", "error"); watchdog('t_contact', "Error cannot add property: '%prop'", array('%prop' => $property), WATCHDOG_ERROR); } } } tripal_contact_update_property($contact_id, 'contact_description', $node->description, 1); } /** * Implementation of tripal_contact_load(). * * * @param $node * The node that is to be accessed from the database * * @return $node * The node with the information to be loaded into the database * */ function chado_contact_load($node) { // get the feature details from chado $contact_id = chado_get_id_for_node('contact', $node->nid); $values = array('contact_id' => $contact_id); $contact = tripal_core_generate_chado_var('contact', $values); // get the contact description and replace the contact.description field with this one $values = array( 'contact_id' => $contact->contact_id, 'type_id' => array( 'name' => 'contact_description', ), ); $options = array( 'return_array' => 1, 'include_fk' => array('type_id' => 1), ); $description = tripal_core_generate_chado_var('contactprop', $values, $options); if (count($description) == 1) { $description = tripal_core_expand_chado_vars($description, 'field', 'contactprop.value'); $contact->description = $description[0]->value; } $additions = new stdClass(); $additions->contact = $contact; return $additions; } /** * Implementation of tripal_contact_delete(). * * This function takes a node and if the delete button has been chosen by the user, the contact * and it's details will be removed.Following,given the node-ID, the instance will be deleted from * the 'chado_contact' table. * * @parm $node * Then node which contains the information stored within the node-ID * */ function chado_contact_delete(&$node) { $contact_id = chado_get_id_for_node('contact', $node->nid); // if we don't have a contact id for this node then this isn't a node of // type chado_contact or the entry in the chado_contact table was lost. if (!$contact_id) { return; } // Remove data from {chado_contact}, {node} and {node_revisions} tables of // drupal database $sql_del = "DELETE FROM {chado_contact} 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 contact and contactprop tables of chado database as well chado_query("DELETE FROM {contactprop} WHERE contact_id = :contact_id", array(':contact_id' => $contact_id)); chado_query("DELETE FROM {contact} WHERE contact_id = :contact_id", array(':contact_id' => $contact_id)); } /** * * * @ingroup tripal_contact */ function tripal_contact_preprocess_tripal_contact_relationships(&$variables) { // we want to provide a new variable that contains the matched contacts. $contact = $variables['node']->contact; // normally we would use tripal_core_expand_chado_vars to expand our // organism object and add in the relationships, however whan a large // number of relationships are present this significantly slows the // query, therefore we will manually perform the query $sql = " SELECT C.name, C.contact_id, CP.nid, CVT.name as rel_type FROM contact_relationship PR INNER JOIN {contact} C ON PR.object_id = C.contact_id INNER JOIN {cvterm} CVT ON PR.type_id = CVT.cvterm_id LEFT JOIN public.chado_contact CP ON C.contact_id = CP.contact_id WHERE PR.subject_id = :contact_id "; $as_subject = chado_query($sql, array(':contact_id' => $contact->contact_id)); $sql = " SELECT C.name, C.contact_id, CP.nid, CVT.name as rel_type FROM contact_relationship PR INNER JOIN {contact} C ON PR.subject_id = C.contact_id INNER JOIN {cvterm} CVT ON PR.type_id = CVT.cvterm_id LEFT JOIN public.chado_contact CP ON C.contact_id = CP.contact_id WHERE PR.object_id = :contact_id "; $as_object = chado_query($sql, array(':contact_id' => $contact->contact_id)); // combine both object and subject relationshisp into a single array $relationships = array(); $relationships['object'] = array(); $relationships['subject'] = array(); // iterate through the object relationships while ($relationship = $as_object->fetchObject()) { // get the relationship and child types $rel_type = t(preg_replace('/_/', " ", $relationship->rel_type)); $sub_type = t(preg_replace('/_/', " ", $relationship->sub_type)); if (!array_key_exists($rel_type, $relationships['object'])) { $relationships['object'][$rel_type] = array(); } if (!array_key_exists($sub_type, $relationships['object'][$rel_type])) { $relationships['object'][$rel_type][$sub_type] = array(); } $relationships['object'][$rel_type][$sub_type][] = $relationship; } // now add in the subject relationships while ($relationship = $as_subject->fetchObject()) { // get the relationship and child types $rel_type = t(preg_replace('/_/', " ", $relationship->rel_type)); $obj_type = t(preg_replace('/_/', " ", $relationship->obj_type)); if (!array_key_exists($rel_type, $relationships['subject'])) { $relationships['subject'][$rel_type] = array(); } if (!array_key_exists($obj_type, $relationships['subject'][$rel_type])) { $relationships['subject'][$rel_type][$obj_type] = array(); } $relationships['subject'][$rel_type][$obj_type][] = $relationship; } $contact->all_relationships = $relationships; } /* * */ function tripal_contact_form_alter(&$form, &$form_state, $form_id) { if ($form_id == "chado_contact_node_form") { } }