tripal_core.chado_nodes.dbxrefs.api.inc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  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. // We need to provide feedback to the user that changes made
  175. // are not saved until the node is saved.
  176. $form['addtl_dbxrefs']['dbxref_table']['save_warning'] = array(
  177. '#type' => 'markup',
  178. '#prefix' => '<div id="dbxref-save-warning" class="messages warning" style="display:none;">',
  179. '#suffix' => '</div>',
  180. '#markup' => '* The changes to these references will not be saved until the "Save" button at the bottom of this form is clicked. <span class="specific-changes"></span>',
  181. '#attached' => array(
  182. 'js' => array(
  183. 'chado-node-api-unsaved' => drupal_get_path('module', 'tripal_core') . '/theme/js/chadoNodeApi_unsavedNotify.js',
  184. ),
  185. ),
  186. );
  187. /* DBxrefs can come to us in two ways:
  188. *
  189. * 1) In the form state in the $form_state['chado_additional_dbxrefs']. Data is in this field
  190. * when an AJAX call updates the form state or a validation error.
  191. *
  192. * 2) Directly from the database if the record already has dbxref's associated. This
  193. * data is only used the first time the form is loaded. On AJAX calls or validation
  194. * errors the fields on the form are populated from the $form_state['chado_additional_dbxrefs']
  195. * entry.
  196. */
  197. if (isset($form_state['chado_additional_dbxrefs'])) {
  198. $existing_dbxrefs = $form_state['chado_additional_dbxrefs'];
  199. }
  200. else {
  201. $existing_dbxrefs = chado_query(
  202. "SELECT
  203. db.name as db_name,
  204. db.db_id as db_id,
  205. dbxref.dbxref_id,
  206. dbxref.accession as accession,
  207. dbxref.description as description,
  208. dbxref.version
  209. FROM {dbxref} dbxref
  210. LEFT JOIN {db} db ON db.db_id = dbxref.db_id
  211. LEFT JOIN {".$details['linking_table']."} linking_table ON linking_table.dbxref_id = dbxref.dbxref_id
  212. WHERE linking_table.".$details['base_foreign_key']."= :base_key_value
  213. ORDER BY db.name ASC, dbxref.version ASC",
  214. array(':base_key_value' => $details['base_key_value'])
  215. );
  216. }
  217. /* The format of the $existing_dbxref's array is either:
  218. *
  219. * From the chado_additional_dbxrefs array:
  220. * $form_state['chado_additional_dbxrefs'] = array(
  221. * '[db_id]-[version]' => array(
  222. * 'db_id' => [the db.db_id value]
  223. * 'db_name' => [the db.name value]
  224. * 'dbxref_id' => [the dbxref.dbxref_id value, or temporary value if it doesn't yet exists],
  225. * 'version' => [the dbxref.version value],
  226. * 'accession' => [the dbxref.accession value],
  227. * ),
  228. * );
  229. *
  230. * OR
  231. * Populated from the database:
  232. * $existing_dbxref = array(
  233. * 0 => array(
  234. * 'dbxref_id' => [the dbxref.dbxref_id value],
  235. * 'db_name' => [the db.name value],
  236. * 'db_id' => [the db.db_id value],
  237. * 'accession' => [the dbxref.accession value],
  238. * 'description' => [the dbxref.description value],
  239. * 'version' => [the dbxref.versiion value],
  240. * ),
  241. * );
  242. *
  243. * NOTE: The main difference is the key
  244. *
  245. * Loop on the array elements of the $existing_dbxrefs array and add
  246. * an element to the form for each one.
  247. */
  248. $num_dbxrefs = 0;
  249. foreach ($existing_dbxrefs as $dbxref) {
  250. if (array_key_exists($dbxref->db_id, $db_options)) {
  251. $num_dbxrefs++;
  252. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id]['#type'] = 'markup';
  253. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id]['#value'] = '';
  254. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['#type'] = 'markup';
  255. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['#value'] = '';
  256. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['#attributes'] = array(
  257. 'class' => array('dbxref', 'saved')
  258. );
  259. // Determine whether this dbxref is unsaved or not.
  260. // We can tell this by looking at the dbxref_id: if it's not
  261. // saved yet we will have entered a TEMP###.
  262. if (preg_match('/^TEMP/', $dbxref->dbxref_id)) {
  263. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['#attributes'] = array(
  264. 'class' => array('dbxref', 'unsaved')
  265. );
  266. }
  267. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['db_id'] = array(
  268. '#type' => 'hidden',
  269. '#value' => $dbxref->db_id
  270. );
  271. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['accession'] = array(
  272. '#type' => 'hidden',
  273. '#value' => $dbxref->accession
  274. );
  275. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['version'] = array(
  276. '#type' => 'hidden',
  277. '#value' => $dbxref->version,
  278. );
  279. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['dbxref_id'] = array(
  280. '#type' => 'hidden',
  281. '#value' => $dbxref->dbxref_id
  282. );
  283. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['db'] = array(
  284. '#type' => 'markup',
  285. '#markup' => $dbxref->db_name,
  286. '#prefix' => '<span class="row-unsaved-warning"></span>'
  287. );
  288. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['dbxref_version'] = array(
  289. '#type' => 'markup',
  290. '#markup' => $dbxref->version,
  291. );
  292. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['dbxref_accession'] = array(
  293. '#type' => 'markup',
  294. '#markup' => $dbxref->accession
  295. );
  296. // remove button
  297. $form['addtl_dbxrefs']['dbxref_table'][$dbxref->db_id][$dbxref->dbxref_id]['dbxref_action'] = array(
  298. '#type' => 'submit',
  299. '#value' => t('Remove'),
  300. '#name' => "dbxrefs_remove-".$dbxref->db_id.'-'.$dbxref->dbxref_id,
  301. '#ajax' => array(
  302. 'callback' => "chado_add_node_form_subtable_ajax_update",
  303. 'wrapper' => 'tripal-generic-edit-addtl_dbxrefs-table',
  304. 'effect' => 'fade',
  305. 'method' => 'replace',
  306. 'prevent' => 'click'
  307. ),
  308. // When this button is clicked, the form will be validated and submitted.
  309. // Therefore, we set custom submit and validate functions to override the
  310. // default node form submit. In the validate function we validate only the
  311. // additional dbxref fields and in the submit we remove the indicated dbxref
  312. // from the chado_additional_dbxrefs array. In order to keep validate errors
  313. // from the node form validate and Drupal required errors for non-dbxref fields
  314. // preventing the user from removing dbxrefs we set the #limit_validation_errors below
  315. '#validate' => array('chado_add_node_form_subtables_remove_button_validate'),
  316. '#submit' => array('chado_add_node_form_subtables_remove_button_submit'),
  317. // Limit the validation of the form upon clicking this button to the dbxref_table tree
  318. // No other fields will be validated (ie: no fields from the main form or any other api
  319. // added form).
  320. '#limit_validation_errors' => array(
  321. array('dbxref_table') // Validate all fields within $form_state['values']['dbxref_table']
  322. )
  323. );
  324. }
  325. }
  326. // Quickly add a hidden field stating how many dbxrefs are currently added.
  327. $form['addtl_dbxrefs']['num_dbxrefs'] = array(
  328. '#type' => 'hidden',
  329. '#value' => $num_dbxrefs,
  330. '#attributes' => array('class' => 'num-dbxrefs')
  331. );
  332. // Form elements for adding a new dbxref
  333. //---------------------------------------------
  334. $form['addtl_dbxrefs']['dbxref_table']['new'] = array(
  335. '#type' => 'markup',
  336. '#prefix' => '<span class="addtl-dbxrefs-add-new-dbxref">',
  337. '#suffix' => '</span>'
  338. );
  339. // add in the existing databases
  340. $form['addtl_dbxrefs']['dbxref_table']['new']['db'] = array(
  341. '#type' => 'select',
  342. '#options' => $db_options,
  343. );
  344. $form['addtl_dbxrefs']['dbxref_table']['new']['dbxref_accession'] = array(
  345. '#type' => 'textfield',
  346. );
  347. $form['addtl_dbxrefs']['dbxref_table']['new']['dbxref_version'] = array(
  348. '#type' => 'textfield',
  349. '#size' => 10,
  350. );
  351. // add button
  352. $form['addtl_dbxrefs']['dbxref_table']['new']['dbxref_action'] = array(
  353. '#type' => 'submit',
  354. '#value' => t('Add'),
  355. '#name' => "dbxrefs-add",
  356. '#ajax' => array(
  357. 'callback' => "chado_add_node_form_subtable_ajax_update",
  358. 'wrapper' => 'tripal-generic-edit-addtl_dbxrefs-table',
  359. 'effect' => 'fade',
  360. 'method' => 'replace',
  361. 'prevent' => 'click'
  362. ),
  363. // When this button is clicked, the form will be validated and submitted.
  364. // Therefore, we set custom submit and validate functions to override the
  365. // default node form submit. In the validate function we validate only the
  366. // additional dbxref fields and in the submit we add them to the chado_additional_dbxrefs
  367. // array. In order to keep validate errors from the node form validate and Drupal
  368. // required errors for non-dbxref fields preventing the user from adding dbxrefs we
  369. // set the #limit_validation_errors below
  370. '#validate' => array('chado_add_node_form_subtables_add_button_validate'),
  371. '#submit' => array('chado_add_node_form_subtables_add_button_submit'),
  372. // Limit the validation of the form upon clicking this button to the dbxref_table tree
  373. // No other fields will be validated (ie: no fields from the main form or any other api
  374. // added form).
  375. '#limit_validation_errors' => array(
  376. array('dbxref_table') // Validate all fields within $form_state['values']['dbxref_table']
  377. )
  378. );
  379. $form['addtl_dbxrefs']['admin_message'] = array(
  380. '#type' => 'markup',
  381. '#markup' => $tripal_message
  382. );
  383. }
  384. /**
  385. * Validate the user input for creating a new dbxref
  386. * Called by the add button in chado_add_node_form_dbxrefs
  387. *
  388. * @ingroup tripal_core
  389. */
  390. function chado_add_node_form_dbxrefs_add_button_validate($form, &$form_state) {
  391. // Ensure the db_id is supplied & Valid
  392. $db = chado_select_record(
  393. 'db',
  394. array('db_id', 'name'),
  395. array('db_id' => $form_state['values']['dbxref_table']['new']['db'])
  396. );
  397. if (!isset($db[0])) {
  398. form_set_error('dbxref_table][new][db', 'Please select a database before attempting to add a new database reference.');
  399. }
  400. else {
  401. $form_state['values']['dbxref_table']['new']['db_name'] = $db[0]->name;
  402. }
  403. // Ensure accession is supplied
  404. if (empty($form_state['values']['dbxref_table']['new']['dbxref_accession'])) {
  405. form_set_error('dbxref_table][new][dbxref_accession','You must enter the accession before attempting to add a new database reference.');
  406. }
  407. }
  408. /**
  409. * Called by the add button in chado_add_node_form_dbxrefs
  410. *
  411. * Create an array of additional dbxrefs in the form state. This array will then be
  412. * used to rebuild the form in subsequent builds
  413. *
  414. * @ingroup tripal_core
  415. */
  416. function chado_add_node_form_dbxrefs_add_button_submit($form, &$form_state) {
  417. // if the chado_additional_dbxrefs array is not set then this is the first time modifying the
  418. // dbxref table. this means we need to include all the dbxrefs from the db
  419. if (!isset($form_state['chado_additional_dbxrefs'])) {
  420. chado_add_node_form_dbxrefs_create_dbxref_formstate_array($form, $form_state);
  421. }
  422. // get details for the new dbxref
  423. $dbxref = array(
  424. 'db_id' => $form_state['values']['dbxref_table']['new']['db'],
  425. 'db_name' => $form_state['values']['dbxref_table']['new']['db_name'],
  426. 'dbxref_id' => 'TEMP' . uniqid(),
  427. 'version' => $form_state['values']['dbxref_table']['new']['dbxref_version'],
  428. 'accession' => $form_state['values']['dbxref_table']['new']['dbxref_accession'],
  429. );
  430. $key = $dbxref['db_id'] . '-' . $dbxref['dbxref_id'];
  431. $form_state['chado_additional_dbxrefs'][$key] = (object) $dbxref;
  432. // we don't want the new element to pick up the values from the previous element so wipe them out
  433. unset($form_state['input']['dbxref_table']['new']['db']);
  434. unset($form_state['input']['dbxref_table']['new']['db_name']);
  435. unset($form_state['input']['dbxref_table']['new']['dbxref_version']);
  436. unset($form_state['input']['dbxref_table']['new']['dbxref_accession']);
  437. }
  438. /**
  439. * Called by the many remove buttons in chado_add_node_form_dbxrefs
  440. *
  441. * @ingroup tripal_core
  442. */
  443. function chado_add_node_form_dbxrefs_remove_button_validate($form, $form_state) {
  444. // No validation needed.
  445. }
  446. /**
  447. * Remove the correct dbxref from the form
  448. * Called by the many remove buttons in chado_add_node_form_dbxrefs
  449. *
  450. * @ingroup tripal_core
  451. */
  452. function chado_add_node_form_dbxrefs_remove_button_submit(&$form, &$form_state) {
  453. // if the chado_additional_dbxrefs array is not set then this is the first time modifying the
  454. // dbxref table. this means we need to include all the dbxrefs from the db
  455. if (!isset($form_state['chado_additional_dbxrefs'])) {
  456. chado_add_node_form_dbxrefs_create_dbxref_formstate_array($form, $form_state);
  457. }
  458. // remove the specified dbxref from the form dbxref table
  459. if(preg_match('/dbxrefs_remove-([^-]+-[^-]+)/',$form_state['triggering_element']['#name'],$match)) {
  460. $key = $match[1];
  461. if (array_key_exists($key, $form_state['chado_additional_dbxrefs'])) {
  462. unset($form_state['chado_additional_dbxrefs'][$key]);
  463. }
  464. }
  465. }
  466. /**
  467. * Creates an array in form_state containing the existing addtl_dbxrefs. This array is
  468. * then modified by the add/remove buttons and used as a source for rebuilding the form.
  469. * This function get's called at each button (add and remove) button submits the first
  470. * time one of the button's is clicked to instantiates the $form_state['chado_additional_dbxrefs'] array
  471. *
  472. * $form_state['chado_additional_dbxrefs'] = array(
  473. * '[db_id]-[version]' => array(
  474. * 'db_id' => [the db.db_id value]
  475. * 'db_name' => [the db.name value]
  476. * 'dbxref_id' => [the dbxref.dbxref_id value, or temporary value if it doesn't yet exists],
  477. * 'version' => [the dbxref.version value],
  478. * 'accession' => [the dbxref.accession value],
  479. * ),
  480. * );
  481. *
  482. * @ingroup tripal_core
  483. */
  484. function chado_add_node_form_dbxrefs_create_dbxref_formstate_array($form, &$form_state) {
  485. $form_state['chado_additional_dbxrefs'] = array();
  486. foreach (element_children($form['addtl_dbxrefs']['dbxref_table']) as $db_id) {
  487. if ($db_id != 'new') {
  488. foreach (element_children($form['addtl_dbxrefs']['dbxref_table'][$db_id]) as $version) {
  489. $element = $form['addtl_dbxrefs']['dbxref_table'][$db_id][$version];
  490. $dbxref = array(
  491. 'db_id' => $element['db_id']['#value'],
  492. 'db_name' => $element['db']['#markup'],
  493. 'dbxref_id' => $element['dbxref_id']['#value'],
  494. 'version' => $element['dbxref_version']['#markup'],
  495. 'accession' => $element['dbxref_accession']['#markup'],
  496. );
  497. $key = $dbxref['db_id'] . '-' . $dbxref['dbxref_id'];
  498. $form_state['chado_additional_dbxrefs'][$key] = (object) $dbxref;
  499. }
  500. }
  501. }
  502. }
  503. /**
  504. * Function to theme the add/remove dbxrefs form into a table
  505. *
  506. * @ingroup tripal_chado_node_api
  507. */
  508. function theme_chado_add_node_form_dbxrefs_table($variables) {
  509. $element = $variables['element'];
  510. $header = array(
  511. 'db' => t('Database'),
  512. 'dbxref_accession' => t('Accession'),
  513. 'dbxref_version' => t('Version'),
  514. 'dbxref_action' => t('Actions'),
  515. );
  516. $rows = array();
  517. foreach (element_children($element) as $db_id) {
  518. if ($db_id == 'new') {
  519. $row = array();
  520. $row['data'] = array();
  521. foreach ($header as $fieldname => $title) {
  522. $row['data'][] = drupal_render($element[$db_id][$fieldname]);
  523. }
  524. $rows[] = $row;
  525. }
  526. else {
  527. foreach (element_children($element[$db_id]) as $version) {
  528. $row = array();
  529. $row['data'] = array();
  530. $row['class'] = $element[$db_id][$version]['#attributes']['class'];
  531. foreach ($header as $fieldname => $title) {
  532. $row['data'][] = drupal_render($element[$db_id][$version][$fieldname]);
  533. }
  534. $rows[] = $row;
  535. }
  536. }
  537. }
  538. return render($element['save_warning']) . theme('table', array(
  539. 'header' => $header,
  540. 'rows' => $rows
  541. ));
  542. }
  543. /**
  544. * This function is used in a hook_insert, hook_update for a node form
  545. * when the additional_dbxrefs form has been added to the form. It retrieves all of the dbxrefs
  546. * and returns them in an array of the format:
  547. *
  548. * $dbxefs[<db_id>][<version>][<dbxref_id>] = <accession>
  549. *
  550. * This array can then be used for inserting or updating dbxrefs using the API call
  551. * tripal_hook_insert_dbxref()
  552. *
  553. * @param $node
  554. *
  555. * @return
  556. * A dbxref array
  557. *
  558. * @ingroup tripal_chado_node_api
  559. */
  560. function chado_retrieve_node_form_dbxrefs($node) {
  561. $dbxrefs = array();
  562. if (isset($node->dbxref_table)) {
  563. foreach ($node->dbxref_table as $db_id => $elements) {
  564. if ($db_id != 'new') {
  565. foreach ($elements as $dbxref_id => $dbxref) {
  566. $version = (!empty($dbxref['version'])) ? $dbxref['version'] : 'NONE';
  567. $dbxrefs[$db_id][$version][$dbxref_id] = $dbxref['accession'];
  568. }
  569. }
  570. }
  571. }
  572. return $dbxrefs;
  573. }
  574. /**
  575. * This function is used in hook_insert or hook_update and handles inserting of any new
  576. * dbxrefs and creation of links between those dbxrefs and node content
  577. *
  578. * @param $node
  579. * The node passed into hook_insert & hook_update
  580. * @param $details
  581. * - linking_table: the name of the _dbxref linking table (ie: feature_dbxref)
  582. * - foreignkey_name: the name of the foreign key used to link to the node content (ie: feature_id)
  583. * - foreignkey_value: the value of the foreign key (ie: 445, if there exists a feature where feature_id=445)
  584. * @param $retrieved_dbxrefs
  585. * An array of databa references from chado_retrieve_node_form_dbxrefs($node).
  586. * This can be used if you need special handling for some of the database references
  587. *
  588. * @ingroup tripal_chado_node_api
  589. */
  590. function chado_update_node_form_dbxrefs($node, $details, $retrieved_dbxrefs = FALSE) {
  591. $linking_table = $details['linking_table'];
  592. $foreignkey_name = $details['foreignkey_name'];
  593. $foreignkey_value = $details['foreignkey_value'];
  594. if (isset($node->dbxref_table) AND ($foreignkey_value > 0)) {
  595. // First remove existing dbxref links
  596. chado_delete_record($linking_table, array($foreignkey_name => $foreignkey_value));
  597. // Add back in dbxref links and insert dbxrefs as needed
  598. if ($retrieved_dbxrefs) {
  599. $dbxrefs = $retrieved_dbxrefs;
  600. }
  601. else {
  602. $dbxrefs = chado_retrieve_node_form_dbxrefs($node);
  603. }
  604. foreach ($dbxrefs as $db_id => $versions) {
  605. foreach ($versions as $version => $elements) {
  606. foreach ($elements as $dbxref_id => $accession) {
  607. // If there is no dbxref then we have to create that first
  608. if (preg_match('/^TEMP/',$dbxref_id)) {
  609. $version = ($version == 'NONE') ? '' : $version;
  610. $success = tripal_insert_dbxref(array(
  611. 'db_id' => $db_id,
  612. 'accession' => $accession,
  613. 'version' => $version,
  614. 'description' => NULL
  615. ));
  616. if ($success) {
  617. $dbxref_id = $success->dbxref_id;
  618. }
  619. else {
  620. $dbxref_id = FALSE;
  621. }
  622. }
  623. // add _dbxref linker
  624. if ($dbxref_id) {
  625. if (preg_match('/(\w+)_dbxref/',$linking_table,$matches)) {
  626. $base_table = $matches[1];
  627. $success_link = tripal_associate_dbxref(
  628. $base_table,
  629. $foreignkey_value,
  630. array('dbxref_id' => $dbxref_id)
  631. );
  632. }
  633. }
  634. }
  635. }
  636. }
  637. }
  638. }