tripal_chado.migrate.inc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <?php
  2. /**
  3. * Implements hook_form()
  4. *
  5. * Provide a form to select Tripal v2 content types for migration
  6. *
  7. * @param $form
  8. * @param $form_state
  9. */
  10. function tripal_chado_migrate_form($form, &$form_state) {
  11. $tv2_content_type = 'all';
  12. if (array_key_exists('values', $form_state)) {
  13. $tv2_content_type = $form_state['values']['tv2_content_type'];
  14. }
  15. $options = tripal_chado_get_tripal_v2_content_type_options(TRUE);
  16. $form['tv2_content_type'] = array(
  17. '#type' => 'select',
  18. '#title' => 'Tripal v2 Content Type',
  19. '#description' => t('Select the Tripal v2 content type to migrate.'),
  20. '#options' => $options,
  21. '#default_value' => $tv2_content_type,
  22. '#ajax' => array(
  23. 'callback' => "tripal_chado_migrate_form_ajax_callback",
  24. 'wrapper' => "tripal-chado-migrate-form",
  25. 'effect' => 'fade',
  26. 'method' => 'replace'
  27. ),
  28. );
  29. // Add a review button that allows reviewing migratable content types
  30. if ($tv2_content_type != 'all') {
  31. $table = str_replace('chado_', '', $tv2_content_type);
  32. $schema = chado_get_schema($table);
  33. $pkey = $schema['primary key'][0];
  34. $fkeys = $schema['foreign keys'];
  35. $form['tv3_content_type'] = array(
  36. '#type' => 'fieldset',
  37. '#title' => 'Tripal v3 Content Type',
  38. '#description' => "Click the 'Get Tripal v3 Types' button to retrieve a list of Tripal v3
  39. content types to which this Tripal v2 type can be converted. This may take a while
  40. depending on the size of your database. The number of items to be converted is
  41. shown beside the type."
  42. );
  43. $form['tv3_content_type']['get_v3_type_btn'] = array(
  44. '#type' => 'button',
  45. '#name' => 'get_v3_type_btn',
  46. '#value' => "Get Tripal v3 Types",
  47. '#ajax' => array(
  48. 'callback' => "tripal_chado_migrate_form_ajax_callback",
  49. 'wrapper' => "tripal-chado-migrate-form",
  50. 'effect' => 'fade',
  51. 'method' => 'replace'
  52. ),
  53. );
  54. $no_data = TRUE;
  55. if ($form_state['clicked_button']['#name'] == 'get_v3_type_btn') {
  56. // Migrate all
  57. $form['tv3_content_type']['tv3_migrate_all'] = array(
  58. '#type' => 'checkbox',
  59. '#title' => 'Migrate All'
  60. );
  61. // Migrate selection only
  62. if (key_exists('cvterm', $fkeys) && key_exists('type_id', $fkeys['cvterm']['columns'])) {
  63. // Get all Tripal v2 node types from the chad_* linking table
  64. $sql =
  65. "SELECT V.name AS type, X.accession, db.name AS namespace , count(*) AS num
  66. FROM {" . $table . "} T
  67. INNER JOIN public.$tv2_content_type CT ON T.$pkey = CT.$pkey
  68. INNER JOIN {cvterm} V ON V.cvterm_id = T.type_id
  69. INNER JOIN {dbxref} X ON X.dbxref_id = V.dbxref_id
  70. INNER JOIN {db} ON db.db_id = X.db_id
  71. LEFT JOIN public.chado_entity CE ON CE.record_id = T.$pkey
  72. AND CE.data_table = '$table'
  73. WHERE CE.record_id IS NULL
  74. GROUP BY V.name, X.accession, db.name";
  75. $tv3_content_types = chado_query($sql);
  76. while($tv3_content_type = $tv3_content_types->fetchObject()) {
  77. // We need to store namespace/accession/type for each checkbox in the key becuase
  78. // the value only allows 1 or 0
  79. $key = urlencode(
  80. 'tv3_content_type--' .
  81. $tv3_content_type->namespace . '--' .
  82. $tv3_content_type->accession . '--' .
  83. $tv3_content_type->type);
  84. $form['tv3_content_type'][$key] = array(
  85. '#type' => 'checkbox',
  86. '#title' => $tv3_content_type->type . ' (' . $tv3_content_type->num . ')',
  87. );
  88. $no_data = FALSE;
  89. }
  90. }
  91. else if ($table == 'organism') {
  92. $sql =
  93. "SELECT count(*)
  94. FROM {organism} O
  95. INNER JOIN public.chado_organism CO ON O.organism_id = CO.organism_id
  96. LEFT JOIN public.chado_entity CE ON CE.record_id = O.organism_id
  97. AND CE.data_table = 'organism'
  98. WHERE CE.record_id IS NULL";
  99. $org_count = chado_query($sql)->fetchField();
  100. if ($org_count > 0) {
  101. $key = urldecode('tv3_content_type--local--organism--organism');
  102. $form['tv3_content_type'][$key] = array(
  103. '#type' => 'checkbox',
  104. '#title' => 'Organism (' . $org_count . ')',
  105. );
  106. $no_data = FALSE;
  107. }
  108. }
  109. else if ($table == 'analysis') {
  110. $sql =
  111. "SELECT count(*)
  112. FROM {analysis} A
  113. INNER JOIN public.chado_analysis CA ON A.analysis_id = CA.analysis_id
  114. LEFT JOIN public.chado_entity CE ON CE.record_id = A.analysis_id
  115. AND CE.data_table = 'analysis'
  116. WHERE CE.record_id IS NULL";
  117. $ana_count = chado_query($sql)->fetchField();
  118. if ($ana_count > 0) {
  119. $key = urlencode('tv3_content_type--local--analysis--analysis');
  120. $form['tv3_content_type'][$key] = array(
  121. '#type' => 'checkbox',
  122. '#title' => 'Analysis (' . $ana_count . ')',
  123. );
  124. $no_data = FALSE;
  125. }
  126. }
  127. if ($no_data) {
  128. unset($form['tv3_content_type']['tv3_migrate_all']);
  129. drupal_set_message('No data for migration or all have been migrated.', 'warning');
  130. }
  131. }
  132. }
  133. // Submit button
  134. if ($tv2_content_type == 'all' || key_exists('tv3_migrate_all', $form['tv3_content_type'])) {
  135. $form['migrate_btn'] = array(
  136. '#type' => 'submit',
  137. '#name' => 'migrate_btn',
  138. '#value' => "Migrate $options[$tv2_content_type]",
  139. );
  140. }
  141. $form['#prefix'] = '<div id="tripal-chado-migrate-form">';
  142. $form['#suffix'] = '</div>';
  143. return $form;
  144. }
  145. /**
  146. * Implements hook_validate()
  147. *
  148. * @param $form
  149. * @param $form_state
  150. */
  151. function tripal_chado_migrate_form_validate($form, &$form_state) {
  152. }
  153. /**
  154. * Implements hook_submit()
  155. *
  156. * By submiting the form, a Tripal job to migrate Tripal v2 content is submitted
  157. *
  158. * @param $form
  159. * @param $form_state
  160. */
  161. function tripal_chado_migrate_form_submit($form, &$form_state) {
  162. if ($form_state['clicked_button']['#name'] == 'migrate_btn') {
  163. global $user;
  164. $values = $form_state['values'];
  165. $tv2_content_type = $form_state['values']['tv2_content_type'];
  166. $tv3_content_type = array();
  167. foreach ($values AS $key => $value) {
  168. if ($tv2_content_type != 'all') {
  169. $key = urldecode($key);
  170. if (preg_match('/^tv3_content_type--(.+)--(.+)--(.+)/', $key, $matches) &&
  171. ($value == 1 || $values['tv3_migrate_all'] == 1)) {
  172. $namespace = $matches[1];
  173. $accession = $matches[2];
  174. $type = $matches[3];
  175. $tv3_content_type [] = array(
  176. 'namespace' => $namespace,
  177. 'accession' => $accession,
  178. 'term_name' => $type
  179. );
  180. }
  181. }
  182. }
  183. // Submit a job to migrate content
  184. global $user;
  185. $args = array(
  186. array(
  187. 'tv2_content_type' => $tv2_content_type,
  188. 'tv3_content_type' => $tv3_content_type
  189. )
  190. );
  191. $includes = array(
  192. module_load_include('inc', 'tripal_chado', 'includes/tripal_chado.migrate'),
  193. );
  194. if ($tv2_content_type == 'all' || count($tv3_content_type) != 0) {
  195. return tripal_add_job("Migrate $tv2_content_type Tripal v2 content.",
  196. 'tripal_chado', 'tripal_chado_migrate_records', $args, $user->uid, 10, $includes);
  197. }
  198. else {
  199. return drupal_set_message('Nothing to do. All data have been migrated or no data for migration.');
  200. }
  201. }
  202. }
  203. /**
  204. * Ajax call back that returns the entire form
  205. *
  206. * The callback is triggered by ajax elements on the form which leads to the update of
  207. * entire form according to the values set on the form
  208. *
  209. * @param $form
  210. * @param $form_state
  211. * @return $form
  212. */
  213. function tripal_chado_migrate_form_ajax_callback($form, $form_state) {
  214. return $form;
  215. }
  216. /**
  217. * Get available Tripal v2 content types
  218. *
  219. * @param boolean $all_option
  220. * Include an 'all' option in the returned array
  221. * @return string[]
  222. * Return a string array keyed by the node type
  223. */
  224. function tripal_chado_get_tripal_v2_content_type_options($all_option = FALSE) {
  225. // Get all available Tripal v2 chado tables
  226. $sql =
  227. "SELECT table_name
  228. FROM information_schema.tables
  229. WHERE table_schema = 'public' AND table_name LIKE 'chado_%'";
  230. $result = db_query($sql);
  231. $tables = array();
  232. while ($field = $result->fetchField()) {
  233. $count = db_query("SELECT count(*) FROM $field")->fetchField();
  234. if ($count != 0) {
  235. array_push($tables, $field);
  236. }
  237. }
  238. // List all available Tripal v2 content types
  239. $result = db_select('node_type', 'nt')
  240. ->fields('nt', array('type', 'name', 'description'))
  241. ->condition('type', 'chado_%', 'LIKE')
  242. ->execute();
  243. $options = array();
  244. if ($all_option) {
  245. $options['all'] = 'All';
  246. }
  247. while ($obj = $result->fetchObject()) {
  248. if (in_array($obj->type, $tables)) {
  249. $options[$obj->type] = $obj->name;
  250. }
  251. }
  252. return $options;
  253. }
  254. /**
  255. * Tripal job callback to migrate Tripal v2 content into Tripal v3 content
  256. *
  257. * @param $migration
  258. * @param $job_id
  259. */
  260. function tripal_chado_migrate_records($migration, $job_id = NULL) {
  261. $tv2_content_type = $migration['tv2_content_type'];
  262. $tv3_content_type = $migration['tv3_content_type'];
  263. // If tv2_content_type is 'all', migrate all existing Tripal v2 content
  264. if ($tv2_content_type == 'all') {
  265. print "Migrating all Tripal v2 content...\n";
  266. tripal_chado_migrate_all_types();
  267. }
  268. // Otherwise, migrate only selected Tripal v2 content
  269. else {
  270. print "Migrating selected Tripal v2 content...\n";
  271. tripal_chado_migrate_selected_types($tv3_content_type);
  272. }
  273. }
  274. /**
  275. * Migrate all Tripal v2 content types
  276. */
  277. function tripal_chado_migrate_all_types() {
  278. // Get all available Tripal v2 content types
  279. $tv2_content_types = tripal_chado_get_tripal_v2_content_type_options();
  280. $types = array();
  281. foreach($tv2_content_types AS $tv2_content_type => $value) {
  282. $table = str_replace('chado_', '', $tv2_content_type);
  283. $schema = chado_get_schema($table);
  284. $pkey = $schema['primary key'][0];
  285. $fkeys = $schema['foreign keys'];
  286. if (key_exists('cvterm', $fkeys) && key_exists('type_id', $fkeys['cvterm']['columns'])) {
  287. // Get all Tripal v2 node types from the chad_* linking table
  288. $sql = "
  289. SELECT V.name AS type, X.accession, db.name AS namespace
  290. FROM {" . $table . "} T
  291. INNER JOIN public.$tv2_content_type CT ON T.$pkey = CT.$pkey
  292. INNER JOIN {cvterm} V ON V.cvterm_id = T.type_id
  293. INNER JOIN {dbxref} X ON X.dbxref_id = V.dbxref_id
  294. INNER JOIN {db} ON db.db_id = X.db_id
  295. GROUP BY V.name, X.accession, db.name
  296. ";
  297. $tv3_content_types = chado_query($sql);
  298. while($tv3_content_type = $tv3_content_types->fetchObject()) {
  299. array_push($types, array(
  300. 'namespace' => $tv3_content_type->namespace,
  301. 'accession' => $tv3_content_type->accession,
  302. 'term_name' => $tv3_content_type->type
  303. ));
  304. }
  305. }
  306. else if ($table == 'organism') {
  307. array_push($types, array(
  308. 'namespace' => 'local',
  309. 'accession' => 'organism',
  310. 'term_name' => 'organism'
  311. ));
  312. }
  313. else if ($table == 'analysis') {
  314. array_push($types, array(
  315. 'namespace' => 'local',
  316. 'accession' => 'analysis',
  317. 'term_name' => 'analysis'
  318. ));
  319. }
  320. }
  321. tripal_chado_migrate_selected_types($types);
  322. }
  323. /**
  324. * Migrate only selected Tripal v2 content types
  325. *
  326. * @param unknown $tv3_content_type
  327. */
  328. function tripal_chado_migrate_selected_types($tv3_content_types) {
  329. foreach ($tv3_content_types AS $tv3_content_type) {
  330. // Check if the term already exists
  331. $term = tripal_load_term_entity($tv3_content_type);
  332. // If term doesn't exist, create a new bundle for this term
  333. if (!$term) {
  334. print("Creating bundle for term '" . $tv3_content_type['term_name'] . "'...\n");
  335. $success = tripal_create_bundle($tv3_content_type['namespace'], $tv3_content_type['accession'], $tv3_content_type['term_name']);
  336. $term = tripal_load_term_entity($tv3_content_type);
  337. }
  338. // Create bundle name
  339. $bundle_name = 'bio_data_' . $term->id;
  340. // Publish records for the bundle
  341. $value = array(
  342. 'sync_node' => 1,
  343. 'bundle_name' => $bundle_name
  344. );
  345. tripal_chado_publish_records ($value);
  346. }
  347. }