tripal_stock.chado_node.inc

  1. 2.x tripal_stock/includes/tripal_stock.chado_node.inc
  2. 3.x legacy/tripal_stock/includes/tripal_stock.chado_node.inc

Stock Node Functionality

File

legacy/tripal_stock/includes/tripal_stock.chado_node.inc
View source
  1. <?php
  2. /**
  3. * @file Stock Node Functionality
  4. */
  5. /**
  6. * Implements hook_node_info().
  7. * Registers a stock node type
  8. *
  9. * @return
  10. * An array describing various details of the node
  11. *
  12. * @ingroup tripal_legacy_stock
  13. */
  14. function tripal_stock_node_info() {
  15. return array(
  16. 'chado_stock' => array(
  17. 'name' => t('Stock'),
  18. 'base' => 'chado_stock',
  19. 'description' => t('A Chado Stock is a collection of material that can be sampled and have experiments performed on it.'),
  20. 'has_title' => TRUE,
  21. 'locked' => TRUE,
  22. 'chado_node_api' => array(
  23. 'base_table' => 'stock',
  24. 'hook_prefix' => 'chado_stock',
  25. 'record_type_title' => array(
  26. 'singular' => t('Stock'),
  27. 'plural' => t('Stocks')
  28. ),
  29. 'sync_filters' => array(
  30. 'type_id' => TRUE,
  31. 'organism_id' => TRUE
  32. ),
  33. )
  34. ),
  35. );
  36. }
  37. /**
  38. * Implements hook_load().
  39. *
  40. * When a node is requested by the user this function is called to allow us
  41. * to add auxiliary data to the node object.
  42. *
  43. * @ingroup tripal_legacy_stock
  44. */
  45. function chado_stock_load($nodes) {
  46. foreach ($nodes as $nid => $node) {
  47. // find the stock and add in the details
  48. $stock_id = chado_get_id_from_nid('stock', $nid);
  49. // if the nid does not have a matching record then skip this node.
  50. // this can happen with orphaned nodes.
  51. if (!$stock_id) {
  52. continue;
  53. }
  54. // build the variable with all the stock details
  55. $values = array('stock_id' => $stock_id);
  56. $stock = chado_generate_var('stock', $values);
  57. $stock = chado_expand_var($stock, 'field', 'stock.uniquename');
  58. $stock = chado_expand_var($stock, 'field', 'stock.description');
  59. $nodes[$nid]->stock = $stock;
  60. // Now get the title
  61. $node->title = chado_get_node_title($node);
  62. }
  63. }
  64. /**
  65. * Implements hook_form().
  66. * Creates the main Add/Edit/Delete Form for chado stocks
  67. *
  68. * Parts to be added by this form
  69. * name,
  70. * uniquename,
  71. * description,
  72. * type => select from cvterm with key cvterm_id,
  73. * organism => select from available with key organism_id
  74. * main_db_reference => accession, version, description, db_name(select from dropdown)
  75. *
  76. * @param $node
  77. * An empty node object on insert OR the current stock node object on update
  78. * @param $form_state
  79. * The current state of the form
  80. *
  81. * @return
  82. * A description of the form to be rendered by drupal_get_form()
  83. *
  84. * @ingroup tripal_legacy_stock
  85. */
  86. function chado_stock_form($node, $form_state) {
  87. /* I don't think we need this... commenting out but leaving just in case
  88. // If existing stock then expand all fields needed using the chado API
  89. if (isset($node->nid)) {
  90. $fields_needed = array('stock.uniquename', 'stock.name', 'stock.stock_id', 'stock.type_id', 'stock.organism_id', 'stock.description', 'stock.dbxref_id', 'dbxref.accession', 'dbxref.description', 'dbxref.db_id', 'db.db_id');
  91. foreach ($fields_needed as $field_name) {
  92. // Check to see if it's excluded and expand it if so
  93. if (isset($node->expandable_fields)) {
  94. if (in_array($field_name, $node->expandable_fields)) {
  95. $node = chado_expand_var($node, 'field', $field_name);
  96. }
  97. }
  98. }
  99. }
  100. */
  101. //TODO: @lacey can you take a look at the above code?
  102. // Default values can come in the following ways:
  103. //
  104. // 1) as elements of the $node object. This occurs when editing an existing stock
  105. // 2) in the $form_state['values'] array which occurs on a failed validation or
  106. // ajax callbacks from non submit form elements
  107. // 3) in the $form_state['input'] array which occurs on ajax callbacks from submit
  108. // form elements and the form is being rebuilt
  109. //
  110. // set form field defaults
  111. $sname = '';
  112. $uniquename = '';
  113. $stock_id = 0;
  114. $type_id = 0;
  115. $organism_id = 0;
  116. $sdescription = '';
  117. $dbxref_accession = '';
  118. $dbxref_description = '';
  119. $dbxref_database = 0;
  120. // 1) if we are editing an existing node then the stock is already part of the node
  121. if (property_exists($node, 'stock')) {
  122. $sname = $node->stock->name;
  123. $uniquename = $node->stock->uniquename;
  124. $stock_id = $node->stock->stock_id;
  125. $type_id = $node->stock->type_id->cvterm_id;
  126. $organism_id = $node->stock->organism_id->organism_id;
  127. $sdescription = $node->stock->description;
  128. if (isset($node->stock->dbxref_id->db_id)) {
  129. $dbxref_accession = $node->stock->dbxref_id->accession;
  130. $dbxref_description = $node->stock->dbxref_id->description;
  131. $dbxref_database = $node->stock->dbxref_id->db_id->db_id;
  132. }
  133. }
  134. // 2) if we are re constructing the form from a failed validation or ajax callback
  135. // then use the $form_state['values'] values
  136. if (array_key_exists('values', $form_state) AND isset($form_state['values']['uniquename'])) {
  137. $sname = $form_state['values']['sname'];
  138. $uniquename = $form_state['values']['uniquename'];
  139. $stock_id = $form_state['values']['stock_id'];
  140. $type_id = $form_state['values']['type_id'];
  141. $organism_id = $form_state['values']['organism_id'];
  142. $sdescription = $form_state['values']['stock_description'];
  143. $dbxref_accession = $form_state['values']['accession'];
  144. $dbxref_description = $form_state['values']['db_description'];
  145. $dbxref_database = $form_state['values']['database'];
  146. }
  147. // 3) if we are re building the form from after submission (from ajax call) then
  148. // the values are in the $form_state['input'] array
  149. if (array_key_exists('input', $form_state) and !empty($form_state['input'])) {
  150. $sname = $form_state['input']['sname'];
  151. $uniquename = $form_state['input']['uniquename'];
  152. $stock_id = $form_state['input']['stock_id'];
  153. $type_id = $form_state['input']['type_id'];
  154. $organism_id = $form_state['input']['organism_id'];
  155. $sdescription = $form_state['input']['stock_description'];
  156. $dbxref_accession = $form_state['input']['accession'];
  157. $dbxref_description = $form_state['input']['db_description'];
  158. $dbxref_database = $form_state['input']['database'];
  159. }
  160. $form['sname'] = array(
  161. '#type' => 'textfield',
  162. '#title' => t('Stock Name'),
  163. '#description' => t('Enter a human-readable name for this stock.'),
  164. '#default_value' => $sname,
  165. '#required' => TRUE
  166. );
  167. $form['uniquename'] = array(
  168. '#type' => 'textfield',
  169. '#title' => t('Unique Name'),
  170. '#default_value' => $uniquename,
  171. '#description' => t('Enter a unique name for this stock. This name must be unique for the organism and stock type.'),
  172. '#required' => TRUE
  173. );
  174. if ($stock_id > 0) {
  175. $form['stock_id'] = array(
  176. '#type' => 'hidden',
  177. '#value' => $stock_id,
  178. );
  179. }
  180. // TODO: Should we make this a textfield with an autocomplete field like the
  181. // feature type_id field?.
  182. $st_cv = tripal_get_default_cv("stock", "type_id");
  183. $type_options = tripal_get_cvterm_default_select_options('stock', 'type_id', 'stock types');
  184. $type_options[0] = 'Select a Type';
  185. $st_message = tripal_set_message("To add additional items to the stock type drop down list,
  186. add a term to the " .
  187. l($st_cv->name . " controlled vocabulary",
  188. "admin/tripal/loaders/chado_vocabs/chado_cv/" . $st_cv->cv_id . "/cvterm/add",
  189. array('attributes' => array('target' => '_blank'))
  190. ),
  191. TRIPAL_INFO, array('return_html' => TRUE)
  192. );
  193. $form['type_id'] = array(
  194. '#type' => 'select',
  195. '#title' => t('Type of Stock'),
  196. '#description' => t('Select the stock type.'),
  197. '#options' => $type_options,
  198. '#default_value' => $type_id,
  199. '#required' => TRUE,
  200. '#suffix' => $st_message,
  201. );
  202. // get the list of organisms
  203. $sql = "SELECT * FROM {organism} ORDER BY genus, species";
  204. $org_rset = chado_query($sql);
  205. $organisms = array();
  206. $organisms[''] = '';
  207. while ($organism = $org_rset->fetchObject()) {
  208. $organisms[$organism->organism_id] = "$organism->genus $organism->species ($organism->common_name)";
  209. }
  210. $form['organism_id'] = array(
  211. '#type' => 'select',
  212. '#title' => t('Organism'),
  213. '#default_value' => $organism_id,
  214. '#description' => t('Choose the organism with which this stock is associated.'),
  215. '#options' => $organisms,
  216. '#required' => TRUE
  217. );
  218. $form['stock_description'] = array(
  219. '#type' => 'text_format',
  220. '#title' => t('Notes'),
  221. '#default_value' => $sdescription,
  222. '#description' => t('Briefly enter any notes on the above stock. This should not include phenotypes or genotypes.'),
  223. );
  224. $form['database_reference'] = array(
  225. '#type' => 'fieldset',
  226. '#title' => t('Stock Database Reference'),
  227. '#description' => t('If this site is not the primary location for information
  228. about this stock, please provide the name of the database, the accession
  229. and an optional description using the fields below. If the database
  230. is not present in the list, then please ') .
  231. l(t('add the database '), 'admin/tripal/legacy/tripal_db/add', array('attributes' => array('target' => '_blank'))) .
  232. t('then refresh this page.'),
  233. );
  234. $db_options = tripal_get_db_select_options();
  235. $form['database_reference']['database'] = array(
  236. '#type' => 'select',
  237. '#title' => t('Database'),
  238. '#options' => $db_options,
  239. '#default_value' => $dbxref_database,
  240. '#description' => t('Select the remote database.')
  241. );
  242. $form['database_reference']['accession'] = array(
  243. '#type' => 'textfield',
  244. '#title' => t('Accession'),
  245. '#default_value' => $dbxref_accession,
  246. '#description' => t('Please enter the accession in the remote database for this stock.')
  247. );
  248. $form['database_reference']['db_description'] = array(
  249. '#type' => 'textarea',
  250. '#title' => t('Description of Database Reference'),
  251. '#default_value' => $dbxref_description,
  252. '#description' => t('Optionally enter a description about the database accession.')
  253. );
  254. // PROPERTIES FORM
  255. //---------------------------------------------
  256. $prop_cv = tripal_get_default_cv('stockprop', 'type_id');
  257. $cv_id = $prop_cv ? $prop_cv->cv_id : NULL;
  258. $details = array(
  259. 'property_table' => 'stockprop',
  260. 'chado_id' => $stock_id,
  261. 'cv_id' => $cv_id
  262. );
  263. chado_add_node_form_properties($form, $form_state, $details);
  264. // ADDITIONAL DBXREFS FORM
  265. //---------------------------------------------
  266. $details = array(
  267. 'linking_table' => 'stock_dbxref',
  268. 'base_foreign_key' => 'stock_id',
  269. 'base_key_value' => $stock_id
  270. );
  271. chado_add_node_form_dbxrefs($form, $form_state, $details);
  272. // RELATIONSHIPS FORM
  273. //---------------------------------------------
  274. $relationship_cv = tripal_get_default_cv('stock_relationship', 'type_id');
  275. $cv_id = $relationship_cv ? $relationship_cv->cv_id : NULL;
  276. $details = array(
  277. 'relationship_table' => 'stock_relationship',
  278. 'base_table' => 'stock',
  279. 'base_foreign_key' => 'stock_id',
  280. 'base_key_value' => $stock_id,
  281. 'nodetype' => 'stock',
  282. 'cv_id' => $cv_id
  283. );
  284. chado_add_node_form_relationships($form, $form_state, $details);
  285. return $form;
  286. }
  287. /**
  288. * Implements hook_validate().
  289. * Validate the input from the chado_stock node form
  290. *
  291. * @param $node
  292. * The current node including fields with the form element names and submitted values
  293. * @param $form
  294. * A description of the form to be rendered by drupal_get_form()
  295. *
  296. * @ingroup tripal_legacy_stock
  297. */
  298. function chado_stock_validate(&$node, $form, &$form_state) {
  299. // We only want to validate when the node is saved.
  300. // Since this validate can be called on AJAX and Deletion of the node
  301. // we need to make this check to ensure queries are not executed
  302. // without the proper values.
  303. if(property_exists($node, "op") and $node->op != 'Save') {
  304. return;
  305. }
  306. // we are syncing if we do not have a node ID but we do have a stock_id. We don't
  307. // need to validate during syncing so just skip it.
  308. if (!property_exists($node, 'nid') and property_exists($node, 'stock_id') and $node->stock_id != 0) {
  309. return;
  310. }
  311. // remove surrounding whitespace
  312. $node->uniquename = property_exists($node, 'uniquename') ? trim($node->uniquename) : '';
  313. $node->sname = property_exists($node, 'sname') ? trim($node->sname) : '';
  314. $node->accession = property_exists($node, 'accession') ? trim($node->accession) : '';
  315. $node->db_description = property_exists($node, 'db_description') ? trim($node->db_description) : '';
  316. $int_in_chado_sql = "SELECT count(*) as count FROM {:table} WHERE :column = :value";
  317. $string_in_chado_sql = "SELECT count(*) as count FROM {:table} WHERE :column = :value";
  318. // if this is an update, we want to make sure that a different stock for
  319. // the organism doesn't already have this uniquename. We don't want to give
  320. // two sequences the same uniquename
  321. if (property_exists($node, 'nid') and property_exists($node, 'stock_id')) {
  322. $sql = "
  323. SELECT *
  324. FROM {stock} S
  325. INNER JOIN {cvterm} CVT ON S.type_id = CVT.cvterm_id
  326. WHERE
  327. uniquename = :uname AND organism_id = :organism_id AND
  328. CVT.name = :cvtname AND NOT stock_id = :stock_id
  329. ";
  330. $result = chado_query($sql, array(':uname' => $node->uniquename,
  331. ':organism_id' => $node->organism_id, ':cvtname' => $node->type_id,
  332. ':stock_id' => $node->stock_id))->fetchObject();
  333. if ($result) {
  334. form_set_error('uniquename', t("Stock update cannot proceed. The stock name '$node->uniquename' is not unique for this organism. Please provide a unique name for this stock."));
  335. }
  336. }
  337. // if this is an insert then we just need to make sure this name doesn't
  338. // already exist for this organism if it does then we need to throw an error
  339. elseif (!empty($node->organism_id) AND !empty($node->type_id)) {
  340. $sql = "
  341. SELECT *
  342. FROM {stock} S
  343. INNER JOIN {cvterm} CVT ON S.type_id = CVT.cvterm_id
  344. WHERE uniquename = :uname AND organism_id = :organism_id AND CVT.name = :cvtname";
  345. $result = chado_query($sql, array(':uname' => $node->uniquename,
  346. ':organism_id' => $node->organism_id, ':cvtname' => $node->type_id))->fetchObject();
  347. if ($result) {
  348. form_set_error('uniquename', t("Stock insert cannot proceed. The stock name '$node->uniquename' already exists for this organism. Please provide a unique name for this stock."));
  349. }
  350. }
  351. // Check Type of Stock is valid cvterm_id in chado ( $form['values']['details']['type_id'] )
  352. if ($node->type_id == 0) {
  353. form_set_error('type_id', 'Please select a type of stock.');
  354. }
  355. else {
  356. $replace = array(':table' => 'cvterm', ':column' => 'cvterm_id');
  357. $new_sql = str_replace(array_keys($replace),$replace,$int_in_chado_sql);
  358. $num_rows = chado_query($new_sql, array(':value' => $node->type_id))->fetchObject();
  359. if ( $num_rows->count != 1) {
  360. form_set_error('type_id', "The type you selected is not valid. Please choose another one. (CODE:$num_rows)"); }
  361. }
  362. // Check Source Organism is valid organism_id in chado ( $form['values']['details']['organism_id'] )
  363. if ( $node->organism_id == 0) {
  364. form_set_error('organism_id', 'Please select a source organism for this stock');
  365. }
  366. else {
  367. $replace = array(':table' => 'organism', ':column' => 'organism_id');
  368. $new_sql = str_replace(array_keys($replace),$replace,$int_in_chado_sql);
  369. $num_rows = chado_query($new_sql, array(':value' => $node->organism_id))->fetchObject();
  370. if ( $num_rows->count != 1 ) {
  371. form_set_error('organism_id', "The organism you selected is not valid. Please choose another one. (CODE:$num_rows)"); }
  372. }
  373. // Check if Accession also database
  374. if ($node->accession != '') {
  375. if ($node->database == 0) {
  376. // there is an accession but no database selected
  377. form_set_error('database', 'You need to enter both a database and an accession for that database in order to add a database reference.');
  378. }
  379. }
  380. else {
  381. if ($node->database > 0) {
  382. // there is a database selected but no accession
  383. form_set_error('accession', 'You need to enter both a database and an accession for that database in order to add a database reference.');
  384. }
  385. }
  386. // Check database is valid db_id in chado ( $form['values']['database_reference']['database'] )
  387. if ( $node->database > 0) {
  388. $replace = array(':table' => 'db', ':column' => 'db_id');
  389. $new_sql = str_replace(array_keys($replace),$replace,$int_in_chado_sql);
  390. $num_rows = chado_query($new_sql, array(':value' => $node->database))->fetchObject();
  391. if ($num_rows->count != 1) {
  392. form_set_error('database', 'The database you selected is not valid. Please choose another one.'); }
  393. }
  394. }
  395. /**
  396. * Implements hook_insert().
  397. * Inserts data from chado_stock_form() into drupal and chado
  398. *
  399. * @param $node
  400. * The current node including fields with the form element names and submitted values
  401. *
  402. * @return
  403. * TRUE if the node was successfully inserted into drupal/chado; FALSE otherwise
  404. *
  405. * @ingroup tripal_legacy_stock
  406. */
  407. function chado_stock_insert($node) {
  408. $stock_id = '';
  409. // if there is an stock_id in the $node object then this must be a sync so
  410. // we can skip adding the stock to chado as it is already there, although
  411. // we do need to proceed with insertion into the chado/drupal linking table.
  412. if (!property_exists($node, 'stock_id')) {
  413. $node->uniquename = trim($node->uniquename);
  414. $node->sname = trim($node->sname);
  415. $node->accession = trim($node->accession);
  416. $node->stock_description = trim($node->stock_description['value']);
  417. // before we can add the stock, we must add the dbxref if one has been
  418. // provided by the user.
  419. $dbxref = NULL;
  420. if (!empty($node->accession) and !empty($node->database)) {
  421. $values = array(
  422. 'db_id' => $node->database,
  423. 'accession' => $node->accession,
  424. );
  425. if (!chado_select_record('dbxref', array('dbxref_id'), $values)) {
  426. $values['description'] = $node->db_description;
  427. $values['version'] = '1';
  428. $dbxref = chado_insert_record('dbxref', $values);
  429. if (!$dbxref) {
  430. drupal_set_message(t('Unable to add database reference to this stock.'), 'warning');
  431. tripal_report_error('tripal_stock', TRIPAL_WARNING,
  432. 'Insert Stock: Unable to create dbxref where values:%values',
  433. array('%values' => print_r($values, TRUE)));
  434. }
  435. }
  436. }
  437. // create stock including the dbxref
  438. $stock = '';
  439. $values = array(
  440. 'organism_id' => $node->organism_id,
  441. 'name' => $node->sname,
  442. 'uniquename' => $node->uniquename,
  443. 'description' => $node->stock_description,
  444. 'type_id' => $node->type_id
  445. );
  446. if ($dbxref) {
  447. $values['dbxref_id'] = array(
  448. 'db_id' => $node->database,
  449. 'accession' => $node->accession
  450. );
  451. }
  452. $stock = chado_insert_record('stock', $values);
  453. if (!$stock) {
  454. drupal_set_message(t('Unable to add stock.'), 'warning');
  455. tripal_report_error('tripal_stock', TRIPAL_WARNING, 'Insert stock: Unable to create stock where values: %values',
  456. array('%values' => print_r($values, TRUE)));
  457. return;
  458. }
  459. $stock_id = $stock['stock_id'];
  460. // Now add properties
  461. $details = array(
  462. 'property_table' => 'stockprop',
  463. 'base_table' => 'stock',
  464. 'foreignkey_name' => 'stock_id',
  465. 'foreignkey_value' => $stock_id
  466. );
  467. chado_update_node_form_properties($node, $details);
  468. // Now add the additional references
  469. $details = array(
  470. 'linking_table' => 'stock_dbxref',
  471. 'foreignkey_name' => 'stock_id',
  472. 'foreignkey_value' => $stock_id
  473. );
  474. chado_update_node_form_dbxrefs($node, $details);
  475. // Now add in relationships
  476. $details = array(
  477. 'relationship_table' => 'stock_relationship',
  478. 'foreignkey_value' => $stock_id
  479. );
  480. chado_update_node_form_relationships($node, $details);
  481. }
  482. else {
  483. $stock_id = $node->stock_id;
  484. }
  485. // Make sure the entry for this stock doesn't already exist in the
  486. // chado_stock table if it doesn't exist then we want to add it.
  487. $check_org_id = chado_get_id_from_nid('stock', $node->nid);
  488. if (!$check_org_id) {
  489. $record = new stdClass();
  490. $record->nid = $node->nid;
  491. $record->vid = $node->vid;
  492. $record->stock_id = $stock_id;
  493. drupal_write_record('chado_stock', $record);
  494. }
  495. }
  496. /**
  497. * Implements hook_update().
  498. * Handles Editing/Updating of main stock info
  499. *
  500. * NOTE: Currently just writes over all old data
  501. *
  502. * @param $node
  503. * The current node including fields with the form element names and submitted values
  504. *
  505. * @return
  506. * TRUE if the node was successfully updated in drupal/chado; FALSE otherwise
  507. *
  508. * @ingroup tripal_legacy_stock
  509. */
  510. function chado_stock_update($node) {
  511. $node->uniquename = trim($node->uniquename);
  512. $node->sname = trim($node->sname);
  513. $node->stock_description = trim($node->stock_description['value']);
  514. if ($node->revision) {
  515. // there is no way to handle revisions in Chado but leave
  516. // this here just to make not we've addressed it.
  517. }
  518. //update dbxref
  519. $dbxref_status = NULL;
  520. $dbxref_present = FALSE;
  521. if ($node->database) {
  522. $dbxref_present = TRUE;
  523. if ($node->accession) {
  524. $dbxref_mode = '';
  525. $stock = chado_select_record(
  526. 'stock',
  527. array('dbxref_id', 'type_id'),
  528. array('stock_id' => $node->stock_id)
  529. );
  530. if ($stock[0]->dbxref_id) {
  531. $values = array(
  532. 'db_id' => $node->database,
  533. 'accession' => $node->accession,
  534. 'description' => $node->db_description
  535. );
  536. $dbxref_status = chado_update_record(
  537. 'dbxref',
  538. array('dbxref_id' => $stock[0]->dbxref_id),
  539. $values
  540. );
  541. $dbxref_mode = 'Update';
  542. }
  543. else {
  544. if ($stock[0]->type_id) {
  545. //create the dbxref
  546. //used the type_id as a control to check we have a stock but not a dbxref
  547. $values = array(
  548. 'db_id' => $node->database,
  549. 'accession' => $node->accession,
  550. 'description' => $node->db_description,
  551. 'version' => '1',
  552. );
  553. $dbxref_status = chado_insert_record(
  554. 'dbxref',
  555. $values
  556. );
  557. $dbxref_mode = 'Create';
  558. }
  559. else {
  560. drupal_set_message(t('Unable to find stock to Update'), 'error');
  561. tripal_report_error('tripal_stock', TRIPAL_ERROR,
  562. 'Stock Update: Unable to find stock to update using values: %values',
  563. array('%values', print_r($values, TRUE))
  564. );
  565. return FALSE;
  566. }
  567. }
  568. }
  569. if (!$dbxref_status) {
  570. tripal_report_error('tripal_stock', TRIPAL_WARNING,
  571. 'Stock Update: Unable to %mode main stock dbxref with values: %values',
  572. array('%values' => print_r($values, TRUE), '%mode' => $dbxref_mode));
  573. }
  574. }
  575. //can't change stock id which is all thats stored in drupal thus only update chado
  576. $update_values = array(
  577. 'organism_id' => $node->organism_id,
  578. 'name' => $node->sname,
  579. 'uniquename' => $node->uniquename,
  580. 'description' => $node->stock_description,
  581. 'type_id' => $node->type_id,
  582. );
  583. if ($dbxref_present) {
  584. if ($dbxref_status) {
  585. $update_values['dbxref_id'] = array(
  586. 'db_id' => $node->database,
  587. 'accession' => $node->accession
  588. );
  589. }
  590. }
  591. $status = chado_update_record('stock', array('stock_id' => $node->stock_id), $update_values);
  592. if (!$status) {
  593. drupal_set_message(t('Unable to update stock'), 'error');
  594. tripal_report_error('tripal_stock', TRIPAL_ERROR,
  595. 'Stock Update: Unable to update stock using match values: %mvalues and update values: %uvalues',
  596. array('%mvalues' => print_r(array('stock_id' => $node->stock_id), TRUE), '%uvalues' => print_r($update_values, TRUE))
  597. );
  598. }
  599. else {
  600. // set the URL for this stock page
  601. $values = array('stock_id' => $node->stock_id);
  602. $stock = chado_select_record('stock', array('*'), $values);
  603. }
  604. // now update the properties
  605. if ($node->stock_id > 0) {
  606. $details = array(
  607. 'property_table' => 'stockprop',
  608. 'base_table' => 'stock',
  609. 'foreignkey_name' => 'stock_id',
  610. 'foreignkey_value' => $node->stock_id
  611. );
  612. chado_update_node_form_properties($node, $details);
  613. }
  614. // now update the additional dbxrefs
  615. if ($node->stock_id > 0) {
  616. $details = array(
  617. 'linking_table' => 'stock_dbxref',
  618. 'foreignkey_name' => 'stock_id',
  619. 'foreignkey_value' => $node->stock_id
  620. );
  621. chado_update_node_form_dbxrefs($node, $details);
  622. }
  623. // now update relationships
  624. if ($node->stock_id > 0) {
  625. $details = array(
  626. 'relationship_table' => 'stock_relationship',
  627. 'foreignkey_value' => $node->stock_id
  628. );
  629. chado_update_node_form_relationships($node, $details);
  630. }
  631. }
  632. /**
  633. * Implements hook_delete().
  634. * Handles deleting of chado_stocks
  635. *
  636. * NOTE: Currently deletes data -no undo or record-keeping functionality
  637. *
  638. * @param $node
  639. * The current node including fields with the form element names and submitted values
  640. *
  641. * @return
  642. * TRUE if the node was successfully deleted from drupal/chado; FALSE otherwise
  643. *
  644. * @ingroup tripal_legacy_stock
  645. */
  646. function chado_stock_delete($node) {
  647. // Set stock in chado: is_obsolete = TRUE
  648. chado_query("DELETE FROM {stock} WHERE stock_id = :stock_id", array(':stock_id' => $node->stock->stock_id));
  649. //remove drupal node and all revisions
  650. db_query("DELETE FROM {chado_stock} WHERE nid = :nid", array(':nid' => $node->nid));
  651. }
  652. /**
  653. * Used by Tripal Chado Node API during sync'ing of nodes
  654. *
  655. * @ingroup tripal_legacy_stock
  656. */
  657. function chado_stock_chado_node_sync_create_new_node($new_node, $record) {
  658. $new_node->organism_id = $record->organism_id;
  659. $new_node->sname = $record->name;
  660. $new_node->uniquename = $record->uniquename;
  661. $new_node->type_id = $record->type_id;
  662. return $new_node;
  663. }
  664. /**
  665. * Implements hook_node_presave(). Acts on all content types.
  666. *
  667. * @ingroup tripal_legacy_stock
  668. */
  669. function tripal_stock_node_presave($node) {
  670. switch ($node->type) {
  671. // This step is for setting the title for the Drupal node. This title
  672. // is permanent and thus is created to be unique. Title changes provided
  673. // by tokens are generated on the fly dynamically, but the node title
  674. // seen in the content listing needs to be set here. Do not call
  675. // the chado_get_node_title() function here to set the title as the node
  676. // object isn't properly filled out and the function will fail.
  677. case 'chado_stock':
  678. // For a form submission the fields are part of the node object
  679. // but for a sync the fields are in an object of the node.
  680. $organism_id = null;
  681. $sname = '';
  682. $uniquename = '';
  683. $type = '';
  684. if(property_exists($node, 'organism_id')) {
  685. $organism_id = $node->organism_id;
  686. $sname = $node->sname;
  687. $uniquename = $node->uniquename;
  688. $type_id = $node->type_id;
  689. $values = array('cvterm_id' => $node->type_id);
  690. $cvterm = chado_select_record('cvterm', array('name'), $values);
  691. $type = $cvterm[0]->name;
  692. }
  693. else if (property_exists($node, 'stock')) {
  694. $organism_id = $node->stock->organism_id;
  695. $sname = $node->stock->name;
  696. $uniquename = $node->stock->uniquename;
  697. $type = $node->stock->type_id->name;
  698. }
  699. $values = array('organism_id' => $organism_id);
  700. $organism = chado_select_record('organism', array('genus','species'), $values);
  701. $node->title = "$sname, $uniquename ($type) " . $organism[0]->genus . ' ' . $organism[0]->species;
  702. break;
  703. }
  704. }
  705. /**
  706. * Implements hook_node_view(). Acts on all content types.
  707. *
  708. * @ingroup tripal_legacy_stock
  709. */
  710. function tripal_stock_node_view($node, $view_mode, $langcode) {
  711. switch ($node->type) {
  712. case 'chado_stock':
  713. if ($view_mode == 'full') {
  714. $node->content['tripal_stock_base'] = array(
  715. '#theme' => 'tripal_stock_base',
  716. '#node' => $node,
  717. '#tripal_toc_id' => 'base',
  718. '#tripal_toc_title' => 'Overview',
  719. '#weight' => -100,
  720. );
  721. $node->content['tripal_stock_collections'] = array(
  722. '#theme' => 'tripal_stock_collections',
  723. '#node' => $node,
  724. '#tripal_toc_id' => 'collections',
  725. '#tripal_toc_title' => 'Stock Collections',
  726. );
  727. $node->content['tripal_stock_properties'] = array(
  728. '#theme' => 'tripal_stock_properties',
  729. '#node' => $node,
  730. '#tripal_toc_id' => 'properties',
  731. '#tripal_toc_title' => 'Properties',
  732. );
  733. $node->content['tripal_stock_references'] = array(
  734. '#theme' => 'tripal_stock_references',
  735. '#node' => $node,
  736. '#tripal_toc_id' => 'references',
  737. '#tripal_toc_title' => 'Cross References',
  738. );
  739. $node->content['tripal_stock_relationships'] = array(
  740. '#theme' => 'tripal_stock_relationships',
  741. '#node' => $node,
  742. '#tripal_toc_id' => 'relationships',
  743. '#tripal_toc_title' => 'Relationships',
  744. );
  745. $node->content['tripal_stock_synonyms'] = array(
  746. '#theme' => 'tripal_stock_synonyms',
  747. '#node' => $node,
  748. '#tripal_toc_id' => 'synonyms',
  749. '#tripal_toc_title' => 'Synonyms',
  750. );
  751. $node->content['tripal_stock_publications'] = array(
  752. '#theme' => 'tripal_stock_publications',
  753. '#node' => $node,
  754. '#tripal_toc_id' => 'publications',
  755. '#tripal_toc_title' => 'Publications',
  756. );
  757. }
  758. if ($view_mode == 'teaser') {
  759. $node->content['tripal_stock_teaser'] = array(
  760. '#theme' => 'tripal_stock_teaser',
  761. '#node' => $node,
  762. );
  763. }
  764. break;
  765. case 'chado_organism':
  766. if ($view_mode == 'full') {
  767. $node->content['tripal_organism_stocks'] = array(
  768. '#theme' => 'tripal_organism_stocks',
  769. '#node' => $node,
  770. '#tripal_toc_id' => 'stocks',
  771. '#tripal_toc_title' => 'Stocks',
  772. );
  773. }
  774. break;
  775. }
  776. }
  777. /**
  778. * Implements hook_node_insert().
  779. * Acts on all content types.
  780. *
  781. * @ingroup tripal_legacy_stock
  782. */
  783. function tripal_stock_node_insert($node) {
  784. // set the URL path after inserting. We do it here because we do not
  785. // know the stock_id in the presave
  786. switch ($node->type) {
  787. case 'chado_stock':
  788. // We still don't have a fully loaded node object in this hook. Therefore,
  789. // we need to simulate one so that the right values are available for
  790. // the URL to be determined.
  791. $stock_id = chado_get_id_from_nid('stock', $node->nid);
  792. $stock = chado_generate_var('stock', array('stock_id' => $stock_id));
  793. $stock = chado_expand_var($stock, 'field', 'stock.uniquename');
  794. $stock = chado_expand_var($stock, 'field', 'stock.description');
  795. $node->stock = $stock;
  796. // Set the Title.
  797. $node->title = chado_get_node_title($node);
  798. // Now use the API to set the path.
  799. chado_set_node_url($node);
  800. break;
  801. }
  802. }
  803. /**
  804. * Implements hook_node_update().
  805. * Acts on all content types.
  806. *
  807. * @ingroup tripal_legacy_stock
  808. */
  809. function tripal_stock_node_update($node) {
  810. // add items to other nodes, build index and search results
  811. switch ($node->type) {
  812. case 'chado_stock':
  813. // Set the Title.
  814. $node->title = chado_get_node_title($node);
  815. // Now use the API to set the path.
  816. chado_set_node_url($node);
  817. break;
  818. }
  819. }
  820. /**
  821. * Implements [content_type]_chado_node_default_title_format().
  822. *
  823. * Defines a default title format for the Chado Node API to set the titles on
  824. * Chado Stock nodes based on chado fields.
  825. */
  826. function chado_stock_chado_node_default_title_format() {
  827. return '[stock.name], [stock.uniquename] ([stock.type_id>cvterm.name]) [stock.organism_id>organism.genus] [stock.organism_id>organism.species]';
  828. }
  829. /**
  830. * Implements hook_chado_node_default_url_format().
  831. *
  832. * Designates a default URL format for stock nodes.
  833. */
  834. function chado_stock_chado_node_default_url_format() {
  835. return '/stock/[stock.organism_id>organism.genus]/[stock.organism_id>organism.species]/[stock.type_id>cvterm.name]/[stock.uniquename]';
  836. }
  837. /**
  838. * Implement hook_node_access().
  839. *
  840. * This hook allows node modules to limit access to the node types they define.
  841. *
  842. * @param $node
  843. * The node on which the operation is to be performed, or, if it does not yet exist, the
  844. * type of node to be created
  845. *
  846. * @param $op
  847. * The operation to be performed
  848. *
  849. * @param $account
  850. * A user object representing the user for whom the operation is to be performed
  851. *
  852. * @return
  853. * If the permission for the specified operation is not set then return FALSE. If the
  854. * permission is set then return NULL as this allows other modules to disable
  855. * access. The only exception is when the $op == 'create'. We will always
  856. * return TRUE if the permission is set.
  857. *
  858. * @ingroup tripal_legacy_stock
  859. */
  860. function tripal_stock_node_access($node, $op, $account) {
  861. $node_type = $node;
  862. if (is_object($node)) {
  863. $node_type = $node->type;
  864. }
  865. if($node_type == 'chado_stock') {
  866. if ($op == 'create') {
  867. if (!user_access('create chado_stock content', $account)) {
  868. return NODE_ACCESS_DENY;
  869. }
  870. return NODE_ACCESS_ALLOW;
  871. }
  872. if ($op == 'update') {
  873. if (!user_access('edit chado_stock content', $account)) {
  874. return NODE_ACCESS_DENY;
  875. }
  876. }
  877. if ($op == 'delete') {
  878. if (!user_access('delete chado_stock content', $account)) {
  879. return NODE_ACCESS_DENY;
  880. }
  881. }
  882. if ($op == 'view') {
  883. if (!user_access('access chado_stock content', $account)) {
  884. return NODE_ACCESS_DENY;
  885. }
  886. }
  887. return NODE_ACCESS_IGNORE;
  888. }
  889. }