tripal_chado.migrate.inc 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276
  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. $form['overview_vert_tabs'] = [
  12. '#type' => 'vertical_tabs',
  13. ];
  14. $form['overview_vert_tabs']['#default_tab'] = key_exists('tripal_migrate_current_tab', $_SESSION) ? $_SESSION['tripal_migrate_current_tab'] : 'edit-step1';
  15. $form['instructions'] = [
  16. '#type' => 'item',
  17. '#markup' => t('Here you may migrate Tripal v2 content types to Tripal v3
  18. content types. The migration process is divided into four steps that
  19. allow you to migrate your site as your own pace. Please click each
  20. step below for details as to the purpose of the step. When all steps
  21. are completed your site will be fully Tripal v3 compatible.'),
  22. '#weight' => -100,
  23. ];
  24. // Step 1
  25. $form['step1'] = [
  26. '#type' => 'fieldset',
  27. '#title' => 'Step1',
  28. '#description' => '<b>Enable Legacy Support</b>',
  29. '#collapsible' => TRUE,
  30. '#collapsed' => TRUE,
  31. '#group' => 'overview_vert_tabs',
  32. ];
  33. global $base_url;
  34. $mod_url = '/admin/modules';
  35. $form['step1']['step1_content'] = [
  36. '#markup' => 'Tripal legacy modules are needed to support the display of Tripal v2
  37. content types. Review and ' . l('enable modules', $mod_url) . ' in the \'Tripal v2 Legacy\' category
  38. for legacy content support. Only content types for enabled legacy
  39. moodules can be migrated',
  40. ];
  41. // Step 2
  42. $form['step2'] = [
  43. '#type' => 'fieldset',
  44. '#title' => 'Step2',
  45. '#description' => '<b>Migrate Content</b>',
  46. '#collapsible' => TRUE,
  47. '#collapsed' => TRUE,
  48. '#group' => 'overview_vert_tabs',
  49. ];
  50. $form['step2']['step2_container'] = [
  51. '#type' => 'container',
  52. '#collapsible' => FALSE,
  53. '#prefix' => '<div id="tripal-chado-migrate-form-step2">',
  54. '#suffix' => '</div>',
  55. ];
  56. $form['step2']['step2_container']['instructions'] = [
  57. '#type' => 'item',
  58. '#markup' => t('Here you can migrate Tripal v2 content types to Tripal v3
  59. content types. This will not destroy or remove existing Tripal v2 pages
  60. but will creatte new Tripal v3 pages. This allows you to keep existing
  61. pages while reviewing and customizing the Tripal v3 content types. Site
  62. visitors can continue to visit the Tripal v2 pages. Tripal
  63. v3 content types may remain private while customization is underway.
  64. Once customization is completed a subsequent step will allow you to
  65. swap out Tripal v2 pages for the newer Tripal v3 pages. If you would like to
  66. use Trial v3 web services you must migrate content types.'),
  67. ];
  68. $tv2_content_type = 'all';
  69. if (array_key_exists('values', $form_state)) {
  70. $tv2_content_type = $form_state['values']['tv2_content_type'];
  71. }
  72. $tv2_options = tripal_chado_get_tripal_v2_content_type_options(TRUE);
  73. $form['step2']['step2_container']['tv2_content_type'] = [
  74. '#type' => 'select',
  75. '#title' => 'Tripal v2 Content Type',
  76. '#description' => t('Select the Tripal v2 content type to migrate.'),
  77. '#options' => $tv2_options,
  78. '#default_value' => $tv2_content_type,
  79. '#ajax' => [
  80. 'callback' => "tripal_chado_migrate_form_step2_ajax_callback",
  81. 'wrapper' => "tripal-chado-migrate-form-step2",
  82. 'effect' => 'fade',
  83. 'method' => 'replace',
  84. ],
  85. ];
  86. // Add a review button that allows reviewing migratable content types
  87. if ($tv2_content_type != 'all') {
  88. $table = str_replace('chado_', '', $tv2_content_type);
  89. $schema = chado_get_schema($table);
  90. $pkey = $schema['primary key'][0];
  91. $fkeys = $schema['foreign keys'];
  92. $form['step2']['step2_container']['tv3_content_type'] = [
  93. '#type' => 'fieldset',
  94. '#title' => 'Tripal v3 Content Type',
  95. '#description' => "Click the 'Get Tripal v3 Types' button to retrieve a list of Tripal v3
  96. content types to which this Tripal v2 type can be converted. This may take a while
  97. depending on the size of your database. The number of items to be converted is
  98. shown beside the type.",
  99. ];
  100. $form['step2']['step2_container']['tv3_content_type']['get_v3_type_btn'] = [
  101. '#type' => 'button',
  102. '#name' => 'get_v3_type_btn',
  103. '#value' => "Get Tripal v3 Types",
  104. '#ajax' => [
  105. 'callback' => "tripal_chado_migrate_form_step2_ajax_callback",
  106. 'wrapper' => "tripal-chado-migrate-form-step2",
  107. 'effect' => 'fade',
  108. 'method' => 'replace',
  109. ],
  110. ];
  111. $no_data = TRUE;
  112. if ($form_state['clicked_button']['#name'] == 'get_v3_type_btn') {
  113. // Migrate all
  114. $form['step2']['step2_container']['tv3_content_type']['tv3_migrate_all'] = [
  115. '#type' => 'checkbox',
  116. '#title' => 'Migrate All',
  117. ];
  118. // Migrate selection only
  119. if ($table == 'organism') {
  120. $sql =
  121. "SELECT count(*)
  122. FROM {organism} O
  123. INNER JOIN [chado_organism] CO ON O.organism_id = CO.organism_id
  124. ";
  125. $org_count = chado_query($sql)->fetchField();
  126. if ($org_count > 0) {
  127. $key = urldecode('tv3_content_type--OBI--0100026--organism');
  128. $form['step2']['step2_container']['tv3_content_type'][$key] = [
  129. '#type' => 'checkbox',
  130. '#title' => 'Organism (' . $org_count . ')',
  131. ];
  132. $no_data = FALSE;
  133. }
  134. }
  135. else {
  136. if ($table == 'analysis') {
  137. $sql =
  138. "SELECT count(*)
  139. FROM {analysis} A
  140. INNER JOIN [chado_analysis] CA ON A.analysis_id = CA.analysis_id
  141. ";
  142. $ana_count = chado_query($sql)->fetchField();
  143. if ($ana_count > 0) {
  144. $key = urlencode('tv3_content_type--operation--2945--analysis');
  145. $form['step2']['step2_container']['tv3_content_type'][$key] = [
  146. '#type' => 'checkbox',
  147. '#title' => 'Analysis (' . $ana_count . ')',
  148. ];
  149. $no_data = FALSE;
  150. }
  151. }
  152. else {
  153. if ($table == 'project') {
  154. $sql =
  155. "SELECT count(*)
  156. FROM {project} P
  157. INNER JOIN [chado_project] CP ON P.project_id = CP.project_id
  158. ";
  159. $proj_count = chado_query($sql)->fetchField();
  160. if ($proj_count > 0) {
  161. $key = urlencode('tv3_content_type--local--project--project');
  162. $form['step2']['step2_container']['tv3_content_type'][$key] = [
  163. '#type' => 'checkbox',
  164. '#title' => 'Project (' . $proj_count . ')',
  165. ];
  166. $no_data = FALSE;
  167. }
  168. }
  169. else {
  170. if ($table == 'featuremap') {
  171. $sql =
  172. "SELECT count(*)
  173. FROM {featuremap} M
  174. INNER JOIN [chado_featuremap] CM ON M.featuremap_id = CM.featuremap_id
  175. ";
  176. $map_count = chado_query($sql)->fetchField();
  177. if ($map_count > 0) {
  178. $key = urlencode('tv3_content_type--data--1274--map');
  179. $form['step2']['step2_container']['tv3_content_type'][$key] = [
  180. '#type' => 'checkbox',
  181. '#title' => 'Map (' . $map_count . ')',
  182. ];
  183. $no_data = FALSE;
  184. }
  185. }
  186. else {
  187. if ($table == 'pub') {
  188. $sql =
  189. "SELECT count(*)
  190. FROM {pub} P
  191. INNER JOIN [chado_pub] CP ON P.pub_id = CP.pub_id
  192. ";
  193. $proj_count = chado_query($sql)->fetchField();
  194. if ($proj_count > 0) {
  195. $key = urlencode('tv3_content_type--TPUB--0000002--Publication');
  196. $form['step2']['step2_container']['tv3_content_type'][$key] = [
  197. '#type' => 'checkbox',
  198. '#title' => 'Publication (' . $proj_count . ')',
  199. ];
  200. $no_data = FALSE;
  201. }
  202. }
  203. else {
  204. if ($table == 'biomaterial') {
  205. $sql =
  206. "SELECT count(*)
  207. FROM {biomaterial} B
  208. INNER JOIN [chado_biomaterial] CB ON B.biomaterial_id = CB.biomaterial_id
  209. ";
  210. $bm_count = chado_query($sql)->fetchField();
  211. if ($bm_count > 0) {
  212. $key = urlencode('tv3_content_type--sep--1095--biological sample');
  213. $form['step2']['step2_container']['tv3_content_type'][$key] = [
  214. '#type' => 'checkbox',
  215. '#title' => 'Biomaterial (' . $bm_count . ')',
  216. ];
  217. $no_data = FALSE;
  218. }
  219. }
  220. else {
  221. if (key_exists('cvterm', $fkeys) && key_exists('type_id', $fkeys['cvterm']['columns'])) {
  222. // Get all Tripal v2 node types from the chad_* linking table
  223. $sql =
  224. "SELECT V.name AS type, X.accession, db.name AS vocabulary , count(*) AS num
  225. FROM {" . $table . "} T
  226. INNER JOIN [" . $tv2_content_type . "] CT ON T.$pkey = CT.$pkey
  227. INNER JOIN {cvterm} V ON V.cvterm_id = T.type_id
  228. INNER JOIN {dbxref} X ON X.dbxref_id = V.dbxref_id
  229. INNER JOIN {db} ON db.db_id = X.db_id
  230. GROUP BY V.name, X.accession, db.name";
  231. $tv3_content_types = chado_query($sql);
  232. while ($tv3_content_type = $tv3_content_types->fetchObject()) {
  233. // We need to store vocabulary/accession/type for each checkbox in the key becuase
  234. // the value only allows 1 or 0
  235. $key = urlencode(
  236. 'tv3_content_type--' .
  237. $tv3_content_type->vocabulary . '--' .
  238. $tv3_content_type->accession . '--' .
  239. $tv3_content_type->type);
  240. $form['step2']['step2_container']['tv3_content_type'][$key] = [
  241. '#type' => 'checkbox',
  242. '#title' => $tv3_content_type->type . ' (' . $tv3_content_type->num . ')',
  243. ];
  244. $no_data = FALSE;
  245. }
  246. }
  247. }
  248. }
  249. }
  250. }
  251. }
  252. }
  253. if ($no_data) {
  254. unset($form['step2']['step2_container']['tv3_content_type']['tv3_migrate_all']);
  255. drupal_set_message('No data for migration or all have been migrated.', 'warning');
  256. }
  257. }
  258. }
  259. // Migrate button
  260. if ($tv2_content_type == 'all' || key_exists('tv3_migrate_all', $form['step2']['step2_container']['tv3_content_type'])) {
  261. $form['step2']['step2_container']['migrate_btn'] = [
  262. '#type' => 'submit',
  263. '#name' => 'migrate_btn',
  264. '#value' => "Migrate $tv2_options[$tv2_content_type]",
  265. ];
  266. // Disable the migration if all have been done
  267. if (count($tv2_options) == 1 && key_exists('all', $tv2_options)) {
  268. $form['step2']['step2_container']['migrate_btn']['#disabled'] = 1;
  269. }
  270. }
  271. // Step 3
  272. $form['step3'] = [
  273. '#type' => 'fieldset',
  274. '#title' => 'Step3',
  275. '#description' => '<b>Use Legacy Templates (optional)</b>',
  276. '#collapsible' => TRUE,
  277. '#collapsed' => TRUE,
  278. '#group' => 'overview_vert_tabs',
  279. ];
  280. $form['step3']['instructions'] = [
  281. '#type' => 'item',
  282. '#markup' => t('Once content types have been migrated you have the option
  283. to use the Tripal v2 display templates. Tripal v3 allows you to
  284. customize the page layout using a web interface whereas Tripal v2
  285. required programatic changes to template files. If your site has
  286. considerable Tripal v2 customizations that you do not
  287. want to lose you can use the legacy templates by checking the box
  288. for the desired content types below.'),
  289. ];
  290. // Get a list of enabled legacy modules with tv2 templates
  291. $enabled_templates = variable_get('tripal_chado_enabled_legacy_templates', []);
  292. $info = module_invoke_all('node_info');
  293. $options = tripal_chado_get_tripal_v2_content_type_options(FALSE, TRUE);
  294. foreach ($options AS $type_name => $type_label) {
  295. $title = $type_label;
  296. if ($type_name != 'all' and !key_exists($type_name, $info)) {
  297. $title .= " <strong>(please enable the $type_name legacy module).</strong>";
  298. }
  299. $form ['step3']['legacy_template--' . $type_name] = [
  300. '#type' => 'checkbox',
  301. '#title' => $title,
  302. '#default_value' => key_exists('legacy_template--' . $type_name, $enabled_templates) ? $enabled_templates['legacy_template--' . $type_name] : 0,
  303. ];
  304. }
  305. $form['step3']['save_btn'] = [
  306. '#type' => 'submit',
  307. '#name' => 'save_enabled_template_btn',
  308. '#value' => "Save",
  309. ];
  310. // Step 4
  311. $form['step4'] = [
  312. '#type' => 'fieldset',
  313. '#title' => 'Step4',
  314. '#description' => '<b>Complete Migration</b>',
  315. '#collapsible' => TRUE,
  316. '#collapsed' => TRUE,
  317. '#group' => 'overview_vert_tabs',
  318. ];
  319. $form['step4']['instructions'] = [
  320. '#type' => 'item',
  321. '#markup' => t('This step allows you to fully switch to Tripal v3 pages.
  322. You can move URLs and titles from Tripal v2 pages to their
  323. corresponding Tripal v3 pages. This ensures user bookmarks and external
  324. links to your site are not broken. Here you can also unpublish Tripal
  325. v2 content types or completely remove them if desired. You can
  326. perform these action in stages such as first moving titles and URLs,
  327. then unpublishing Tripal v2 pages and once the migration has been
  328. verified you can finally delete the Tripal v2 pages to free space.
  329. Deleting the Tripal v2 content will not delete the data in Chado.
  330. The page is simply removed from the site.'),
  331. ];
  332. $form['step4']['warning'] = [
  333. '#type' => 'item',
  334. '#markup' => tripal_set_message('Any of the following options cannot be
  335. undone. Also, please be sure you have migrated all
  336. desired content types in Step 2 prior to deleting the Tripal v2
  337. contents.', TRIPAL_WARNING, ['return_html' => TRUE]),
  338. ];
  339. $opt_complete_migration = [
  340. 'cp_title' => 'Copy Title over to Tripal v3 Content',
  341. 'mv_url' => 'Migrate URL Alias to Tripal v3 Content',
  342. 'unpublish' => 'Unpublish Tripal v2 Content',
  343. 'delete' => 'Delete Tripal v2 Content',
  344. ];
  345. if (count($tv2_options) == 1 && key_exists('all', $tv2_options)) {
  346. $form['step4']['complete'] = [
  347. '#markup' => 'Migration completed. All content have been migrated.',
  348. ];
  349. }
  350. else {
  351. foreach ($tv2_options AS $opt_key => $opt) {
  352. $form['step4'][$opt_key . '_title'] = [
  353. '#markup' => "<b>$opt</b>",
  354. ];
  355. $form['step4']['complete_migration--' . $opt_key] = [
  356. '#type' => 'checkboxes',
  357. '#options' => $opt_complete_migration,
  358. ];
  359. }
  360. $form['step4']['submit_btn'] = [
  361. '#type' => 'submit',
  362. '#name' => 'complete_migration_btn',
  363. '#value' => "Submit",
  364. ];
  365. }
  366. return $form;
  367. }
  368. /**
  369. * Implements hook_validate()
  370. *
  371. * @param $form
  372. * @param $form_state
  373. */
  374. function tripal_chado_migrate_form_validate($form, &$form_state) {
  375. }
  376. /**
  377. * Implements hook_submit()
  378. *
  379. * By submiting the form, a Tripal job to migrate Tripal v2 content is submitted
  380. *
  381. * @param $form
  382. * @param $form_state
  383. */
  384. function tripal_chado_migrate_form_submit($form, &$form_state) {
  385. // Store the legacy template setting in a Drupal variable
  386. if ($form_state['clicked_button']['#name'] == 'save_enabled_template_btn') {
  387. $values = $form_state['values'];
  388. $enabled_templates = [];
  389. foreach ($values AS $key => $value) {
  390. if (preg_match('/^legacy_template--/', $key)) {
  391. $enabled_templates[$key] = $value;
  392. }
  393. }
  394. variable_set('tripal_chado_enabled_legacy_templates', $enabled_templates);
  395. drupal_theme_rebuild();
  396. $_SESSION['tripal_migrate_current_tab'] = 'edit-step3';
  397. }
  398. // Complete migration
  399. else {
  400. if ($form_state['clicked_button']['#name'] == 'complete_migration_btn') {
  401. $values = $form_state['values'];
  402. $config = [
  403. 'delete' => [],
  404. 'unpublish' => [],
  405. 'cp_title' => [],
  406. 'mv_url' => [],
  407. ];
  408. $all = [];
  409. $all_types = [];
  410. // Gather checked checkboxes and store in the $config array
  411. foreach ($values AS $key => $value) {
  412. if (preg_match('/^complete_migration--/', $key)) {
  413. $type = str_replace('complete_migration--', '', $key);
  414. if ($type != 'all') {
  415. array_push($all_types, $type);
  416. }
  417. foreach ($value AS $key_op => $op) {
  418. if ($type == 'all') {
  419. if ($op) {
  420. array_push($all, $key_op);
  421. }
  422. }
  423. else {
  424. if ($op) {
  425. array_push($config[$key_op], $type);
  426. }
  427. }
  428. }
  429. }
  430. }
  431. foreach ($all AS $a) {
  432. $config[$a] = $all_types;
  433. }
  434. // Submit jobs to complete the migration
  435. global $user;
  436. $includes = [
  437. module_load_include('inc', 'tripal_chado', 'includes/tripal_chado.migrate'),
  438. ];
  439. if (count($config['cp_title']) > 0) {
  440. $args = [$config['cp_title']];
  441. tripal_add_job("Copy Title over to Tripal v3 Content", 'tripal_chado',
  442. 'tripal_chado_copy_title_for_selected_types', $args, $user->uid, 10, $includes);
  443. }
  444. if (count($config['mv_url']) > 0) {
  445. $args = [$config['mv_url']];
  446. tripal_add_job(" Migrate URL Alias to Tripal v3 Content ", 'tripal_chado',
  447. 'tripal_chado_migrate_url_alias_for_selected_types', $args, $user->uid, 10, $includes);
  448. }
  449. if (count($config['unpublish']) > 0) {
  450. $args = [$config['unpublish']];
  451. tripal_add_job(" Unpublish Tripal v2 Content ", 'tripal_chado',
  452. 'tripal_chado_unpublish_selected_types', $args, $user->uid, 10, $includes);
  453. }
  454. if (count($config['delete']) > 0) {
  455. $args = [$config['delete']];
  456. tripal_add_job("Delete Tripal v2 Content ", 'tripal_chado',
  457. 'tripal_chado_delete_selected_types', $args, $user->uid, 10, $includes);
  458. }
  459. $_SESSION['tripal_migrate_current_tab'] = 'edit-step4';
  460. return;
  461. }
  462. // Migrate tv2 content to tv3 content
  463. else {
  464. if ($form_state['clicked_button']['#name'] == 'migrate_btn') {
  465. global $user;
  466. $values = $form_state['values'];
  467. $tv2_content_type = $form_state['values']['tv2_content_type'];
  468. $tv3_content_type = [];
  469. foreach ($values AS $key => $value) {
  470. if ($tv2_content_type != 'all') {
  471. $key = urldecode($key);
  472. if (preg_match('/^tv3_content_type--(.+)--(.+)--(.+)/', $key, $matches) &&
  473. ($value == 1 || $values['tv3_migrate_all'] == 1)) {
  474. $vocabulary = $matches[1];
  475. $accession = $matches[2];
  476. $type = $matches[3];
  477. $table = str_replace('chado_', '', $tv2_content_type);
  478. $tv3_content_type [] = [
  479. 'vocabulary' => $vocabulary,
  480. 'accession' => $accession,
  481. 'term_name' => $type,
  482. 'storage_args' => [
  483. 'data_table' => $table,
  484. 'type_column' => db_field_exists('chado.' . $table, 'type_id') ? 'type_id' : '',
  485. ],
  486. ];
  487. }
  488. }
  489. }
  490. // Submit a job to migrate content
  491. global $user;
  492. $args = [
  493. [
  494. 'tv2_content_type' => $tv2_content_type,
  495. 'tv3_content_type' => $tv3_content_type,
  496. ],
  497. ];
  498. $includes = [
  499. module_load_include('inc', 'tripal_chado', 'includes/tripal_chado.migrate'),
  500. ];
  501. if ($tv2_content_type == 'all' || count($tv3_content_type) != 0) {
  502. return tripal_add_job("Migrate $tv2_content_type Tripal v2 content.",
  503. 'tripal_chado', 'tripal_chado_migrate_records', $args, $user->uid, 10, $includes);
  504. }
  505. else {
  506. return drupal_set_message('Nothing to do. All data have been migrated or no data for migration.');
  507. }
  508. $_SESSION['tripal_migrate_current_tab'] = 'edit-step2';
  509. }
  510. }
  511. }
  512. }
  513. /**
  514. * Ajax call back that returns the entire form
  515. *
  516. * The callback is triggered by ajax elements on the form which leads to the
  517. * update of entire form according to the values set on the form
  518. *
  519. * @param $form
  520. * @param $form_state
  521. *
  522. * @return $form
  523. */
  524. function tripal_chado_migrate_form_step2_ajax_callback(&$form, &$form_state) {
  525. return $form['step2']['step2_container'];
  526. }
  527. /**
  528. * Get available Tripal v2 content types
  529. *
  530. * @param boolean $all_option
  531. * Include an 'all' option in the returned array
  532. * @param boolean $has_template
  533. * Return TV2 content types only if it has a base template. This will exclude
  534. * TV2 content types such as Blast/Kegg/Interpro/Unigene which are all
  535. * converted into the TV3
  536. * 'Analysis' entity type
  537. *
  538. * @return string[]
  539. * Return a string array keyed by the node type
  540. */
  541. function tripal_chado_get_tripal_v2_content_type_options($all_option = FALSE, $has_template = FALSE) {
  542. // Get all available Tripal v2 chado tables
  543. $sql = "
  544. SELECT table_name
  545. FROM information_schema.tables
  546. WHERE table_schema = 'public' AND table_name LIKE 'chado_%'
  547. ";
  548. $result = db_query($sql);
  549. // Store 'chado_*' tables that has at least one node
  550. $tables = [];
  551. while ($field = $result->fetchField()) {
  552. $count = db_query("SELECT count(*) FROM $field LIMIT 1")->fetchField();
  553. if ($count != 0) {
  554. array_push($tables, $field);
  555. }
  556. }
  557. // List all available Tripal v2 content types
  558. $result = db_select('node_type', 'nt')
  559. ->fields('nt', ['type', 'name', 'description'])
  560. ->condition('type', 'chado_%', 'LIKE')
  561. ->execute();
  562. $options = [];
  563. if ($all_option) {
  564. $options['all'] = 'All';
  565. }
  566. while ($obj = $result->fetchObject()) {
  567. // Ignore analysis sub modules
  568. if ($has_template && !preg_match('/^chado_analysis_.+$/', $obj->type)) {
  569. $mod = str_replace('chado_', 'tripal_', $obj->type);
  570. $mod_dir = drupal_get_path('module', $mod);
  571. if (file_exists($mod_dir . '/theme/templates/' . $mod . '_base.tpl.php')) {
  572. $options[$obj->type] = $obj->name;
  573. }
  574. }
  575. else {
  576. if (in_array($obj->type, $tables)) {
  577. $options[$obj->type] = $obj->name;
  578. }
  579. }
  580. }
  581. return $options;
  582. }
  583. /**
  584. * Tripal job callback to migrate Tripal v2 content into Tripal v3 content
  585. *
  586. * @param $migration
  587. * @param $job_id
  588. */
  589. function tripal_chado_migrate_records($migration, $job_id = NULL) {
  590. $tv2_content_type = $migration['tv2_content_type'];
  591. $tv3_content_type = $migration['tv3_content_type'];
  592. // If tv2_content_type is 'all', migrate all existing Tripal v2 content
  593. if ($tv2_content_type == 'all') {
  594. print "Migrating all Tripal v2 content...\n";
  595. tripal_chado_migrate_all_types();
  596. }
  597. // Otherwise, migrate only selected Tripal v2 content
  598. else {
  599. print "Migrating selected Tripal v2 content...\n";
  600. tripal_chado_migrate_selected_types($tv3_content_type);
  601. }
  602. }
  603. /**
  604. * Migrate all Tripal v2 content types
  605. *
  606. * Gather all available Tripal v2 content types and store the result in an
  607. * associated array with values of vocabulary, accession, term_name. The array
  608. * is then pass to the function tripal_chado_migrate_selected_types() that
  609. * handles the migration.
  610. */
  611. function tripal_chado_migrate_all_types() {
  612. // Get all available Tripal v2 content types
  613. $tv2_content_types = tripal_chado_get_tripal_v2_content_type_options();
  614. $types = tripal_chado_migrate_map_types($tv2_content_types);
  615. tripal_chado_migrate_selected_types($types);
  616. }
  617. /**
  618. * Map all tv2_content_type to tv3_content_type
  619. *
  620. * @param unknown $tv2_content_type
  621. * return $tv3_content_type
  622. */
  623. function tripal_chado_migrate_map_types($tv2_content_types) {
  624. $types = [];
  625. foreach ($tv2_content_types AS $tv2_content_type => $value) {
  626. $table = str_replace('chado_', '', $tv2_content_type);
  627. $schema = chado_get_schema($table);
  628. $pkey = $schema['primary key'][0];
  629. $fkeys = $schema['foreign keys'];
  630. if ($table == 'organism') {
  631. array_push($types, [
  632. 'vocabulary' => 'OBI',
  633. 'accession' => '0100026',
  634. 'term_name' => 'organism',
  635. 'storage_args' => [
  636. 'data_table' => $table,
  637. ],
  638. ]);
  639. }
  640. else {
  641. if ($table == 'analysis') {
  642. array_push($types, [
  643. 'vocabulary' => 'operation',
  644. 'accession' => '2945',
  645. 'term_name' => 'Analysis',
  646. 'storage_args' => [
  647. 'data_table' => $table,
  648. ],
  649. ]);
  650. }
  651. else {
  652. if ($table == 'project') {
  653. array_push($types, [
  654. 'vocabulary' => 'local',
  655. 'accession' => 'project',
  656. 'term_name' => 'project',
  657. 'storage_args' => [
  658. 'data_table' => $table,
  659. ],
  660. ]);
  661. }
  662. else {
  663. if ($table == 'featuremap') {
  664. array_push($types, [
  665. 'vocabulary' => 'data',
  666. 'accession' => '1274',
  667. 'term_name' => 'map',
  668. 'storage_args' => [
  669. 'data_table' => $table,
  670. ],
  671. ]);
  672. }
  673. else {
  674. if ($table == 'pub') {
  675. array_push($types, [
  676. 'vocabulary' => 'TPUB',
  677. 'accession' => '0000002',
  678. 'term_name' => 'Publication',
  679. 'storage_args' => [
  680. 'data_table' => $table,
  681. ],
  682. ]);
  683. }
  684. else {
  685. if ($table == 'biomaterial') {
  686. array_push($types, [
  687. 'vocabulary' => 'sep',
  688. 'accession' => '1095',
  689. 'term_name' => 'biological sample',
  690. 'storage_args' => [
  691. 'data_table' => $table,
  692. ],
  693. ]);
  694. }
  695. else {
  696. if (key_exists('cvterm', $fkeys) && key_exists('type_id', $fkeys['cvterm']['columns'])) {
  697. // Get all Tripal v2 node types from the chad_* linking table
  698. $sql = "
  699. SELECT V.name AS type, X.accession, db.name AS vocabulary
  700. FROM {" . $table . "} T
  701. INNER JOIN [" . $tv2_content_type . "] CT ON T.$pkey = CT.$pkey
  702. INNER JOIN {cvterm} V ON V.cvterm_id = T.type_id
  703. INNER JOIN {dbxref} X ON X.dbxref_id = V.dbxref_id
  704. INNER JOIN {db} ON db.db_id = X.db_id
  705. GROUP BY V.name, X.accession, db.name
  706. ";
  707. $tv3_content_types = chado_query($sql);
  708. while ($tv3_content_type = $tv3_content_types->fetchObject()) {
  709. array_push($types, [
  710. 'vocabulary' => $tv3_content_type->vocabulary,
  711. 'accession' => $tv3_content_type->accession,
  712. 'term_name' => $tv3_content_type->type,
  713. 'storage_args' => [
  714. 'data_table' => $table,
  715. 'type_column' => db_field_exists('chado.' . $table, 'type_id') ? 'type_id' : '',
  716. ],
  717. ]);
  718. }
  719. }
  720. }
  721. }
  722. }
  723. }
  724. }
  725. }
  726. }
  727. return $types;
  728. }
  729. /**
  730. * Migrate only selected Tripal v2 content types
  731. *
  732. * @param unknown $tv3_content_type
  733. */
  734. function tripal_chado_migrate_selected_types($tv3_content_types) {
  735. // Initialize the population of the chado_cvterm_mapping table before migration.
  736. tripal_chado_map_cvterms();
  737. foreach ($tv3_content_types AS $tv3_content_type) {
  738. // Check if the term already exists
  739. $term = tripal_load_term_entity($tv3_content_type);
  740. // If term doesn't exist, create a new bundle for this term
  741. if (!$term) {
  742. print("Creating bundle for term '" . $tv3_content_type['term_name'] . "'...\n");
  743. $success = tripal_create_bundle($tv3_content_type);
  744. $term = tripal_load_term_entity($tv3_content_type);
  745. }
  746. // Create bundle name
  747. $bundle_name = 'bio_data_' . $term->id;
  748. // Publish records for the bundle
  749. $value = [
  750. 'sync_node' => 1,
  751. 'bundle_name' => $bundle_name,
  752. ];
  753. chado_publish_records($value);
  754. // Migrate Resource Titles/Blocks or Resource Links if available
  755. tripal_chado_migrate_resource_blocks($bundle_name);
  756. tripal_chado_migrate_resource_links($bundle_name);
  757. // Migrate organism images
  758. if ($term->name == 'organism') {
  759. tripal_chado_migrate_organism_images($bundle_name);
  760. }
  761. }
  762. }
  763. /**
  764. * Delete selected Tripal v2 content
  765. *
  766. * Delete all records from chado_* table then call the cleanup orphan nodes
  767. * function
  768. *
  769. * @param unknown $tv2_content_types
  770. */
  771. function tripal_chado_delete_selected_types($tv2_content_types = [], $job_id) {
  772. foreach ($tv2_content_types AS $type) {
  773. $sql = "DELETE FROM $type";
  774. db_query($sql);
  775. chado_cleanup_orphaned_nodes(str_replace('chado_', '', $type), 25000, NULL, NULL, $job_id);
  776. }
  777. }
  778. /**
  779. * Unpublish selected Tripal v2 content
  780. *
  781. * Set status = 0 (unpublished) for all nodes of selected Tripal v2 content
  782. * types
  783. *
  784. * @param unknown $tv2_content_types
  785. */
  786. function tripal_chado_unpublish_selected_types($tv2_content_types = [], $job_id) {
  787. foreach ($tv2_content_types AS $type) {
  788. $sql = "UPDATE node SET status = 0 WHERE nid IN (SELECT nid FROM $type)";
  789. db_query($sql);
  790. $sql = "UPDATE node_revision SET status = 0 WHERE nid IN (SELECT nid FROM $type)";
  791. db_query($sql);
  792. }
  793. }
  794. /**
  795. * Copy titles for selected Tripal v2 content
  796. *
  797. * Copy tiltles for all nodes of selected Tripal v2 content types
  798. *
  799. * @param unknown $tv2_content_types
  800. */
  801. function tripal_chado_copy_title_for_selected_types($tv2_content_types = [], $job_id) {
  802. foreach ($tv2_content_types AS $type) {
  803. $chado_table = str_replace('chado_', '', $type);
  804. $bio_data_tables = tripal_chado_migrate_get_biodata_tables($chado_table);
  805. foreach ($bio_data_tables AS $bio_data_table) {
  806. $sql = "SELECT nid, entity_id FROM $bio_data_table WHERE nid IN (SELECT nid FROM $type)";
  807. $result = db_query($sql);
  808. while ($entity = $result->fetchObject()) {
  809. $usql = "
  810. UPDATE tripal_entity
  811. SET title = (SELECT title FROM node WHERE nid = :nid)
  812. WHERE id = :entity_id";
  813. db_query($usql, [
  814. ':nid' => $entity->nid,
  815. ':entity_id' => $entity->entity_id,
  816. ]
  817. );
  818. }
  819. }
  820. }
  821. }
  822. /**
  823. * Migrate URL alias for selected Tripal v2 content
  824. *
  825. * Migrate URL alias for all nodes of selected Tripal v2 content types
  826. *
  827. * @param unknown $tv2_content_types
  828. */
  829. function tripal_chado_migrate_url_alias_for_selected_types($tv2_content_types = [], $job_id) {
  830. foreach ($tv2_content_types AS $type) {
  831. $chado_table = str_replace('chado_', '', $type);
  832. $bio_data_tables = tripal_chado_migrate_get_biodata_tables($chado_table);
  833. foreach ($bio_data_tables AS $bio_data_table) {
  834. $sql = "SELECT nid, entity_id FROM $bio_data_table WHERE nid IN (SELECT nid FROM $type)";
  835. $result = db_query($sql);
  836. while ($entity = $result->fetchObject()) {
  837. $usql = "
  838. UPDATE url_alias
  839. SET source = 'bio_data/" . $entity->entity_id .
  840. "' WHERE source = 'node/" . $entity->nid . "'";
  841. db_query($usql);
  842. }
  843. }
  844. }
  845. }
  846. /**
  847. * Migrate images for Tripal v2 organism content
  848. *
  849. * Migrate images for all chado_organism
  850. *
  851. */
  852. function tripal_chado_migrate_organism_images($bundle_name) {
  853. // Get all organism entities
  854. $bio_data_table = array_pop(tripal_chado_migrate_get_biodata_tables('organism'));
  855. $results =
  856. db_select($bio_data_table, 'ce')
  857. ->fields('ce', ['entity_id', 'record_id', 'nid'])
  858. ->execute();
  859. // Iterate through each organism entity
  860. while ($organism = $results->fetchObject()) {
  861. $nid = $organism->nid;
  862. $entity_id = $organism->entity_id;
  863. // check if there is a file record for the organism node
  864. $fid = db_select('file_usage', 'fu')
  865. ->fields('fu', ['fid'])
  866. ->condition('module', 'tripal_organism')
  867. ->condition('type', 'organism_image')
  868. ->condition('id', $nid)
  869. ->execute()
  870. ->fetchField();
  871. // check if the image was added using the old interface.
  872. if (!$fid) {
  873. $sql =
  874. "SELECT genus,species,nid
  875. FROM {organism} O
  876. INNER JOIN chado_organism CO ON O.organism_id = CO.organism_id
  877. WHERE O.organism_id = :organism_id";
  878. $chado_org = chado_query($sql, [':organism_id' => $organism->record_id])->fetchObject();
  879. if ($chado_org) {
  880. $base_path = realpath('.');
  881. $image_dir = tripal_get_files_dir('tripal_organism') . "/images";
  882. $image_name = $chado_org->genus . "_" . $chado_org->species . ".jpg";
  883. $image_path = "$base_path/$image_dir/$image_name";
  884. // image files are stored as 'genus_species.jpg'
  885. $file = NULL;
  886. if (file_exists($image_path)) {
  887. $handle = fopen($image_path, 'r');
  888. $file = file_save_data($handle, "public://$image_name");
  889. fclose($handle);
  890. }
  891. // last possible case: image files are stored as 'organism_id.jpg'
  892. else {
  893. $image_name = $chado_org->nid . ".jpg";
  894. $image_path = "$base_path/$image_dir/$image_name";
  895. if (file_exists($image_path)) {
  896. $handle = fopen($image_path, 'r');
  897. $file = file_save_data($handle, "public://$image_name");
  898. fclose($handle);
  899. }
  900. }
  901. if ($file) {
  902. tripal_chado_migrate_organism_image_add_file($file->fid, $entity_id, $bundle_name);
  903. }
  904. }
  905. }
  906. else {
  907. // If there is an image, add it to the organism entity
  908. tripal_chado_migrate_organism_image_add_file($fid, $entity_id, $bundle_name);
  909. }
  910. }
  911. }
  912. /**
  913. *
  914. * Add image file for the organism entity
  915. *
  916. * @param unknown $fid
  917. */
  918. function tripal_chado_migrate_organism_image_add_file($fid, $entity_id, $bundle_name) {
  919. if ($fid && $entity_id) {
  920. $file = file_load($fid);
  921. // Add a record to the file_usage table
  922. file_usage_add($file, 'file', 'TripalEntity', $entity_id);
  923. $image_file = (array) $file;
  924. // Attached it to the entity
  925. /*
  926. $entities = entity_load('TripalEntity', array($entity_id));
  927. $entity = $entities[$entity_id];
  928. $image = array(
  929. 'und' => array(
  930. 0 =>$image_file
  931. )
  932. );
  933. $entity->data__image = $image;
  934. field_attach_update('TripalEntity', $entity);
  935. entity_get_controller('TripalEntity')->resetCache(array($entity_id));
  936. */
  937. // Add a record to the field_data_data__image table
  938. $values = [
  939. 'entity_type' => 'TripalEntity',
  940. 'bundle' => $bundle_name,
  941. 'entity_id' => $entity_id,
  942. 'revision_id' => $entity_id,
  943. 'language' => 'und',
  944. 'delta' => 0,
  945. 'data__image_fid' => $fid,
  946. ];
  947. drupal_write_record('field_data_data__image', $values);
  948. }
  949. }
  950. /**
  951. * Retrieve chado_biodata_* table name
  952. *
  953. * @param string $chado_table
  954. * the chado_table where the record is stored
  955. *
  956. * @return
  957. * Return all chado_biodata_* table names mapping to a chado_table
  958. */
  959. function tripal_chado_migrate_get_biodata_tables($chado_table) {
  960. // To find the bundle_table, check if type_column is used for the chado_table
  961. $query = db_select('chado_bundle', 'cb');
  962. $query->join('tripal_bundle', 'tb', 'tb.id = cb.bundle_id');
  963. $query->fields('cb', ['data_table']);
  964. $query->fields('tb', ['name']);
  965. $query->condition('cb.data_table', $chado_table);
  966. $bundles = $query->execute();
  967. $tables = [];
  968. while ($bundle = $bundles->fetchObject()) {
  969. array_push($tables, 'chado_' . $bundle->name);
  970. }
  971. return $tables;
  972. }
  973. function tripal_chado_migrate_resource_blocks($bundle_name) {
  974. // Do not try to migrate resouce blocks and titles if they weren't set up
  975. if (!db_table_exists('field_revision_field_resource_titles') || !db_table_exists('field_revision_field_resource_blocks')) {
  976. return;
  977. }
  978. $entites =
  979. db_select('chado_' . $bundle_name, 'B')
  980. ->fields('B', ['nid'])
  981. ->execute();
  982. while ($nid = $entites->fetchField()) {
  983. // Only the latest revision is migrated
  984. $sql = "
  985. SELECT
  986. entity_id,
  987. max(revision_id) AS vid,
  988. delta,
  989. (SELECT field_resource_titles_value
  990. FROM field_revision_field_resource_titles
  991. WHERE entity_id = RT.entity_id
  992. AND revision_id = max(RT.revision_id)
  993. AND delta = RT.delta
  994. ),
  995. (SELECT field_resource_blocks_value
  996. FROM field_revision_field_resource_blocks
  997. WHERE entity_id = RT.entity_id
  998. AND revision_id = max(RT.revision_id)
  999. AND delta = RT.delta
  1000. )
  1001. FROM field_revision_field_resource_titles RT
  1002. WHERE RT.entity_id = :nid
  1003. GROUP BY entity_id, delta
  1004. ORDER BY RT.delta
  1005. ";
  1006. $results = db_query($sql, [':nid' => $nid]);
  1007. while ($resource = $results->fetchObject()) {
  1008. $title = $resource->field_resource_titles_value;
  1009. $content = $resource->field_resource_blocks_value;
  1010. $delta = $resource->delta;
  1011. $nid = $resource->entity_id;
  1012. $entity_id =
  1013. db_select('chado_' . $bundle_name, 'B')
  1014. ->fields('B', ['entity_id'])
  1015. ->condition('nid', $nid)
  1016. ->execute()
  1017. ->fetchField();
  1018. // field name: (can not be longer than 32 chars)
  1019. // bio_data_<i>_resource_<title to lower case/space replaced with _/first 10 chars>
  1020. $field_name = $bundle_name . '_rsc_' . substr(preg_replace('/\s+/', '_', strtolower($title)), 0, 15);
  1021. // Create a field if it does not exist
  1022. if (!field_info_field($field_name)) {
  1023. field_create_field([
  1024. 'field_name' => $field_name,
  1025. 'type' => 'text',
  1026. 'cardinality' => 1,
  1027. 'locked' => FALSE,
  1028. 'storage' => [
  1029. 'type' => 'field_sql_storage',
  1030. ],
  1031. 'settings' => [
  1032. 'max_length' => 10485760,
  1033. 'text_processing' => 1,
  1034. ],
  1035. ]);
  1036. }
  1037. // Create field instance for the bundle if it does not exist
  1038. if (!field_info_instance('TripalEntity', $field_name, $bundle_name)) {
  1039. field_create_instance([
  1040. 'field_name' => $field_name,
  1041. 'entity_type' => 'TripalEntity',
  1042. 'bundle' => $bundle_name,
  1043. 'label' => $title,
  1044. 'widget' => [
  1045. 'type' => 'text_textarea',
  1046. ],
  1047. 'display' => [
  1048. 'default' => [
  1049. 'label' => 'hidden',
  1050. ],
  1051. ],
  1052. 'settings' => [
  1053. 'text_processing' => 1,
  1054. 'format' => 'full_html',
  1055. 'term_vocabulary' => 'schema',
  1056. 'term_name' => 'comment',
  1057. 'term_accession' => 'comment',
  1058. ],
  1059. ]);
  1060. }
  1061. // Migrate the field content
  1062. $ftable = 'field_data_' . $field_name;
  1063. $frtable = 'field_revision_' . $field_name;
  1064. $fvalue = $field_name . '_value';
  1065. $fformat = $field_name . '_format';
  1066. try {
  1067. $sql = "
  1068. INSERT INTO $ftable (entity_type, bundle, entity_id, revision_id, language, delta, $fvalue, $fformat)
  1069. VALUES (:entity_type, :bundle, :entity_id, :revision_id, :language, :delta, :value, :format)
  1070. ";
  1071. db_query($sql,
  1072. [
  1073. ':entity_type' => 'TripalEntity',
  1074. ':bundle' => $bundle_name,
  1075. ':entity_id' => $entity_id,
  1076. 'revision_id' => $entity_id,
  1077. ':language' => 'und',
  1078. ':delta' => 0,
  1079. ':value' => $content,
  1080. ':format' => 'full_html',
  1081. ]
  1082. );
  1083. $rsql = "
  1084. INSERT INTO $frtable (entity_type, bundle, entity_id, revision_id, language, delta, $fvalue, $fformat)
  1085. VALUES (:entity_type, :bundle, :entity_id, :revision_id, :language, :delta, :value, :format)
  1086. ";
  1087. db_query($rsql,
  1088. [
  1089. ':entity_type' => 'TripalEntity',
  1090. ':bundle' => $bundle_name,
  1091. ':entity_id' => $entity_id,
  1092. 'revision_id' => $entity_id,
  1093. ':language' => 'und',
  1094. ':delta' => 0,
  1095. ':value' => $content,
  1096. ':format' => 'full_html',
  1097. ]
  1098. );
  1099. } catch (\PDOException $e) {
  1100. $error = $e->getMessage();
  1101. watchdog_exception('tripal_chado', $e);
  1102. }
  1103. }
  1104. }
  1105. }
  1106. function tripal_chado_migrate_resource_links($bundle_name) {
  1107. // Do not try to migrate resouce blocks and titles if they weren't set up
  1108. if (!db_table_exists('field_revision_field_resource_links')) {
  1109. return;
  1110. }
  1111. $entites =
  1112. db_select('chado_' . $bundle_name, 'B')
  1113. ->fields('B', ['nid'])
  1114. ->execute();
  1115. while ($nid = $entites->fetchField()) {
  1116. // Only the latest revision is migrated
  1117. $sql = "
  1118. SELECT
  1119. entity_id,
  1120. max(revision_id) AS vid,
  1121. delta,
  1122. (SELECT field_resource_links_value
  1123. FROM field_revision_field_resource_links
  1124. WHERE entity_id = RT.entity_id
  1125. AND revision_id = max(RT.revision_id)
  1126. AND delta = RT.delta
  1127. )
  1128. FROM field_revision_field_resource_links RT
  1129. WHERE RT.entity_id = :nid
  1130. GROUP BY entity_id, delta
  1131. ORDER BY RT.delta
  1132. ";
  1133. $results = db_query($sql, [':nid' => $nid]);
  1134. while ($resource = $results->fetchObject()) {
  1135. $values = explode('|', $resource->field_resource_links_value);
  1136. $title = $values[0];
  1137. $link = $values[1];
  1138. $delta = $resource->delta;
  1139. $nid = $resource->entity_id;
  1140. $entity_id =
  1141. db_select('chado_' . $bundle_name, 'B')
  1142. ->fields('B', ['entity_id'])
  1143. ->condition('nid', $nid)
  1144. ->execute()
  1145. ->fetchField();
  1146. // field name: (can not be longer than 32 chars)
  1147. // bio_data_<i>_resource_<title to lower case/space replaced with _/first 10 chars>
  1148. $field_name = $bundle_name . '_resource_links';
  1149. // Create a field if it does not exist
  1150. if (!field_info_field($field_name)) {
  1151. field_create_field([
  1152. 'field_name' => $field_name,
  1153. 'type' => 'link_field',
  1154. 'cardinality' => FIELD_CARDINALITY_UNLIMITED,
  1155. 'locked' => FALSE,
  1156. 'storage' => [
  1157. 'type' => 'field_sql_storage',
  1158. ],
  1159. 'settings' => [
  1160. ],
  1161. ]);
  1162. }
  1163. // Create field instance for the bundle if it does not exist.
  1164. if (!field_info_instance('TripalEntity', $field_name, $bundle_name)) {
  1165. field_create_instance([
  1166. 'field_name' => $field_name,
  1167. 'entity_type' => 'TripalEntity',
  1168. 'bundle' => $bundle_name,
  1169. 'label' => 'Links',
  1170. 'widget' => [
  1171. 'type' => 'link_field',
  1172. ],
  1173. 'display' => [
  1174. 'default' => [
  1175. 'label' => 'hidden',
  1176. ],
  1177. ],
  1178. 'settings' => [
  1179. 'term_vocabulary' => 'schema',
  1180. 'term_name' => 'url',
  1181. 'term_accession' => 'url',
  1182. 'absolute_url' => 0,
  1183. 'validate_url' => 0,
  1184. ],
  1185. ]);
  1186. }
  1187. // Migrate the field content
  1188. $ftable = 'field_data_' . $field_name;
  1189. $frtable = 'field_revision_' . $field_name;
  1190. $furl = $field_name . '_url';
  1191. $ftitle = $field_name . '_title';
  1192. try {
  1193. $sql = "
  1194. INSERT INTO $ftable (entity_type, bundle, entity_id, revision_id, language, delta, $furl, $ftitle)
  1195. VALUES (:entity_type, :bundle, :entity_id, :revision_id, :language, :delta, :url, :title)
  1196. ";
  1197. db_query($sql,
  1198. [
  1199. ':entity_type' => 'TripalEntity',
  1200. ':bundle' => $bundle_name,
  1201. ':entity_id' => $entity_id,
  1202. 'revision_id' => $entity_id,
  1203. ':language' => 'und',
  1204. ':delta' => $delta,
  1205. ':url' => $link,
  1206. ':title' => $title,
  1207. ]
  1208. );
  1209. $rsql = "
  1210. INSERT INTO $frtable (entity_type, bundle, entity_id, revision_id, language, delta, $furl, $ftitle)
  1211. VALUES (:entity_type, :bundle, :entity_id, :revision_id, :language, :delta, :url, :title)
  1212. ";
  1213. db_query($rsql,
  1214. [
  1215. ':entity_type' => 'TripalEntity',
  1216. ':bundle' => $bundle_name,
  1217. ':entity_id' => $entity_id,
  1218. 'revision_id' => $entity_id,
  1219. ':language' => 'und',
  1220. ':delta' => $delta,
  1221. ':url' => $link,
  1222. ':title' => $title,
  1223. ]
  1224. );
  1225. } catch (\PDOException $e) {
  1226. $error = $e->getMessage();
  1227. watchdog_exception('tripal_chado', $e);
  1228. }
  1229. }
  1230. }
  1231. }