tripal_core.chado_nodes.dbxrefs.api.inc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. <?php
  2. /**
  3. * @file
  4. * API to manage the chado _dbxref table for various Tripal Node Types
  5. *
  6. * How To Use:
  7. * @code
  8. function chado_example_form($form, &$form_state) {
  9. // Default values for form elements can come in the following ways:
  10. //
  11. // 1) as elements of the $node object. This occurs when editing an existing node
  12. // 2) in the $form_state['values'] array which occurs on a failed validation or
  13. // ajax callbacks when the ajax call originates from non-submit fields other
  14. // than button
  15. // 3) in the $form_state['input'] array which occurs on ajax callbacks from submit
  16. // form elements (e.g. buttons) and the form is being rebuilt but has not yet
  17. // been validated
  18. //
  19. // The reference elements added by this function do use AJAX calls from buttons,
  20. // therefore, it is important to check for form values in the $form_state['values']
  21. // for case #2 above, and in the $form_state['input'] for case #3.
  22. // See the chado analysis node form for an example.
  23. // Next, add in all the form array definition particular to your node type
  24. // To add in the additional database reference form elements, you first need to prepare the arguments
  25. // for the function call.
  26. $details = array(
  27. 'linking_table' => 'example_dbxref', // the name of the table linking additional dbxrefs to this node
  28. 'base_foreign_key' => 'example_id', // key to link to the chado content created by this node
  29. 'base_key_value' => $example_id, // the value of the above key
  30. 'fieldset_title' => 'Additional References', // the non-translated title for this fieldset
  31. 'additional_instructions' => '' // a non-stranslated string providing additional instructions
  32. );
  33. // Finally, and add the additional form elements to the form
  34. chado_add_node_form_dbxrefs($form, $form_state, $details);
  35. return $form;
  36. }
  37. function chado_example_insert($node) {
  38. // if there is an example_id in the $node object then this must be a sync so
  39. // we can skip adding the chado_example as it is already there, although
  40. // we do need to proceed with the rest of the insert
  41. if (!property_exists($node, 'example_id')) {
  42. // Add record to chado example table
  43. // Add to any other tables needed
  44. // Add all additional database references
  45. // This function will create new database references as needed and select existing ones.
  46. // Existing _dbxref links will be cleared and then re-added
  47. chado_update_node_form_dbxrefs(
  48. $node, // the node object passed in via hook_insert()
  49. 'example_dbxref', // the name of the _dbxref linking table
  50. 'example_id', // key to link to the chado content created by this node
  51. $node->example_id // value of the above key
  52. );
  53. }
  54. // Add record to chado_example linking example_id to new node
  55. }
  56. function chado_example_update($node) {
  57. // Update record in chado example table
  58. // Update any other tables needed
  59. // Update all additional database references
  60. // This function will create new database references as needed and select existing ones.
  61. // Existing _dbxref links will be cleared and then re-added
  62. chado_update_node_form_dbxrefs(
  63. $node, // the node object passed in via hook_insert()
  64. 'example_dbxref', // the name of the _dbxref linking table
  65. 'example_id', // key to link to the chado content created by this node
  66. $node->example_id // value of the above key
  67. );
  68. // Don't need to update chado_example linking table since niether example_id or nid can be changed in update
  69. }
  70. * @endcode
  71. *
  72. * @ingroup tripal_chado_node_api
  73. */
  74. /**
  75. * @section
  76. * Additional Database References Form to be added to node forms
  77. */
  78. /**
  79. * Provides a form for adding to BASE_dbxref and dbxref tables
  80. *
  81. * @param $form
  82. * The Drupal form array into which the dbxref elements will be added
  83. * @param $form_state
  84. * The corresponding form_state array for the form
  85. * @param $details
  86. * An array defining details needed by this form. Required Keys are:
  87. * - linking_table: the name of the dbxref linking table (ie: feature_dbxref)
  88. * - base_foreign_key: the name of the foreign key linking this table to the non-dbxref table (ie: feature_id)
  89. * - base_key_value: the value of the base_foreign_key for the current form (ie: 999 if the feature_id=999)
  90. * Optional keys include:
  91. * - fieldset_title: the non-translated title for this fieldset
  92. * - additional_instructions: a non-translated string providing additional instructions
  93. * - select_options: must be an array where the [key] is a valid db_id and
  94. * the [value] is the human-readable name of the option. This includes all databases
  95. * in the chado db table by default
  96. *
  97. * @ingroup tripal_chado_node_api
  98. */
  99. function chado_add_node_form_dbxrefs(&$form, &$form_state, $details) {
  100. // Set defaults for optional fields
  101. $details['fieldset_title'] = 'External References';
  102. $details['additional_instructions'] = '';
  103. // Get the list of databases to display in the dropdown.
  104. if (isset($details['select_options'])) {
  105. // the callee has provided a list
  106. $db_options = $details['select_options'];
  107. }
  108. else {
  109. // get the list of databases from the db table
  110. $db_options = array(0 => 'Select a Database');
  111. $options = array('order_by' => array('name' => 'ASC'));
  112. $select = chado_select_record('db', array('db_id','name'), array(), $options);
  113. foreach($select as $db) {
  114. $db_options[$db->db_id] = $db->name;
  115. }
  116. }
  117. // Determine the node type using the name of the foreign key.
  118. $details['nodetype'] = str_replace('_id', '', $details['base_foreign_key']);
  119. // Tell tripal administrators how to add terms to the property types drop down.
  120. $importance = (empty($db_options)) ? TRIPAL_WARNING : TRIPAL_INFO;
  121. $tripal_message = tripal_set_message(
  122. t('To add databases to the drop down list, you need to <a href="@dblink">add
  123. an external database reference</a>.',
  124. array(
  125. '@dblink' => url('admin/tripal/chado/tripal_db/add')
  126. )
  127. ),
  128. $importance,
  129. array('return_html' => TRUE)
  130. );
  131. // Group all of the chado node api fieldsets into vertical tabs.
  132. $form['chado_node_api'] = array(
  133. '#type' => 'vertical_tabs',
  134. '#attached' => array(
  135. 'css' => array(
  136. 'chado-node-api' => drupal_get_path('module', 'tripal_core') . '/theme/css/chado_node_api.css',
  137. ),
  138. ),
  139. );
  140. // the fieldset of the dbxref elements
  141. $instructions = 'To add an external reference, select the database you want to reference from the
  142. drop-down below. Then enter the name/accession (as it is shown in the external database) of this
  143. particular %nodetype into the text box before clicking "Add". The version can be used to
  144. indicate the version of the external database or the version of the reference
  145. depending upon what is available. To remove incorrect references, click the
  146. "Remove" button. Note: you cannot edit previously added references but instead
  147. need to remove and re-add them.';
  148. $form['addtl_dbxrefs'] = array(
  149. '#type' => 'fieldset',
  150. '#title' => t($details['fieldset_title']),
  151. '#description' => t('<p><strong>Indicate that this %nodetype either originates from
  152. or is present in another database.</strong></p><p>'. $instructions . $details['additional_instructions'] . '</p>',
  153. array('%nodetype' => $details['nodetype'])),
  154. '#collapsible' => TRUE,
  155. '#collapsed' => TRUE,
  156. '#group' => 'chado_node_api',
  157. '#weight' => 9,
  158. '#attributes' => array('class' => array('chado-node-api','dbxrefs')),
  159. '#attached' => array(
  160. 'js' => array(
  161. 'chado-node-api-vertical-tabs' => drupal_get_path('module', 'tripal_core') . '/theme/js/chadoNodeApi_updateVerticalTabSummary.js',
  162. ),
  163. ),
  164. );
  165. // this form element is a tree, so that we don't puke all of the values into then node variable
  166. // it is set as a tree, and keeps them in the $form_state['values']['dbxref_table'] heading.
  167. $form['addtl_dbxrefs']['dbxref_table'] = array(
  168. '#type' => 'markup',
  169. '#tree' => TRUE,
  170. '#prefix' => '<div id="tripal-generic-edit-addtl_dbxrefs-table">',
  171. '#suffix' => '</div>',
  172. '#theme' => 'chado_node_additional_dbxrefs_form_table'
  173. );
  174. /* DBxrefs can come to us in two ways:
  175. *
  176. * 1) In the form state in the $form_state['chado_additional_dbxrefs']. Data is in this field
  177. * when an AJAX call updates the form state or a validation error.
  178. *
  179. * 2) Directly from the database if the record already has dbxref's associated. This
  180. * data is only used the first time the form is loaded. On AJAX calls or validation
  181. * errors the fields on the form are populated from the $form_state['chado_additional_dbxrefs']
  182. * entry.
  183. */
  184. if (isset($form_state['chado_additional_dbxrefs'])) {
  185. $existing_dbxrefs = $form_state['chado_additional_dbxrefs'];
  186. }
  187. else {
  188. $existing_dbxrefs = chado_query(
  189. "SELECT
  190. db.name as db_name,
  191. db.db_id as db_id,
  192. dbxref.dbxref_id,
  193. dbxref.accession as accession,
  194. dbxref.description as description,
  195. dbxref.version
  196. FROM {dbxref} dbxref
  197. LEFT JOIN {db} db ON db.db_id = dbxref.db_id
  198. LEFT JOIN {".$details['linking_table']."} linking_table ON linking_table.dbxref_id = dbxref.dbxref_id
  199. WHERE linking_table.".$details['base_foreign_key']."= :base_key_value
  200. ORDER BY db.name ASC, dbxref.version ASC",
  201. array(':base_key_value' => $details['base_key_value'])
  202. );
  203. }
  204. /* The format of the $existing_dbxref's array is either:
  205. *
  206. * From the chado_additional_dbxrefs array:
  207. * $form_state['chado_additional_dbxrefs'] = array(
  208. * '[db_id]-[version]' => array(
  209. * 'db_id' => [the db.db_id value]
  210. * 'db_name' => [the db.name value]
  211. * 'dbxref_id' => [the dbxref.dbxref_id value, or temporary value if it doesn't yet exists],
  212. * 'version' => [the dbxref.version value],
  213. * 'accession' => [the dbxref.accession value],
  214. * ),
  215. * );
  216. *
  217. * OR
  218. * Populated from the database:
  219. * $existing_dbxref = array(
  220. * 0 => array(
  221. * 'dbxref_id' => [the dbxref.dbxref_id value],
  222. * 'db_name' => [the db.name value],
  223. * 'db_id' => [the db.db_id value],
  224. * 'accession' => [the dbxref.accession value],
  225. * 'description' => [the dbxref.description value],
  226. * 'version' => [the dbxref.versiion value],
  227. * ),
  228. * );
  229. *
  230. * NOTE: The main difference is the key
  231. *
  232. * Loop on the array elements of the $existing_dbxrefs array and add
  233. * an element to the form for each one.
  234. */
  235. $num_dbxrefs = 0;
  236. foreach ($existing_dbxrefs as $dbxref) {
  237. if (array_key_exists($dbxref->db_id, $db_options)) {
  238. $num_dbxrefs++;
  239. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id]['#type'] = 'markup';
  240. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id]['#value'] = '';
  241. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['#type'] = 'markup';
  242. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['#value'] = '';
  243. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['#attributes'] = array(
  244. 'class' => array('dbxref', 'saved')
  245. );
  246. // Determine whether this dbxref is unsaved or not.
  247. // We can tell this by looking at the dbxref_id: if it's not
  248. // saved yet we will have entered a TEMP###.
  249. if (preg_match('/^TEMP/', $dbxref->dbxref_id)) {
  250. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['#attributes'] = array(
  251. 'class' => array('dbxref', 'unsaved')
  252. );
  253. }
  254. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['db_id'] = array(
  255. '#type' => 'hidden',
  256. '#value' => $dbxref->db_id
  257. );
  258. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['accession'] = array(
  259. '#type' => 'hidden',
  260. '#value' => $dbxref->accession
  261. );
  262. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['version'] = array(
  263. '#type' => 'hidden',
  264. '#value' => $dbxref->version,
  265. );
  266. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['dbxref_id'] = array(
  267. '#type' => 'hidden',
  268. '#value' => $dbxref->dbxref_id
  269. );
  270. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['db'] = array(
  271. '#type' => 'markup',
  272. '#markup' => $dbxref->db_name
  273. );
  274. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['dbxref_version'] = array(
  275. '#type' => 'markup',
  276. '#markup' => $dbxref->version,
  277. );
  278. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['dbxref_accession'] = array(
  279. '#type' => 'markup',
  280. '#markup' => $dbxref->accession
  281. );
  282. // remove button
  283. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['dbxref_action'] = array(
  284. '#type' => 'submit',
  285. '#value' => t('Remove'),
  286. '#name' => "dbxrefs_remove-".$dbxref->db_id.'-'.$dbxref->dbxref_id,
  287. '#ajax' => array(
  288. 'callback' => "chado_add_node_form_subtable_ajax_update",
  289. 'wrapper' => 'tripal-generic-edit-addtl_dbxrefs-table',
  290. 'effect' => 'fade',
  291. 'method' => 'replace',
  292. 'prevent' => 'click'
  293. ),
  294. // When this button is clicked, the form will be validated and submitted.
  295. // Therefore, we set custom submit and validate functions to override the
  296. // default node form submit. In the validate function we validate only the
  297. // additional dbxref fields and in the submit we remove the indicated dbxref
  298. // from the chado_additional_dbxrefs array. In order to keep validate errors
  299. // from the node form validate and Drupal required errors for non-dbxref fields
  300. // preventing the user from removing dbxrefs we set the #limit_validation_errors below
  301. '#validate' => array('chado_add_node_form_subtables_remove_button_validate'),
  302. '#submit' => array('chado_add_node_form_subtables_remove_button_submit'),
  303. // Limit the validation of the form upon clicking this button to the dbxref_table tree
  304. // No other fields will be validated (ie: no fields from the main form or any other api
  305. // added form).
  306. '#limit_validation_errors' => array(
  307. array('dbxref_table') // Validate all fields within $form_state['values']['dbxref_table']
  308. )
  309. );
  310. }
  311. }
  312. // Quickly add a hidden field stating how many dbxrefs are currently added.
  313. $form['addtl_dbxrefs']['num_dbxrefs'] = array(
  314. '#type' => 'hidden',
  315. '#value' => $num_dbxrefs,
  316. '#attributes' => array('class' => 'num-dbxrefs')
  317. );
  318. // Form elements for adding a new dbxref
  319. //---------------------------------------------
  320. $form['addtl_dbxrefs']['dbxref_table']['new'] = array(
  321. '#type' => 'markup',
  322. '#prefix' => '<span class="addtl-dbxrefs-add-new-dbxref">',
  323. '#suffix' => '</span>'
  324. );
  325. // add in the existing databases
  326. $form['addtl_dbxrefs']['dbxref_table']['new']['db'] = array(
  327. '#type' => 'select',
  328. '#options' => $db_options,
  329. );
  330. $form['addtl_dbxrefs']['dbxref_table']['new']['dbxref_accession'] = array(
  331. '#type' => 'textfield',
  332. );
  333. $form['addtl_dbxrefs']['dbxref_table']['new']['dbxref_version'] = array(
  334. '#type' => 'textfield',
  335. '#size' => 10,
  336. );
  337. // add button
  338. $form['addtl_dbxrefs']['dbxref_table']['new']['dbxref_action'] = array(
  339. '#type' => 'submit',
  340. '#value' => t('Add'),
  341. '#name' => "dbxrefs-add",
  342. '#ajax' => array(
  343. 'callback' => "chado_add_node_form_subtable_ajax_update",
  344. 'wrapper' => 'tripal-generic-edit-addtl_dbxrefs-table',
  345. 'effect' => 'fade',
  346. 'method' => 'replace',
  347. 'prevent' => 'click'
  348. ),
  349. // When this button is clicked, the form will be validated and submitted.
  350. // Therefore, we set custom submit and validate functions to override the
  351. // default node form submit. In the validate function we validate only the
  352. // additional dbxref fields and in the submit we add them to the chado_additional_dbxrefs
  353. // array. In order to keep validate errors from the node form validate and Drupal
  354. // required errors for non-dbxref fields preventing the user from adding dbxrefs we
  355. // set the #limit_validation_errors below
  356. '#validate' => array('chado_add_node_form_subtables_add_button_validate'),
  357. '#submit' => array('chado_add_node_form_subtables_add_button_submit'),
  358. // Limit the validation of the form upon clicking this button to the dbxref_table tree
  359. // No other fields will be validated (ie: no fields from the main form or any other api
  360. // added form).
  361. '#limit_validation_errors' => array(
  362. array('dbxref_table') // Validate all fields within $form_state['values']['dbxref_table']
  363. )
  364. );
  365. $form['addtl_dbxrefs']['admin_message'] = array(
  366. '#type' => 'markup',
  367. '#markup' => $tripal_message
  368. );
  369. }
  370. /**
  371. * Validate the user input for creating a new dbxref
  372. * Called by the add button in chado_add_node_form_dbxrefs
  373. *
  374. * @ingroup tripal_core
  375. */
  376. function chado_add_node_form_dbxrefs_add_button_validate($form, &$form_state) {
  377. // Ensure the db_id is supplied & Valid
  378. $db = chado_select_record(
  379. 'db',
  380. array('db_id', 'name'),
  381. array('db_id' => $form_state['values']['dbxref_table']['new']['db'])
  382. );
  383. if (!isset($db[0])) {
  384. form_set_error('dbxref_table][new][db', 'Please select a database before attempting to add a new database reference.');
  385. }
  386. else {
  387. $form_state['values']['dbxref_table']['new']['db_name'] = $db[0]->name;
  388. }
  389. // Ensure accession is supplied
  390. if (empty($form_state['values']['dbxref_table']['new']['dbxref_accession'])) {
  391. form_set_error('dbxref_table][new][dbxref_accession','You must enter the accession before attempting to add a new database reference.');
  392. }
  393. }
  394. /**
  395. * Called by the add button in chado_add_node_form_dbxrefs
  396. *
  397. * Create an array of additional dbxrefs in the form state. This array will then be
  398. * used to rebuild the form in subsequent builds
  399. *
  400. * @ingroup tripal_core
  401. */
  402. function chado_add_node_form_dbxrefs_add_button_submit($form, &$form_state) {
  403. // if the chado_additional_dbxrefs array is not set then this is the first time modifying the
  404. // dbxref table. this means we need to include all the dbxrefs from the db
  405. if (!isset($form_state['chado_additional_dbxrefs'])) {
  406. chado_add_node_form_dbxrefs_create_dbxref_formstate_array($form, $form_state);
  407. }
  408. // get details for the new dbxref
  409. $dbxref = array(
  410. 'db_id' => $form_state['values']['dbxref_table']['new']['db'],
  411. 'db_name' => $form_state['values']['dbxref_table']['new']['db_name'],
  412. 'dbxref_id' => 'TEMP' . uniqid(),
  413. 'version' => $form_state['values']['dbxref_table']['new']['dbxref_version'],
  414. 'accession' => $form_state['values']['dbxref_table']['new']['dbxref_accession'],
  415. );
  416. $key = $dbxref['db_id'] . '-' . $dbxref['dbxref_id'];
  417. $form_state['chado_additional_dbxrefs'][$key] = (object) $dbxref;
  418. // we don't want the new element to pick up the values from the previous element so wipe them out
  419. unset($form_state['input']['dbxref_table']['new']['db']);
  420. unset($form_state['input']['dbxref_table']['new']['db_name']);
  421. unset($form_state['input']['dbxref_table']['new']['dbxref_version']);
  422. unset($form_state['input']['dbxref_table']['new']['dbxref_accession']);
  423. }
  424. /**
  425. * Called by the many remove buttons in chado_add_node_form_dbxrefs
  426. *
  427. * @ingroup tripal_core
  428. */
  429. function chado_add_node_form_dbxrefs_remove_button_validate($form, $form_state) {
  430. // No validation needed.
  431. }
  432. /**
  433. * Remove the correct dbxref from the form
  434. * Called by the many remove buttons in chado_add_node_form_dbxrefs
  435. *
  436. * @ingroup tripal_core
  437. */
  438. function chado_add_node_form_dbxrefs_remove_button_submit(&$form, &$form_state) {
  439. // if the chado_additional_dbxrefs array is not set then this is the first time modifying the
  440. // dbxref table. this means we need to include all the dbxrefs from the db
  441. if (!isset($form_state['chado_additional_dbxrefs'])) {
  442. chado_add_node_form_dbxrefs_create_dbxref_formstate_array($form, $form_state);
  443. }
  444. // remove the specified dbxref from the form dbxref table
  445. if(preg_match('/dbxrefs_remove-([^-]+-[^-]+)/',$form_state['triggering_element']['#name'],$match)) {
  446. $key = $match[1];
  447. if (array_key_exists($key, $form_state['chado_additional_dbxrefs'])) {
  448. unset($form_state['chado_additional_dbxrefs'][$key]);
  449. }
  450. }
  451. }
  452. /**
  453. * Creates an array in form_state containing the existing addtl_dbxrefs. This array is
  454. * then modified by the add/remove buttons and used as a source for rebuilding the form.
  455. * This function get's called at each button (add and remove) button submits the first
  456. * time one of the button's is clicked to instantiates the $form_state['chado_additional_dbxrefs'] array
  457. *
  458. * $form_state['chado_additional_dbxrefs'] = array(
  459. * '[db_id]-[version]' => array(
  460. * 'db_id' => [the db.db_id value]
  461. * 'db_name' => [the db.name value]
  462. * 'dbxref_id' => [the dbxref.dbxref_id value, or temporary value if it doesn't yet exists],
  463. * 'version' => [the dbxref.version value],
  464. * 'accession' => [the dbxref.accession value],
  465. * ),
  466. * );
  467. *
  468. * @ingroup tripal_core
  469. */
  470. function chado_add_node_form_dbxrefs_create_dbxref_formstate_array($form, &$form_state) {
  471. $form_state['chado_additional_dbxrefs'] = array();
  472. foreach (element_children($form['addtl_dbxrefs']['dbxref_table']) as $db_id) {
  473. if ($db_id != 'new') {
  474. foreach (element_children($form['addtl_dbxrefs']['dbxref_table'][$db_id]) as $version) {
  475. $element = $form['addtl_dbxrefs']['dbxref_table'][$db_id][$version];
  476. $dbxref = array(
  477. 'db_id' => $element['db_id']['#value'],
  478. 'db_name' => $element['db']['#markup'],
  479. 'dbxref_id' => $element['dbxref_id']['#value'],
  480. 'version' => $element['dbxref_version']['#markup'],
  481. 'accession' => $element['dbxref_accession']['#markup'],
  482. );
  483. $key = $dbxref['db_id'] . '-' . $dbxref['dbxref_id'];
  484. $form_state['chado_additional_dbxrefs'][$key] = (object) $dbxref;
  485. }
  486. }
  487. }
  488. }
  489. /**
  490. * Function to theme the add/remove dbxrefs form into a table
  491. *
  492. * @ingroup tripal_chado_node_api
  493. */
  494. function theme_chado_add_node_form_dbxrefs_table($variables) {
  495. $element = $variables['element'];
  496. $header = array(
  497. 'db' => t('Database'),
  498. 'dbxref_accession' => t('Accession'),
  499. 'dbxref_version' => t('Version'),
  500. 'dbxref_action' => t('Actions'),
  501. );
  502. $rows = array();
  503. foreach (element_children($element) as $db_id) {
  504. if ($db_id == 'new') {
  505. $row = array();
  506. $row['data'] = array();
  507. foreach ($header as $fieldname => $title) {
  508. $row['data'][] = drupal_render($element[$db_id][$fieldname]);
  509. }
  510. $rows[] = $row;
  511. }
  512. else {
  513. foreach (element_children($element[$db_id]) as $version) {
  514. $row = array();
  515. $row['data'] = array();
  516. $row['class'] = $element[$db_id][$version]['#attributes']['class'];
  517. foreach ($header as $fieldname => $title) {
  518. $row['data'][] = drupal_render($element[$db_id][$version][$fieldname]);
  519. }
  520. $rows[] = $row;
  521. }
  522. }
  523. }
  524. return theme('table', array(
  525. 'header' => $header,
  526. 'rows' => $rows
  527. ));
  528. }
  529. /**
  530. * This function is used in a hook_insert, hook_update for a node form
  531. * when the additional_dbxrefs form has been added to the form. It retrieves all of the dbxrefs
  532. * and returns them in an array of the format:
  533. *
  534. * $dbxefs[<db_id>][<version>][<dbxref_id>] = <accession>
  535. *
  536. * This array can then be used for inserting or updating dbxrefs using the API call
  537. * tripal_hook_insert_dbxref()
  538. *
  539. * @param $node
  540. *
  541. * @return
  542. * A dbxref array
  543. *
  544. * @ingroup tripal_chado_node_api
  545. */
  546. function chado_retrieve_node_form_dbxrefs($node) {
  547. $dbxrefs = array();
  548. if (isset($node->dbxref_table)) {
  549. foreach ($node->dbxref_table as $db_id => $elements) {
  550. if ($db_id != 'new') {
  551. foreach ($elements as $dbxref_id => $dbxref) {
  552. $version = (!empty($dbxref['version'])) ? $dbxref['version'] : 'NONE';
  553. $dbxrefs[$db_id][$version][$dbxref_id] = $dbxref['accession'];
  554. }
  555. }
  556. }
  557. }
  558. return $dbxrefs;
  559. }
  560. /**
  561. * This function is used in hook_insert or hook_update and handles inserting of any new
  562. * dbxrefs and creation of links between those dbxrefs and node content
  563. *
  564. * @param $node
  565. * The node passed into hook_insert & hook_update
  566. * @param $details
  567. * - linking_table: the name of the _dbxref linking table (ie: feature_dbxref)
  568. * - foreignkey_name: the name of the foreign key used to link to the node content (ie: feature_id)
  569. * - foreignkey_value: the value of the foreign key (ie: 445, if there exists a feature where feature_id=445)
  570. * @param $retrieved_dbxrefs
  571. * An array of databa references from chado_retrieve_node_form_dbxrefs($node).
  572. * This can be used if you need special handling for some of the database references
  573. *
  574. * @ingroup tripal_chado_node_api
  575. */
  576. function chado_update_node_form_dbxrefs($node, $details, $retrieved_dbxrefs = FALSE) {
  577. $linking_table = $details['linking_table'];
  578. $foreignkey_name = $details['foreignkey_name'];
  579. $foreignkey_value = $details['foreignkey_value'];
  580. if (isset($node->dbxref_table) AND ($foreignkey_value > 0)) {
  581. // First remove existing dbxref links
  582. chado_delete_record($linking_table, array($foreignkey_name => $foreignkey_value));
  583. // Add back in dbxref links and insert dbxrefs as needed
  584. if ($retrieved_dbxrefs) {
  585. $dbxrefs = $retrieved_dbxrefs;
  586. }
  587. else {
  588. $dbxrefs = chado_retrieve_node_form_dbxrefs($node);
  589. }
  590. foreach ($dbxrefs as $db_id => $versions) {
  591. foreach ($versions as $version => $elements) {
  592. foreach ($elements as $dbxref_id => $accession) {
  593. // If there is no dbxref then we have to create that first
  594. if (preg_match('/^TEMP/',$dbxref_id)) {
  595. $version = ($version == 'NONE') ? '' : $version;
  596. $success = tripal_insert_dbxref(array(
  597. 'db_id' => $db_id,
  598. 'accession' => $accession,
  599. 'version' => $version,
  600. 'description' => NULL
  601. ));
  602. if ($success) {
  603. $dbxref_id = $success->dbxref_id;
  604. }
  605. else {
  606. $dbxref_id = FALSE;
  607. }
  608. }
  609. // add _dbxref linker
  610. if ($dbxref_id) {
  611. if (preg_match('/(\w+)_dbxref/',$linking_table,$matches)) {
  612. $base_table = $matches[1];
  613. $success_link = tripal_associate_dbxref(
  614. $base_table,
  615. $foreignkey_value,
  616. array('dbxref_id' => $dbxref_id)
  617. );
  618. }
  619. }
  620. }
  621. }
  622. }
  623. }
  624. }