blast_ui.theme.inc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. <?php
  2. /**
  3. * @file
  4. * This file contains functions specifically related to theme-ing the BLAST module
  5. */
  6. /**
  7. * Preprocess function for the show_blast_report.tpl.php
  8. *
  9. * Use this function to prepare variables for use in the template,
  10. * as well as to add css/javascript needed.
  11. *
  12. * @param $vars
  13. * The variables currently available to the template.
  14. */
  15. function blast_ui_preprocess_show_blast_report(&$vars) {
  16. // Add CSS and Javascript files
  17. $path = drupal_get_path('module', 'blast_ui');
  18. drupal_add_css($path . '/theme/css/blast_report.css');
  19. drupal_add_js('https://code.jquery.com/jquery-1.12.4.min.js');
  20. // Get blast job details.
  21. $vars['blast_job'] = get_BLAST_job($vars['job_id']);
  22. // Determine the blast command for display.
  23. $vars['blast_job']->blast_cmd = $vars['blast_job']->program;
  24. foreach($vars['blast_job']->options as $key => $value) {
  25. $vars['blast_job']->blast_cmd .= ' -' . $key. ' ' . $value ;
  26. }
  27. // CViTjs
  28. $vars['show_cvit_diagram'] = FALSE;
  29. if (variable_get('blast_ui_cvitjs_enabled', false)
  30. && isset($vars['blast_job']->blastdb->cvitjs_enabled)
  31. && $vars['blast_job']->blastdb->cvitjs_enabled == '1') {
  32. // Set a clean var so we don't have to do this long check again ;-).
  33. $vars['show_cvit_diagram'] = TRUE;
  34. // Add the CSS/JS.
  35. $cvitjs_location = variable_get('blast_ui_cvitjs_location', '');
  36. $base = drupal_get_path('module','blast_ui')
  37. . DIRECTORY_SEPARATOR . $cvitjs_location
  38. . DIRECTORY_SEPARATOR . 'js'
  39. . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR;
  40. drupal_add_css($base.'bootstrap/css/bootstrap.min.css',array('preprocess'=>FALSE));
  41. drupal_add_css($base.'hopscotch/css/hopscotch.min.css',array('preprocess'=>FALSE));
  42. drupal_add_css($base.'../../css/cvit.css',array('preprocess'=> FALSE));
  43. drupal_add_js($base.'require/require.js',array('group'=>'JS_LIBRARY','type'=>'file'));
  44. drupal_add_js($base.'require/blast_ui-config.js',array('group'=>'JS_THEME'));
  45. // Add the JS settings.
  46. global $base_url;
  47. drupal_add_js(array('blast_ui'=> array(
  48. 'dataset' => $vars['blast_job']->blastdb->db_name,
  49. 'gff' => $base_url . '/' . $vars['blast_job']->files->result->gff
  50. )),
  51. 'setting'
  52. );
  53. }
  54. // Determine the URL of the blast form.
  55. $vars['blast_form_url'] = 'blast/nucleotide/nucleotide';
  56. switch($vars['blast_job']->program) {
  57. case 'blastn':
  58. $vars['blast_form_url'] = 'blast/nucleotide/nucleotide';
  59. break;
  60. case 'blastx':
  61. $vars['blast_form_url'] = 'blast/nucleotide/protein';
  62. break;
  63. case 'tblastn':
  64. $vars['blast_form_url'] = 'blast/protein/nucleotide';
  65. break;
  66. case 'blastp':
  67. $vars['blast_form_url'] = 'blast/protein/protein';
  68. break;
  69. }
  70. // Load the XML file.
  71. $vars['xml'] = NULL;
  72. $vars['num_results'] = FALSE;
  73. $vars['too_many_results'] = FALSE;
  74. $full_path_xml = DRUPAL_ROOT . DIRECTORY_SEPARATOR . $vars['blast_job']->files->result->xml;
  75. if (is_readable($full_path_xml)) {
  76. $vars['num_results'] = shell_exec('grep -c "<Hit>" ' . escapeshellarg($full_path_xml));
  77. $max_results = intval(variable_get('blast_ui_max_results_displayed', 500));
  78. if ($vars['num_results'] < $max_results) {
  79. $vars['xml'] = simplexml_load_file($full_path_xml);
  80. }
  81. else {
  82. $vars['too_many_results'] = TRUE;
  83. }
  84. }
  85. }
  86. /**
  87. * Implements hook_theme_registery_alter().
  88. */
  89. function blast_ui_theme_registry_alter(&$theme_registry) {
  90. $theme_registry_copy = $theme_registry;
  91. $module_path = drupal_get_path('module', 'blast_ui') . '/theme';
  92. _theme_process_registry($theme_registry_copy, 'phptemplate', 'theme_engine', 'my_custom_theme', $module_path);
  93. $theme_registry += array_diff_key($theme_registry_copy, $theme_registry);
  94. // A list of templates the module will provide templates for
  95. $hooks = array('page');
  96. foreach ($hooks as $hook) {
  97. // Add the key 'theme paths' if it doesn't exist in this theme's registry
  98. if (!isset($theme_registry[$hook]['theme paths'])) {
  99. $theme_registry[$hook]['theme paths'] = array();
  100. }
  101. // Shift this module's directory to the top of the theme path list
  102. if (is_array($theme_registry[$hook]['theme paths'])) {
  103. $first_element = array_shift($theme_registry[$hook]['theme paths']);
  104. if ($first_element) {
  105. array_unshift($theme_registry[$hook]['theme paths'], $first_element, $module_path);
  106. }
  107. else {
  108. array_unshift($theme_registry[$hook]['theme paths'], $module_path);
  109. }
  110. }
  111. }
  112. }
  113. /**
  114. * Makes the tripal job_id unrecognizable.
  115. *
  116. * @param $job_id
  117. * The tripal job_id of the blast you want to make secret.
  118. *
  119. * @return
  120. * A short string representing the job_id.
  121. */
  122. function blast_ui_make_secret($job_id) {
  123. $mapping = blast_ui_secret_mapping();
  124. $secret = str_replace(array_keys($mapping), $mapping, $job_id);
  125. return $secret;
  126. }
  127. /**
  128. * Reveals the true job_id for your secret blast result.
  129. *
  130. * @param $secret
  131. * The job_id previously made secret by blast_ui_make_secret().
  132. *
  133. * @return
  134. * The revealed tripal job_id.
  135. */
  136. function blast_ui_reveal_secret($secret) {
  137. $mapping = blast_ui_secret_mapping(TRUE);
  138. $job_id = str_replace(array_keys($mapping), $mapping, $secret);
  139. // Check that the job_id exists if it is an integer.
  140. if (is_numeric($job_id)) {
  141. $exists = db_query('SELECT job_id FROM {tripal_jobs} WHERE job_id=:id',
  142. array(':id' => $job_id))->fetchField();
  143. if (!$exists) {
  144. tripal_report_error(
  145. 'blast_ui',
  146. TRIPAL_ERROR,
  147. 'Unable to decode the blast job_id from :id.',
  148. array(':id' => $secret)
  149. );
  150. }
  151. else {
  152. return $job_id;
  153. }
  154. }
  155. // Last ditch effort: maybe this job was encoded before the upgrade?
  156. else {
  157. $job_id = base64_decode($secret);
  158. if (is_numeric($job_id)) {
  159. $exists = db_query('SELECT job_id FROM {tripal_jobs} WHERE job_id=:id',
  160. array(':id' => $job_id))->fetchField();
  161. if (!$exists) {
  162. tripal_report_error(
  163. 'blast_ui',
  164. TRIPAL_ERROR,
  165. 'Unable to decode the blast job_id from :id.',
  166. array(':id' => $secret)
  167. );
  168. }
  169. else {
  170. return $job_id;
  171. }
  172. }
  173. else {
  174. tripal_report_error(
  175. 'blast_ui',
  176. TRIPAL_ERROR,
  177. 'Unable to decode the blast job_id from :id.',
  178. array(':id' => $secret)
  179. );
  180. }
  181. }
  182. return FALSE;
  183. }
  184. /**
  185. * A single location for keeping track of the mapping used in our secrets.
  186. */
  187. function blast_ui_secret_mapping($reveal = FALSE) {
  188. $mapping = array(
  189. 1 => 'P',
  190. 2 => 'sA',
  191. 3 => 'b',
  192. 4 => 'Q',
  193. 5 => 'Hi',
  194. 6 => 'yt',
  195. 7 => 'f',
  196. 8 => 'zE',
  197. 9 => 'Km',
  198. 0 => 'jVo',
  199. );
  200. // Since this is an open-source module with all the code publically available,
  201. // our secret is not very secret... We are ok with this since the liklihood of
  202. // profiting by stealing random blast results is pretty low. That said, if this bothers
  203. // you, feel free to implement the following function in a private module to change
  204. // this mapping to something that cannot easily be looked up on github. ;-).
  205. // NOTE: Ensure that the mapping you come up with is unique to ensure that the
  206. // job_id can be consistently revealed or your users might end up unable to find
  207. // their own blast results...
  208. if (function_exists('private_make_mapping_ultra_secret')) {
  209. $mapping = private_make_mapping_ultra_secret($mapping);
  210. }
  211. if ($reveal) {
  212. return array_flip($mapping);
  213. }
  214. else {
  215. return $mapping;
  216. }
  217. }
  218. /**
  219. * Tests your secret mapping over a set of random integers
  220. * to ensure the job_id can be recovered.
  221. *
  222. * @param $num_iterations
  223. * An integer representing the number of times you wish to test your mapping.
  224. */
  225. function blast_ui_test_secret_mapping($num_iterations = 10000) {
  226. $all_work = TRUE;
  227. for($i = 0; $i <= $num_iterations; $i++) {
  228. $job_id = mt_rand(0,100000);
  229. $secret = blast_ui_make_secret($job_id);
  230. $recovered_job_id = blast_ui_reveal_secret($secret);
  231. if ($job_id != $recovered_job_id) {
  232. drupal_set_message("Unable to recover job_id: $job_id; Secret: $secret.",'error');
  233. $all_work = FALSE;
  234. }
  235. }
  236. if ($all_work) {
  237. drupal_Set_message("Secret Mapping works over $num_iterations iterations with random integers.");
  238. }
  239. }