tripal_bulk_loader.loader.inc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. <?php
  2. /**
  3. * Add Loader Job Form
  4. *
  5. * This form is meant to be included on the node page to allow users to submit/re-submit
  6. * loading jobs
  7. */
  8. function tripal_bulk_loader_add_loader_job_form ($form_state, $node) {
  9. $form = array();
  10. $form['nid'] = array(
  11. '#type' => 'hidden',
  12. '#value' => $node->nid,
  13. );
  14. $form['file'] = array(
  15. '#type' => 'hidden',
  16. '#value' => $node->file
  17. );
  18. $form['job_id'] = array(
  19. '#type' => 'hidden',
  20. '#value' => $node->job_id,
  21. );
  22. $form['submit'] = array(
  23. '#type' => 'submit',
  24. '#value' => ($node->job_id) ? 'Re-Submit Job' : 'Submit Job',
  25. );
  26. $form['submit-cancel'] = array(
  27. '#type' => ($node->job_id)? 'submit' : 'hidden',
  28. '#value' => 'Cancel Job',
  29. );
  30. return $form;
  31. }
  32. /**
  33. * Add Loader Job Form (Submit)
  34. */
  35. function tripal_bulk_loader_add_loader_job_form_submit ($form, $form_state) {
  36. global $user;
  37. if (preg_match('/Submit Job/', $form_state['values']['op'])) {
  38. //Submit Tripal Job
  39. $job_args[1] = $form_state['values']['nid'];
  40. if (is_readable($form_state['values']['file'])) {
  41. $fname = basename($form_state['values']['file']);
  42. $job_id = tripal_add_job("Bulk Loading Job: $fname",'tripal_bulk_loader', 'tripal_bulk_loader_load_data', $job_args, $user->uid);
  43. // add job_id to bulk_loader node
  44. $record = node_load($form_state['values']['nid']);
  45. $record->job_id = $job_id;
  46. drupal_write_record('tripal_bulk_loader', $record, 'nid');
  47. // Add Sync Features Job
  48. tripal_add_job('Sync all features','tripal_feature',
  49. 'tripal_feature_sync_features',$job_args,$user->uid);
  50. } else {
  51. drupal_set_message("Can not open ".$form_state['values']['file'].". Job not scheduled.");
  52. }
  53. } elseif (preg_match('/Re-Submit Job/', $form_state['values']['op'])) {
  54. tripal_jobs_rerun($form_state['values']['job_id']);
  55. } elseif (preg_match('/Cancel Job/', $form_state['values']['op'])) {
  56. tripal_jobs_cancel($form_state['values']['job_id']);
  57. }
  58. }
  59. /**
  60. * Tripal Bulk Loader
  61. *
  62. * This is the function that's run by tripal_launch_jobs to bulk load chado data.
  63. * @param $nid
  64. * The Node ID of the bulk loading job node to be loaded. All other needed data is expected to be
  65. * in the node (ie: template ID and file)
  66. *
  67. * Note: Instead of returning a value this function updates the tripal_bulk_loader.status and
  68. * Enters errors into tripal_bulk_loader_errors if they are encountered.
  69. */
  70. function tripal_bulk_loader_load_data($nid) {
  71. $node = node_load($nid);
  72. print "Template: ".$node->template->name." (".$node->template_id.")\n";
  73. print "File: ".$node->file."\n";
  74. // Prep Work ==================================================================================
  75. // Generate default values array
  76. $default_data = array();
  77. $field2column = array();
  78. $record2priority = array();
  79. foreach ($node->template->template_array as $priority => $record_array) {
  80. if (!is_array($record_array)) { continue; }
  81. foreach ($record_array['fields'] as $field_index => $field_array) {
  82. $default_data[$priority]['table'] = $record_array['table'];
  83. $record2priority[$record_array['record_id']] = $priority;
  84. if (preg_match('/table field/', $field_array['type'])) {
  85. $default_data[$priority]['values_array'][$field_array['field']] = '';
  86. $default_data[$priority]['need_further_processing'] = TRUE;
  87. $field2column[$priority][$field_array['field']] = $field_array['spreadsheet column'];
  88. } elseif (preg_match('/constant/', $field_array['type'])) {
  89. $default_data[$priority]['values_array'][$field_array['field']] = $field_array['constant value'];
  90. } elseif (preg_match('/foreign key/', $field_array['type'])) {
  91. $default_data[$priority]['values_array'][$field_array['field']] = array();
  92. $default_data[$priority]['values_array'][$field_array['field']]['foreign record'] = $field_array['foreign key'];
  93. $default_data[$priority]['need_further_processing'] = TRUE;
  94. } else {
  95. print 'WARNING: Unsupported type: '. $field_array['type'] . ' for ' . $table . '.' . $field_array['field']."!\n";
  96. }
  97. } // end of foreach field
  98. } //end of foreach record
  99. //print "\nDefault Values Array: ".print_r($default_data, TRUE)."\n";
  100. //print "\nField to Column Mapping: ".print_r($field2column, TRUE)."\n";
  101. // Parse File adding records as we go ========================================================
  102. $file_handle = fopen($node->file, 'r');
  103. if (preg_match('/(t|true|1)/', $node->file_has_header)) { fgets($file_handle, 4096); }
  104. $num_records = 0;
  105. $num_lines = 0;
  106. $num_errors = 0;
  107. while (!feof($file_handle)) {
  108. $line = array();
  109. $raw_line = fgets($file_handle, 4096);
  110. $raw_line = trim($raw_line);
  111. $line = preg_split("/\t/", $raw_line);
  112. $num_lines++;
  113. $data = $default_data;
  114. foreach ($data as $priority => $table_data) {
  115. $table = $table_data['table'];
  116. $values = $table_data['values_array'];
  117. if ($table_data['need_further_processing']) {
  118. $values = tripal_bulk_loader_add_spreadsheetdata_to_values ($values, $line, $field2column[$priority]);
  119. $values = tripal_bulk_loader_add_foreignkey_to_values($values, $data, $record2priority);
  120. }
  121. // add new values array into the data array
  122. $data[$priority]['values_array'] = $values;
  123. // first check if it already exists
  124. $exists = tripal_core_chado_select($table, array_keys($values), $values, array('has_record'=>TRUE));
  125. if ($exists) {
  126. watchdog('T_bulk_loader',
  127. 'Record already exists in %table: %record',
  128. array('%table' => $table, '%record' => tripal_bulk_loader_flatten_array($values)),
  129. 'WATCHDOG_WARNING'
  130. );
  131. } else {
  132. // if it doesn't exist already then insert it
  133. $success = tripal_core_chado_insert($table, $values);
  134. if (!$success) {
  135. watchdog('T_bulk_loader',
  136. 'Unable to insert the following record into %table: %record',
  137. array('%table' => $table, '%record' => tripal_bulk_loader_flatten_array($values)),
  138. 'WATCHDOG_ERROR'
  139. );
  140. }
  141. }// end of if/not record exists
  142. } // end of foreach table in default data array
  143. } //end of foreach line of file
  144. }
  145. /**
  146. * This function adds the file data to the values array
  147. *
  148. * @param $values
  149. * The default values array -contains all constants
  150. * @param $line
  151. * An array of values for the current line
  152. * @param $field2column
  153. * An array mapping values fields to line columns
  154. * @return
  155. * Supplemented values array
  156. */
  157. function tripal_bulk_loader_add_spreadsheetdata_to_values ($values, $line, $field2column) {
  158. foreach ($values as $field => $value) {
  159. if (is_array($value)) { continue; }
  160. $column = $field2column[$field] - 1;
  161. if ($line[$column] OR (!$values[$field])) {
  162. $values[$field] = $line[$column];
  163. }
  164. }
  165. return $values;
  166. }
  167. /**
  168. * Handles foreign keys in the values array.
  169. *
  170. * Specifically, if the value for a field is an array then it is assumed that the array contains
  171. * the name of the record whose values array should be substituted here. Thus the foreign
  172. * record is looked up and the values array is substituted in.
  173. *
  174. */
  175. function tripal_bulk_loader_add_foreignkey_to_values($values, $data, $record2priority) {
  176. foreach ($values as $field => $value) {
  177. if (is_array($value)) {
  178. $foreign_record = $value['foreign record'];
  179. $foreign_priority = $record2priority[$foreign_record];
  180. $foreign_values = $data[$foreign_priority]['values_array'];
  181. //add to current values array
  182. $values[$field] = $foreign_values;
  183. }
  184. }
  185. return $values;
  186. }
  187. /**
  188. * Flattens an array up to two levels
  189. * Used for printing of arrays without taking up much space
  190. */
  191. function tripal_bulk_loader_flatten_array ($values) {
  192. $flattened_values = array();
  193. foreach ($values as $k => $v) {
  194. if (is_array($v)) {
  195. $vstr = array();
  196. foreach ($v as $vk => $vv) {
  197. if (strlen($vv) > 20) {
  198. $vstr[] = $vk .'=>'. substr($vv, 0, 20) . '...';
  199. } else {
  200. $vstr[] = $vk .'=>'. $vv;
  201. }
  202. }
  203. $v = '{'. implode(',',$vstr) .'}';
  204. } elseif (strlen($v) > 20) {
  205. $v = substr($v, 0, 20) . '...';
  206. }
  207. $flattened_values[] = $k .'=>'. $v;
  208. }
  209. return implode(', ',$flattened_values);
  210. }