tripal_pub.pub_importers.inc 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415
  1. <?php
  2. /**
  3. * @file
  4. * Management of importers
  5. */
  6. /**
  7. * A function to generate a table containing the list of publication importers
  8. *
  9. * @ingroup tripal_pub
  10. */
  11. function tripal_pub_importers_list() {
  12. // clear out the session variable when we view the list.
  13. unset($_SESSION['tripal_pub_import']);
  14. $header = array('', 'Importer Name', 'Database', 'Search String', 'Disabled', 'Create Contact', '');
  15. $rows = array();
  16. $importers = db_query("SELECT * FROM {tripal_pub_import} ORDER BY name");
  17. while ($importer = $importers->fetchObject()) {
  18. $criteria = unserialize($importer->criteria);
  19. $num_criteria = $criteria['num_criteria'];
  20. $criteria_str = '';
  21. for ($i = 1; $i <= $num_criteria; $i++) {
  22. $search_terms = $criteria['criteria'][$i]['search_terms'];
  23. $scope = $criteria['criteria'][$i]['scope'];
  24. $is_phrase = $criteria['criteria'][$i]['is_phrase'];
  25. $operation = $criteria['criteria'][$i]['operation'];
  26. $criteria_str .= "$operation ($scope: $search_terms) ";
  27. }
  28. $rows[] = array(
  29. array(
  30. 'data' => l(t('Edit/Test'), "admin/tripal/chado/tripal_pub/import/edit/$importer->pub_import_id") . '<br>' .
  31. l(t('Import Pubs'), "admin/tripal/chado/tripal_pub/import/submit/$importer->pub_import_id"),
  32. 'nowrap' => 'nowrap'
  33. ),
  34. $importer->name,
  35. $criteria['remote_db'],
  36. $criteria_str,
  37. $importer->disabled ? 'Yes' : 'No',
  38. $importer->do_contact ? 'Yes' : 'No',
  39. l(t('Delete'), "admin/tripal/chado/tripal_pub/import/delete/$importer->pub_import_id"),
  40. );
  41. }
  42. $page = "<ul class='action-links'>";
  43. $page .= ' <li>' . l('New Importer', 'admin/tripal/chado/tripal_pub/import/new') . '</li>';
  44. $page .= '</ul>';
  45. $page .= '<p>' . t(
  46. "A publication importer is used to create a set of search criteria that can be used
  47. to query a remote database, find publications that match the specified criteria
  48. and then import those publications into the Chado database. An example use case would
  49. be to peridocially add new publications to this Tripal site that have appeared in PubMed
  50. in the last 30 days. You can import publications in one of two ways:
  51. <ol>
  52. <li>Create a new importer by clicking the 'New Importer' link above, and after saving it should appear in the list below. Click the
  53. link labeled 'Import Pubs' to schedule a job to import the publications</li>
  54. <li>The first method only performs the import once. However, you can schedule the
  55. importer to run peridically by adding a cron job. See the " .
  56. l("Pub Module help instructions", "admin/tripal/chado/tripal_pub/help") . " to learn how to
  57. set the importers to run automatically.") . '</li>
  58. </ol><br>';
  59. $page .= theme('table', array('header' => $header, 'rows' => $rows));
  60. return $page;
  61. }
  62. /**
  63. * Creates the page that contains the publication importer setup form and
  64. * test results.
  65. *
  66. * @param $action
  67. * The action to perform
  68. * @param $pub_import_id
  69. * The importer ID
  70. *
  71. * @return
  72. * The HTML for the importer setup page
  73. *
  74. * @ingroup tripal_pub
  75. */
  76. function tripal_pub_importer_setup_page($action = 'new', $pub_import_id = NULL) {
  77. global $base_path;
  78. // make sure the tripal_pub and tripal_contact ontologies are loaded
  79. $values = array('name' => 'tripal_pub');
  80. $tpub_cv = chado_select_record('cv', array('cv_id'), $values);
  81. if (count($tpub_cv) == 0) {
  82. drupal_set_message(t('Before importing publications you must first ') . l(t('load the Tripal Pub Ontology'), 'admin/tripal/tripal_cv/obo_loader'), 'error');
  83. }
  84. $values = array('name' => 'tripal_contact');
  85. $tpub_cv = chado_select_record('cv', array('cv_id'), $values);
  86. if (count($tpub_cv) == 0) {
  87. drupal_set_message(t('If you want to create contact pages for authors, you must first ') . l(t('load the Tripal Contact Ontology'), 'admin/tripal/tripal_cv/obo_loader'), 'error');
  88. }
  89. if(!extension_loaded ('yaz')){
  90. drupal_set_message(t('<b>Note:</b> In order to create an importer using the USDA National Agricultural Library (AGL) you must install the yaz libraries. See the ') . l(t('Pub Module help page'), 'admin/tripal/chado/tripal_pub/help') . ' for assistance. If you do not want to use AGL you can ignore this warning.', 'warning');
  91. }
  92. // generate the search form
  93. $form = drupal_get_form('tripal_pub_importer_setup_form', $pub_import_id, $action);
  94. $output = l("Return to publication importers list", "admin/tripal/chado/tripal_pub/import_list");
  95. $output .= drupal_render($form);
  96. // retrieve any results
  97. if (array_key_exists('tripal_pub_import', $_SESSION)) {
  98. $remote_db = $_SESSION['tripal_pub_import']['remote_db'];
  99. $num_criteria = $_SESSION['tripal_pub_import']['num_criteria'];
  100. $days = $_SESSION['tripal_pub_import']['days'];
  101. $search_array = array();
  102. $search_array['remote_db'] = $remote_db;
  103. $search_array['num_criteria'] = $num_criteria;
  104. $search_array['days'] = $days;
  105. for ($i = 1; $i <= $num_criteria; $i++) {
  106. $search_array['criteria'][$i]['search_terms'] = $_SESSION['tripal_pub_import']['criteria'][$i]['search_terms'];
  107. $search_array['criteria'][$i]['scope'] = $_SESSION['tripal_pub_import']['criteria'][$i]['scope'];
  108. $search_array['criteria'][$i]['is_phrase'] = $_SESSION['tripal_pub_import']['criteria'][$i]['is_phrase'];
  109. $search_array['criteria'][$i]['operation'] = $_SESSION['tripal_pub_import']['criteria'][$i]['operation'];
  110. }
  111. // if the form has been submitted with the 'test' button then get the results
  112. if ($_SESSION['tripal_pub_import']['perform_search']) {
  113. $limit = 25;
  114. // get the list of publications from the remote database using the search criteria.
  115. $page = isset($_GET['page']) ? $_GET['page'] : '0';
  116. $results = tripal_get_remote_pubs($remote_db, $search_array, $limit, $page);
  117. $total_records = $results['total_records'];
  118. $search_str = $results['search_str'];
  119. $pubs = $results['pubs'];
  120. // iterate through the results and construct the table displaying the publications
  121. $rows = array();
  122. $i = $page * $limit + 1;
  123. if (count($pubs) > 0) {
  124. foreach ($pubs as $pub) {
  125. $citation = htmlspecialchars($pub['Citation']);
  126. $raw_link = '';
  127. if($pub['Publication Dbxref']) {
  128. $raw_link = l('raw', 'admin/tripal/chado/tripal_pub/import/raw/' . $pub['Publication Dbxref'], array('attributes' => array('target' => '_blank')));
  129. }
  130. $rows[] = array(
  131. number_format($i),
  132. $citation,
  133. $raw_link,
  134. );
  135. $i++;
  136. }
  137. }
  138. if (count($rows) == 0) {
  139. $rows[] = array(
  140. array(
  141. 'data' => 'No results found',
  142. 'colspan' => 3,
  143. ),
  144. );
  145. }
  146. $headers = array('', 'Publication', 'Raw Results');
  147. $table = array(
  148. 'header' => $headers,
  149. 'rows' => $rows,
  150. 'attributes' => array(
  151. 'id' => 'tripal_pub-importer-test',
  152. 'class' => 'tripal-data-table'
  153. ),
  154. 'sticky' => FALSE,
  155. 'caption' => '',
  156. 'colgroups' => array(),
  157. 'empty' => '',
  158. );
  159. // once we have our table array structure defined, we call Drupal's theme_table()
  160. // function to generate the table.
  161. $table = theme_table($table);
  162. // generate the pager
  163. pager_default_initialize($total_records, $limit);
  164. $pager = array(
  165. 'tags' => array(),
  166. 'element' => 0,
  167. 'parameters' => array(),
  168. 'quantity' => $limit,
  169. );
  170. $pager = theme_pager($pager);
  171. // because this is an ajax callback, the theme_pager will set the URL to be
  172. // "system/ajax", so we need to reset that
  173. $pager = str_replace($base_path . "system/ajax", "", $pager) ;
  174. // join all to form the results
  175. $total_pages = (int) ($total_records / $limit) + 1;
  176. $page = isset($_GET['page']) ? $_GET['page'] : '0';
  177. $output .= "$pager<br><b>Found " . number_format($total_records) . " publications. Page " . ($page + 1) . " of $total_pages.</b> " .
  178. "<br>$remote_db Search String: $search_str $table<br>$pager";
  179. }
  180. }
  181. return $output;
  182. }
  183. /**
  184. * The form used for creating publication importers.
  185. *
  186. * @param $form
  187. * The Drupal form
  188. * @param $form_state
  189. * The form state
  190. * @param $pub_import_id
  191. * The publication importer ID
  192. * @param $action
  193. * The action to perform
  194. *
  195. * @return
  196. * A form array
  197. *
  198. * @ingroup tripal_pub
  199. */
  200. function tripal_pub_importer_setup_form($form, &$form_state = NULL, $pub_import_id = NULL, $action = 'new') {
  201. // Default values can come in the following ways:
  202. //
  203. // 1) as elements of the $pub_importer object. This occurs when editing an existing importer
  204. // 2) in the $form_state['values'] array which occurs on a failed validation or
  205. // ajax callbacks from non submit form elements
  206. // 3) in the $form_state['input'] array which occurs on ajax callbacks from submit
  207. // form elements and the form is being rebuilt
  208. //
  209. // set form field defaults
  210. // Set the default values. If the pub_import_id isn't already defined by the form values
  211. // and one is provided then look it up in the database
  212. $criteria = NULL;
  213. $remote_db = '';
  214. $days = '';
  215. $disabled = '';
  216. $do_contact = '';
  217. $num_criteria = 1;
  218. $loader_name = '';
  219. // if this is an edit the we are pulling an import object from the database
  220. if ($action == "edit") {
  221. $sql = "SELECT * FROM {tripal_pub_import} WHERE pub_import_id = :pub_import_id";
  222. $importer = db_query($sql, array(':pub_import_id' => $pub_import_id))->fetchObject();
  223. $criteria = unserialize($importer->criteria);
  224. $remote_db = $criteria['remote_db'];
  225. $days = $criteria['days'];
  226. $disabled = $criteria['disabled'];
  227. $do_contact = $criteria['do_contact'];
  228. $num_criteria = $criteria['num_criteria'];
  229. $loader_name = $criteria['loader_name'];
  230. }
  231. // if there are any session variables then use those
  232. if (array_key_exists('tripal_pub_import', $_SESSION)) {
  233. $remote_db = $_SESSION['tripal_pub_import']['remote_db'];
  234. $days = $_SESSION['tripal_pub_import']['days'];
  235. $disabled = $_SESSION['tripal_pub_import']['disabled'];
  236. $do_contact = $_SESSION['tripal_pub_import']['do_contact'];
  237. $num_criteria = $_SESSION['tripal_pub_import']['num_criteria'];
  238. $loader_name = $_SESSION['tripal_pub_import']['loader_name'];
  239. // check if the pub_import_id in the session variable is not the same as the one we've been provided
  240. // if so, then clear the session variable
  241. if ($pub_import_id and $pub_import_id != $_SESSION['tripal_pub_import']['pub_import_id']) {
  242. unset($_SESSION['tripal_pub_import']);
  243. }
  244. }
  245. // if we are re constructing the form from a failed validation or ajax callback
  246. // then use the $form_state['values'] values
  247. if (array_key_exists('values', $form_state)) {
  248. $remote_db = $form_state['values']['remote_db'];
  249. $days = $form_state['values']['days'];
  250. $disabled = $form_state['values']['disabled'];
  251. $do_contact = $form_state['values']['do_contact'];
  252. $num_criteria = $form_state['values']['num_criteria'];
  253. $loader_name = $form_state['values']['loader_name'];
  254. }
  255. // if we are re building the form from after submission (from ajax call) then
  256. // the values are in the $form_state['input'] array
  257. if (array_key_exists('input', $form_state) and !empty($form_state['input'])) {
  258. $remote_db = $form_state['input']['remote_db'];
  259. $days = $form_state['input']['days'];
  260. $disabled = $form_state['input']['disabled'];
  261. $do_contact = $form_state['input']['do_contact'];
  262. $loader_name = $form_state['input']['loader_name'];
  263. // because the num_criteria is a value and not a visible or hidden form
  264. // element it is not part of the ['input'] array, so we need to get it from the form
  265. $num_criteria = $form_state['complete form']['num_criteria']['#value'];
  266. }
  267. if (array_key_exists('triggering_element', $form_state) and
  268. $form_state['triggering_element']['#name'] == 'add') {
  269. $num_criteria++;
  270. }
  271. if (array_key_exists('triggering_element', $form_state) and
  272. $form_state['triggering_element']['#name'] == 'remove') {
  273. $num_criteria--;
  274. }
  275. // set the values we need for later but that should not be shown on the form
  276. $form['num_criteria']= array(
  277. '#type' => 'value',
  278. '#value' => $num_criteria,
  279. );
  280. $form['pub_import_id'] = array(
  281. '#type' => 'value',
  282. '#value' => $pub_import_id,
  283. );
  284. $form['action'] = array(
  285. '#type' => 'value',
  286. '#value' => $action,
  287. );
  288. // add in the elements that will be organized via a theme function
  289. $form['themed_element']['loader_name'] = array(
  290. '#type' => 'textfield',
  291. '#title' => t('Loader Name'),
  292. '#description' => t('Please provide a name for this loader setup.'),
  293. '#default_value' => $loader_name,
  294. '#required' => TRUE,
  295. );
  296. $supported_dbs = variable_get('tripal_pub_supported_dbs', array());
  297. $remote_dbs = array();
  298. $values = array(
  299. 'name' => $supported_dbs,
  300. );
  301. $dbs = chado_select_record('db', array('*'), $values);
  302. foreach ($dbs as $index => $db) {
  303. $remote_dbs[$db->name] = $db->description;
  304. };
  305. // use PubMed as the default
  306. if (!$remote_db) {
  307. $remote_db = 'PMID';
  308. }
  309. $form['themed_element']['remote_db'] = array(
  310. '#title' => t('Remote Database'),
  311. '#type' => 'select',
  312. '#options' => $remote_dbs,
  313. '#default_value' => $remote_db,
  314. '#ajax' => array(
  315. 'callback' => "tripal_pubs_setup_form_ajax_update",
  316. 'wrapper' => 'tripal-pubs-importer-setup',
  317. 'effect' => 'fade',
  318. 'method' => 'replace',
  319. ),
  320. );
  321. $form['themed_element']['days'] = array(
  322. '#type' => 'textfield',
  323. '#title' => t('Days since record modified'),
  324. '#description' => t('Limit the search to include pubs that have been added no more than this many days before today.'),
  325. '#default_value' => $days,
  326. '#size' => 5,
  327. );
  328. $form['themed_element']['disabled'] = array(
  329. '#type' => 'checkbox',
  330. '#title' => t('Disabled'),
  331. '#description' => t('Check to disable this importer.'),
  332. '#default_value' => $disabled,
  333. );
  334. $form['themed_element']['do_contact'] = array(
  335. '#type' => 'checkbox',
  336. '#title' => t('Create Contact'),
  337. '#description' => t('Check to create an entry in the contact table for each author of a matching publication during import. This allows storage of
  338. additional information such as affilation, etc. Otherwise, only authors names are retrieved.'),
  339. '#default_value' => $do_contact,
  340. );
  341. // add in the form for the criteria
  342. tripal_pub_importer_setup_add_criteria_fields($form, $form_state, $num_criteria, $criteria);
  343. // add in the buttons
  344. $form['save'] = array(
  345. '#type' => 'submit',
  346. '#value' => t('Save Importer'),
  347. );
  348. $form['test'] = array(
  349. '#type' => 'submit',
  350. '#value' => t('Test Importer'),
  351. );
  352. $form['delete'] = array(
  353. '#type' => 'submit',
  354. '#value' => t('Delete Importer'),
  355. '#attributes' => array('style' => 'float: right;')
  356. );
  357. // add in the section where the test results will appear
  358. $form['results'] = array(
  359. '#markup' => '<div id="tripal-pub-importer-test-section"></div>',
  360. );
  361. // allow the selected remote database to make changes to the form if needed
  362. $callback = "tripal_pub_remote_alter_form_$remote_db";
  363. $form = call_user_func($callback, $form, $form_state, $num_criteria);
  364. $form['themed_element']['#theme'] = 'tripal_pub_importer_setup_form_elements';
  365. return $form;
  366. }
  367. /**
  368. * A helper function for the importer setup form that adds the criteria to
  369. * the form that belong to the importer.
  370. *
  371. * @param $form
  372. * The form
  373. * @param $form_state
  374. * The form state
  375. * @param $num_criteria
  376. * The number of criteria that exist for the importer
  377. * @param $criteria
  378. * An array containing the criteria
  379. *
  380. *@return
  381. * A form array
  382. *
  383. * @ingroup tripal_pub
  384. */
  385. function tripal_pub_importer_setup_add_criteria_fields(&$form, &$form_state, $num_criteria, $criteria){
  386. // choices array
  387. $scope_choices = array(
  388. 'any' => 'Any Field',
  389. 'abstract' => 'Abstract',
  390. 'author' => 'Author',
  391. 'id' => 'Accession',
  392. 'title' => 'Title',
  393. 'journal' => 'Journal Name'
  394. );
  395. $first_op_choices = array(
  396. '' => '',
  397. 'NOT' => 'NOT'
  398. );
  399. $op_choices = array(
  400. 'AND' => 'AND',
  401. 'OR' => 'OR',
  402. 'NOT' => 'NOT'
  403. );
  404. for($i = 1; $i <= $num_criteria; $i++) {
  405. $is_phrase = 1;
  406. $search_terms = '';
  407. $scope = '';
  408. $is_phrase = '';
  409. $operation = '';
  410. // if we have criteria supplied from the database then use that as the initial defaults
  411. if ($criteria) {
  412. $search_terms = $criteria['criteria'][$i]['search_terms'];
  413. $scope = $criteria['criteria'][$i]['scope'];
  414. $is_phrase = $criteria['criteria'][$i]['is_phrase'];
  415. $operation = $criteria['criteria'][$i]['operation'];
  416. }
  417. // if the criteria comes the session
  418. if (array_key_exists('tripal_pub_import', $_SESSION)) {
  419. $search_terms = isset($_SESSION['tripal_pub_import']['criteria'][$i]['search_terms']) ? $_SESSION['tripal_pub_import']['criteria'][$i]['search_terms'] : $search_terms;
  420. $scope = isset($_SESSION['tripal_pub_import']['criteria'][$i]['scope']) ? $_SESSION['tripal_pub_import']['criteria'][$i]['scope'] : $scope;
  421. $is_phrase = isset($_SESSION['tripal_pub_import']['criteria'][$i]['is_phrase']) ? $_SESSION['tripal_pub_import']['criteria'][$i]['is_phrase'] : $is_phrase;
  422. $operation = isset($_SESSION['tripal_pub_import']['criteria'][$i]['operation']) ? $_SESSION['tripal_pub_import']['criteria'][$i]['operation'] : $operation;
  423. }
  424. // If the form_state has variables then use those. This happens when an error occurs on the form or the
  425. // form is resbumitted using AJAX
  426. if (array_key_exists('values', $form_state)) {
  427. $search_terms = $form_state['values']["search_terms-$i"];
  428. $scope = $form_state['values']["scope-$i"];
  429. $is_phrase = $form_state['values']["is_phrase-$i"];
  430. $operation = $form_state['values']["operation-$i"];
  431. }
  432. $form['themed_element']['criteria'][$i]["scope-$i"] = array(
  433. '#type' => 'select',
  434. '#description' => t('Please select the fields to search for this term.'),
  435. '#options' => $scope_choices,
  436. '#default_value' => $scope,
  437. );
  438. $form['themed_element']['criteria'][$i]["search_terms-$i"] = array(
  439. '#type' => 'textfield',
  440. '#description' => t('<span style="white-space: normal">Please provide a list of words for searching. You may use
  441. conjunctions such as "AND" or "OR" to separate words if they are expected in
  442. the same scope, but do not mix ANDs and ORs. Check the "Is Phrase" checkbox to use conjunctions as part of the text to search</span>'),
  443. '#default_value' => $search_terms,
  444. '#required' => TRUE,
  445. '#maxlength' => 2048,
  446. );
  447. $form['themed_element']['criteria'][$i]["is_phrase-$i"] = array(
  448. '#type' => 'checkbox',
  449. '#title' => t('Is Phrase?'),
  450. '#default_value' => $is_phrase,
  451. );
  452. if ($i == 1) {
  453. /*
  454. $form['criteria'][$i]["operation-$i"] = array(
  455. '#type' => 'select',
  456. '#options' => $first_op_choices,
  457. '#default_value' => $operation,
  458. );*/
  459. }
  460. if ($i > 1) {
  461. $form['themed_element']['criteria'][$i]["operation-$i"] = array(
  462. '#type' => 'select',
  463. '#options' => $op_choices,
  464. '#default_value' => $operation,
  465. );
  466. }
  467. if ($i == $num_criteria) {
  468. if($i > 1) {
  469. $form['themed_element']['criteria'][$i]["remove-$i"] = array(
  470. '#type' => 'button',
  471. '#name' => 'remove',
  472. '#value' => t('Remove'),
  473. '#ajax' => array(
  474. 'callback' => "tripal_pubs_setup_form_ajax_update",
  475. 'wrapper' => 'tripal-pubs-importer-setup',
  476. 'effect' => 'fade',
  477. 'method' => 'replace',
  478. 'prevent' => 'click'
  479. ),
  480. // When this button is clicked, the form will be validated and submitted.
  481. // Therefore, we set custom submit and validate functions to override the
  482. // default form submit. In the validate function we set the form_state
  483. // to rebuild the form so the submit function never actually gets called,
  484. // but we need it or Drupal will run the default validate anyway.
  485. // we also set #limit_validation_errors to empty so fields that
  486. // are required that don't have values won't generate warnings.
  487. '#submit' => array('tripal_pub_setup_form_ajax_button_submit'),
  488. '#validate' => array('tripal_pub_setup_form_ajax_button_validate'),
  489. '#limit_validation_errors' => array(),
  490. );
  491. }
  492. $form['themed_element']['criteria'][$i]["add-$i"] = array(
  493. '#type' => 'button',
  494. '#name' => 'add',
  495. '#value' => t('Add'),
  496. '#ajax' => array(
  497. 'callback' => "tripal_pubs_setup_form_ajax_update",
  498. 'wrapper' => 'tripal-pubs-importer-setup',
  499. 'effect' => 'fade',
  500. 'method' => 'replace',
  501. 'prevent' => 'click'
  502. ),
  503. // When this button is clicked, the form will be validated and submitted.
  504. // Therefore, we set custom submit and validate functions to override the
  505. // default form submit. In the validate function we set the form_state
  506. // to rebuild the form so the submit function never actually gets called,
  507. // but we need it or Drupal will run the default validate anyway.
  508. // we also set #limit_validation_errors to empty so fields that
  509. // are required that don't have values won't generate warnings.
  510. '#submit' => array('tripal_pub_setup_form_ajax_button_submit'),
  511. '#validate' => array('tripal_pub_setup_form_ajax_button_validate'),
  512. '#limit_validation_errors' => array(),
  513. );
  514. }
  515. }
  516. }
  517. /**
  518. * This function is used to rebuild the form if an ajax call is made vai a button.
  519. * The button causes the form to be submitted. We don't want this so we override
  520. * the validate and submit routines on the form button. Therefore, this function
  521. * only needs to tell Drupal to rebuild the form
  522. *
  523. * @ingroup tripal_pub
  524. */
  525. function tripal_pub_setup_form_ajax_button_validate($form, &$form_state){
  526. $form_state['rebuild'] = TRUE;
  527. }
  528. /**
  529. * This function is just a dummy to override the default form submit on ajax calls for buttons
  530. *
  531. * @ingroup tripal_pub
  532. */
  533. function tripal_pub_setup_form_ajax_button_submit($form, &$form_state){
  534. // do nothing
  535. }
  536. /**
  537. * Validate the tripal_pub_importer_setup_form form
  538. *
  539. * @ingroup tripal_pub
  540. */
  541. function tripal_pub_importer_setup_form_validate($form, &$form_state) {
  542. $num_criteria = $form_state['values']['num_criteria'];
  543. $remote_db = $form_state['values']["remote_db"];
  544. $days = trim($form_state['values']["days"]);
  545. $disabled = $form_state['values']["disabled"];
  546. $do_contact = $form_state['values']["do_contact"];
  547. $loader_name = trim($form_state['values']["loader_name"]);
  548. for ($i = 1; $i <= $num_criteria; $i++) {
  549. $search_terms = trim($form_state['values']["search_terms-$i"]);
  550. $scope = $form_state['values']["scope-$i"];
  551. $is_phrase = $form_state['values']["is_phrase-$i"];
  552. $operation = '';
  553. if($i > 1) {
  554. $operation = $form_state['values']["operation-$i"];
  555. }
  556. if (!$is_phrase) {
  557. if (preg_match('/and/i', $search_terms) and preg_match('/or/i', $search_terms)) {
  558. form_set_error("search_terms-$i", "You may use 'AND' or 'OR' but cannot use both. Add a new entry below with the same scope for the other conunction.");
  559. $_SESSION['tripal_pub_import']['perform_search'] = 0;
  560. }
  561. }
  562. }
  563. if ($days and !is_numeric($days) or preg_match('/\./', $days)) {
  564. form_set_error("days", "Please enter a numeric, non decimal value, for the number of days.");
  565. $_SESSION['tripal_pub_import']['perform_search'] = 0;
  566. }
  567. // allow the selected remote database to validate any changes to the form if needed
  568. $callback = "tripal_pub_remote_validate_form_$remote_db";
  569. $form = call_user_func($callback, $form, $form_state);
  570. }
  571. /**
  572. * Submit the tripal_pub_importer_setup_form form
  573. *
  574. * @ingroup tripal_pub
  575. */
  576. function tripal_pub_importer_setup_form_submit($form, &$form_state) {
  577. $pub_import_id = $form_state['values']['pub_import_id'];
  578. $num_criteria = $form_state['values']['num_criteria'];
  579. $remote_db = $form_state['values']["remote_db"];
  580. $days = trim($form_state['values']["days"]);
  581. $loader_name = trim($form_state['values']["loader_name"]);
  582. $disabled = $form_state['values']["disabled"];
  583. $do_contact = $form_state['values']["do_contact"];
  584. // set the session variables
  585. $_SESSION['tripal_pub_import']['remote_db'] = $remote_db;
  586. $_SESSION['tripal_pub_import']['days'] = $days;
  587. $_SESSION['tripal_pub_import']['num_criteria'] = $num_criteria;
  588. $_SESSION['tripal_pub_import']['loader_name'] = $loader_name;
  589. $_SESSION['tripal_pub_import']['disabled'] = $disabled;
  590. $_SESSION['tripal_pub_import']['do_contact'] = $do_contact;
  591. $_SESSION['tripal_pub_import']['pub_import_id'] = $pub_import_id;
  592. unset($_SESSION['tripal_pub_import']['criteria']);
  593. for ($i = 1; $i <= $num_criteria; $i++) {
  594. $search_terms = trim($form_state['values']["search_terms-$i"]);
  595. $scope = $form_state['values']["scope-$i"];
  596. $is_phrase = $form_state['values']["is_phrase-$i"];
  597. $operation = '';
  598. if ($i > 1) {
  599. $operation = $form_state['values']["operation-$i"];
  600. }
  601. $_SESSION['tripal_pub_import']['criteria'][$i] = array(
  602. 'search_terms' => $search_terms,
  603. 'scope' => $scope,
  604. 'is_phrase' => $is_phrase,
  605. 'operation' => $operation
  606. );
  607. }
  608. // now perform the appropriate action for the button clicked
  609. if ($form_state['values']['op'] == 'Test Importer') {
  610. $_SESSION['tripal_pub_import']['perform_search'] = 1;
  611. }
  612. if ($form_state['values']['op'] == 'Save Importer' or
  613. $form_state['values']['op'] == 'Save & Import Now') {
  614. $record = array(
  615. 'name' => $loader_name,
  616. 'criteria' => serialize($_SESSION['tripal_pub_import']),
  617. 'disabled' => $disabled,
  618. 'do_contact' => $do_contact
  619. );
  620. // first check to see if this pub_import_id is already present. If so,
  621. // do an update rather than an insert
  622. $sql = "SELECT * FROM {tripal_pub_import} WHERE pub_import_id = :pub_import_id";
  623. $importer = db_query($sql, array(':pub_import_id' => $pub_import_id))->fetchObject();
  624. if($importer) {
  625. // do the update
  626. $record['pub_import_id'] = $pub_import_id;
  627. if(drupal_write_record('tripal_pub_import', $record, 'pub_import_id')){
  628. unset($_SESSION['tripal_pub_import']);
  629. drupal_set_message('Publication import settings updated.');
  630. drupal_goto('admin/tripal/chado/tripal_pub/import_list');
  631. }
  632. else {
  633. drupal_set_message('Could not update publication import settings.', 'error');
  634. }
  635. }
  636. else {
  637. // do the insert
  638. if(drupal_write_record('tripal_pub_import', $record)){
  639. unset($_SESSION['tripal_pub_import']);
  640. drupal_set_message('Publication import settings saved.');
  641. // if the user wants to do the import now then do it (may time out
  642. // for long jobs)
  643. if ($form_state['values']['op'] == 'Save & Import Now') {
  644. tripal_execute_pub_importer($record['pub_import_id']);
  645. }
  646. drupal_goto('admin/tripal/chado/tripal_pub/import_list');
  647. }
  648. else {
  649. drupal_set_message('Could not save publication import settings.', 'error');
  650. }
  651. }
  652. }
  653. if ($form_state['values']['op'] == 'Delete Importer') {
  654. $sql = "DELETE FROM {tripal_pub_import} WHERE pub_import_id = :pub_import_id";
  655. $success = db_query($sql, array(':pub_import_id' => $pub_import_id));
  656. if ($success) {
  657. drupal_set_message('Publication importer deleted.');
  658. drupal_goto('admin/tripal/chado/tripal_pub/import_list');
  659. }
  660. else {
  661. drupal_set_message('Could not delete publication importer.', 'error');
  662. }
  663. }
  664. }
  665. /**
  666. * AJAX callback for updating the form.
  667. *
  668. * @ingroup tripal_pub
  669. */
  670. function tripal_pubs_setup_form_ajax_update($form, $form_state) {
  671. return $form['themed_element'];
  672. }
  673. /**
  674. * Theme the tripal_pub_importer_setup_form form.
  675. *
  676. * @ingroup tripal_pub
  677. */
  678. function theme_tripal_pub_importer_setup_form_elements($variables) {
  679. $form = $variables['form'];
  680. // first render the fields at the top of the form
  681. $markup = '';
  682. $markup .= '<div id="pub-search-form-row0">';
  683. $markup .= ' <div id="pub-search-form-row0-col1" style="float: left">' . drupal_render($form['remote_db']) . '</div>';
  684. $markup .= ' <div id="pub-search-form-row0-col2" style="float: left; margin-left: 10px">' . drupal_render($form['loader_name']) . '</div>';
  685. $markup .= '</div>';
  686. $markup .= '<div id="pub-search-form-row1" style="clear:both">';
  687. $markup .= ' <div id="pub-search-form-row1-col1">' . drupal_render($form['days']) . '</div>';
  688. $markup .= '</div>';
  689. $markup .= '<div id="pub-search-form-row2">' . drupal_render($form['disabled']) . '</div>';
  690. $markup .= '<div id="pub-search-form-row3">' . drupal_render($form['do_contact']) . '</div>';
  691. // next render the criteria fields into a table format
  692. $rows = array();
  693. foreach ($form['criteria'] as $i => $element) {
  694. if(is_numeric($i)) {
  695. $rows[] = array(
  696. drupal_render($element["operation-$i"]),
  697. drupal_render($element["scope-$i"]),
  698. drupal_render($element["search_terms-$i"]),
  699. drupal_render($element["is_phrase-$i"]),
  700. drupal_render($element["add-$i"]) . drupal_render($element["remove-$i"]),
  701. );
  702. }
  703. }
  704. $headers = array('Operation','Scope', 'Search Terms', '','');
  705. $table = array(
  706. 'header' => $headers,
  707. 'rows' => $rows,
  708. 'attributes' => array(
  709. 'class' => array('tripal-data-table')
  710. ),
  711. 'sticky' => TRUE,
  712. 'caption' => '',
  713. 'colgroups' => array(),
  714. 'empty' => '',
  715. );
  716. $criteria_table = theme_table($table);
  717. $markup .= $criteria_table;
  718. // add the rendered form
  719. $form = array(
  720. '#markup' => $markup,
  721. '#prefix' => '<div id="tripal-pubs-importer-setup">',
  722. '#suffix' => '</div>',
  723. );
  724. return drupal_render($form);
  725. }
  726. /**
  727. * Add a job to import publications
  728. *
  729. * @param $pub_importer_id
  730. * The id of the importer to submit a job to update
  731. *
  732. * @ingroup tripal_pub
  733. */
  734. function tripal_pub_importer_submit_job($import_id) {
  735. global $user;
  736. // get all of the loaders
  737. $args = array(':import_id' => $import_id);
  738. $sql = "SELECT * FROM {tripal_pub_import} WHERE pub_import_id = :import_id ";
  739. $import = db_query($sql, $args)->fetchObject();
  740. $args = array($import_id);
  741. tripal_add_job("Import publications $import->name", 'tripal_pub',
  742. 'tripal_execute_pub_importer', $args, $user->uid);
  743. drupal_goto('admin/tripal/chado/tripal_pub/import_list');
  744. }
  745. /**
  746. * Adds publications that have been retrieved from a remote database and
  747. * consolidated into an array of details.
  748. *
  749. * @param $pubs
  750. * An array containing a list of publications to add to Chado. The
  751. * array contains a set of details for the publication.
  752. * @param $do_contact
  753. * Set to TRUE if authors should automatically have a contact record added
  754. * to Chado.
  755. * @param $update
  756. * If set to TRUE then publications that already exist in the Chado database
  757. * will be updated, whereas if FALSE only new publications will be added
  758. *
  759. * @return
  760. * Returns an array containing the number of publications that were
  761. * inserted, updated, skipped and which had an error during import.
  762. *
  763. * @ingroup tripal_pub
  764. */
  765. function tripal_pub_add_publications($pubs, $do_contact, $update = FALSE) {
  766. $report = array();
  767. $report['error'] = 0;
  768. $report['inserted'] = array();
  769. $report['skipped'] = array();
  770. $total_pubs = count($pubs);
  771. // iterate through the publications and add each one
  772. $i = 1;
  773. foreach ($pubs as $pub) {
  774. $memory = number_format(memory_get_usage()) . " bytes";
  775. print "Processing $i of $total_pubs. Memory usage: $memory.\r";
  776. // add the publication to Chado
  777. $action = '';
  778. $pub_id = tripal_pub_add_publication($pub, $action, $do_contact, $update);
  779. if ($pub_id){
  780. // add the publication cross reference (e.g. to PubMed)
  781. if ($pub_id and $pub['Publication Dbxref']) {
  782. $dbxref = array();
  783. if (preg_match('/^(.*?):(.*?)$/', trim($pub['Publication Dbxref']), $matches)) {
  784. $dbxref['db_name'] = $matches[1];
  785. $dbxref['accession'] = $matches[2];
  786. }
  787. else {
  788. tripal_report_error(
  789. 'tripal_pub',
  790. TRIPAL_ERROR,
  791. 'Unable to extract the dbxref to be associated with the publication (pub ID=@pub_id) from @dbxref. This reference should be [database-name]:[accession]',
  792. array('@pub_id' => $pub_id, '@dbxref' => $pub['Publication Dbxref'])
  793. );
  794. }
  795. $pub_dbxref = tripal_associate_dbxref('pub', $pub_id, $dbxref);
  796. }
  797. $pub['pub_id'] = $pub_id;
  798. }
  799. switch ($action) {
  800. case 'error':
  801. $report['error']++;
  802. break;
  803. case 'inserted':
  804. $report['inserted'][] = $pub;
  805. break;
  806. case 'updated':
  807. $report['updated'][] = $pub;
  808. break;
  809. case 'skipped':
  810. $report['skipped'][] = $pub;
  811. break;
  812. }
  813. $i++;
  814. }
  815. print "\n";
  816. return $report;
  817. }
  818. /**
  819. * Adds a new publication to the Chado, along with all properties and
  820. * database cross-references. If the publication does not already exist
  821. * in Chado then it is added. If it does exist nothing is done. If
  822. * the $update parameter is TRUE then the publication is updated if it exists.
  823. *
  824. * @param $pub_details
  825. * An associative array containing all of the details about the publication.
  826. * @param $action
  827. * This variable will get set to a text value indicating the action that was
  828. * performed. The values include 'skipped', 'inserted', 'updated' or 'error'.
  829. * @param $do_contact
  830. * Optional. Set to TRUE if a contact entry should be added to the Chado contact table
  831. * for authors of the publication.
  832. * @param $update_if_exists
  833. * Optional. If the publication already exists then this function will return
  834. * without adding a new publication. However, set this value to TRUE to force
  835. * the function to pudate the publication using the $pub_details that are provided.
  836. *
  837. * @return
  838. * If the publication already exists, is inserted or updated then the publication
  839. * ID is returned, otherwise FALSE is returned. If the publication already exists
  840. * and $update_if_exists is not TRUE then the $action variable is set to 'skipped'.
  841. * If the publication already exists and $update_if_exists is TRUE and if the update
  842. * was successful then $action is set to 'updated'. Otherwise on successful insert
  843. * the $action variable is set to 'inserted'. If the function failes then the
  844. * $action variable is set to 'error'
  845. *
  846. * @ingroup tripal_pub
  847. */
  848. function tripal_pub_add_publication($pub_details, &$action, $do_contact = FALSE, $update_if_exists = FALSE) {
  849. $pub_id = 0;
  850. if (!is_array($pub_details)) {
  851. return FALSE;
  852. }
  853. // before proceeding check to see if the publication already exists. If there is only one match
  854. // and the $update_if_exists is NOT set then return FALSE
  855. $pub_ids = tripal_publication_exists($pub_details);
  856. if(count($pub_ids) == 1 and !$update_if_exists) {
  857. tripal_report_error('tripal_pub', TRIPAL_NOTICE,
  858. "There is a publication that is a duplicate of this publication. Cannot continue. It either ".
  859. "has a matching Dbxref (e.g. PubMed ID), a non-unique citation or matches on the unique " .
  860. "constraint set by the Tripal publication module configuration page. \nCitation: %title %dbxref.\nMatching Pub id: %ids",
  861. array(
  862. '%title' => $pub_details['Citation'],
  863. '%dbxref' => $pub_details['Publication Dbxref'],
  864. '%ids' => implode(",", $pub_ids),
  865. )
  866. );
  867. $action = 'skipped';
  868. return FALSE;
  869. }
  870. // if we have more than one matching pub then return an error as we don't know which to update even if
  871. // update_if_exists is set to TRUE
  872. if(count($pub_ids) > 1) {
  873. tripal_report_error('tripal_pub', TRIPAL_NOTICE,
  874. "There are %num publications that are duplicates of this publication. They either " .
  875. "have a matching Dbxref (e.g. PubMed ID) or match on the unique constraint set by the Tripal publication module ".
  876. "configuration page. \nCitation: %title %dbxref.\nMatching Pub ids: %ids",
  877. array(
  878. '%num' => count($pub_ids),
  879. '%title' => $pub_details['Citation'],
  880. '%dbxref' => $pub_details['Publication Dbxref'],
  881. '%ids' => implode(",", $pub_ids),
  882. )
  883. );
  884. $action = 'skipped';
  885. return FALSE;
  886. }
  887. // get the publication type (use the first publication type)
  888. if (array_key_exists('Publication Type', $pub_details)) {
  889. $pub_type = '';
  890. if(is_array($pub_details['Publication Type'])) {
  891. $pub_type = $pub_details['Publication Type'][0];
  892. }
  893. else {
  894. $pub_type = $pub_details['Publication Type'];
  895. }
  896. $identifiers = array(
  897. 'name' => $pub_type,
  898. 'cv_id' => array(
  899. 'name' => 'tripal_pub'
  900. ),
  901. );
  902. $pub_type = tripal_get_cvterm($identifiers);
  903. }
  904. else {
  905. tripal_report_error('tripal_pub', TRIPAL_ERROR,
  906. "The Publication Type is a required property but is missing", array());
  907. $action = 'error';
  908. return FALSE;
  909. }
  910. if (!$pub_type) {
  911. tripal_report_error('tripal_pub', TRIPAL_ERROR, "Cannot find publication type: '%type'",
  912. array('%type' => $pub_details['Publication Type'][0]));
  913. $action = 'error';
  914. return FALSE;
  915. }
  916. // the series name field in the pub table is only 255 characters, so we should trim just in case
  917. $series_name = '';
  918. if (array_key_exists('Series_Name', $pub_details)) {
  919. $series_name = substr($pub_details['Series Name'], 0, 255);
  920. }
  921. if (array_key_exists('Journal Name', $pub_details)) {
  922. $series_name = substr($pub_details['Journal Name'], 0, 255);
  923. }
  924. // build the values array for inserting or updating
  925. $values = array(
  926. 'title' => $pub_details['Title'],
  927. 'volume' => $pub_details['Volume'],
  928. 'series_name' => $series_name,
  929. 'issue' => $pub_details['Issue'],
  930. 'pyear' => $pub_details['Year'],
  931. 'pages' => $pub_details['Pages'],
  932. 'uniquename' => $pub_details['Citation'],
  933. 'type_id' => $pub_type->cvterm_id,
  934. );
  935. // if there is no pub_id then we need to do an insert.
  936. if (!$pub_id) {
  937. $options = array('statement_name' => 'ins_pub_tivoseispypaunty');
  938. $pub = chado_insert_record('pub', $values, $options);
  939. if (!$pub) {
  940. tripal_report_error('tripal_pub', TRIPAL_ERROR, "Cannot insert the publication with title: %title",
  941. array('%title' => $pub_details['Title']));
  942. $action = 'error';
  943. return FALSE;
  944. }
  945. $pub_id = $pub['pub_id'];
  946. $action = 'inserted';
  947. }
  948. // if there is a pub_id and we've been told to update, then do the update
  949. if ($pub_id and $update_if_exists) {
  950. $match = array('pub_id' => $pub_id);
  951. $options = array('statement_name' => 'up_pub_tivoseispypaunty');
  952. $success = chado_update_record('pub', $match, $values, $options);
  953. if (!$success) {
  954. tripal_report_error('tripal_pub', TRIPAL_ERROR, "Cannot update the publication with title: %title",
  955. array('%title' => $pub_details['Title']));
  956. $action = 'error';
  957. return FALSE;
  958. }
  959. $action = 'updated';
  960. }
  961. // before we add any new properties we need to remove those that are there if this
  962. // is an update. The only thing we don't want to remove are the 'Publication Dbxref'
  963. if ($update_if_exists) {
  964. $sql = "
  965. DELETE FROM {pubprop}
  966. WHERE
  967. pub_id = :pub_id AND
  968. NOT type_id in (
  969. SELECT cvterm_id
  970. FROM {cvterm}
  971. WHERE name = 'Publication Dbxref'
  972. )
  973. ";
  974. chado_query($sql, array(':pub_id' => $pub_id));
  975. }
  976. // iterate through the properties and add them
  977. foreach ($pub_details as $key => $value) {
  978. // the pub_details may have the raw search data (e.g. in XML from PubMed. We'll irgnore this for now
  979. if($key == 'raw') {
  980. continue;
  981. }
  982. // get the cvterm by name
  983. $identifiers = array(
  984. 'name' => $key,
  985. 'cv_id' => array(
  986. 'name' => 'tripal_pub'
  987. ),
  988. );
  989. $cvterm = tripal_get_cvterm($identifiers);
  990. // if we could not find the cvterm by name then try by synonym
  991. //$cvterm = tripal_get_cvterm(array('name' => $key, 'cv_id' => array('name' => 'tripal_pub')));
  992. if (!$cvterm) {
  993. $identifiers = array(
  994. 'synonym' => array(
  995. 'name' => $key,
  996. 'cv_name' => 'tripal_pub'
  997. )
  998. );
  999. $cvterm = tripal_get_cvterm($identifiers);
  1000. }
  1001. if (!$cvterm) {
  1002. tripal_report_error('tripal_pub', TRIPAL_ERROR, "Cannot find term: '%prop'. Skipping.", array('%prop' => $key));
  1003. continue;
  1004. }
  1005. // skip details that won't be stored as properties
  1006. if ($key == 'Author List') {
  1007. tripal_pub_add_authors($pub_id, $value, $do_contact);
  1008. continue;
  1009. }
  1010. if ($key == 'Title' or $key == 'Volume' or $key == 'Journal Name' or $key == 'Issue' or
  1011. $key == 'Year' or $key == 'Pages') {
  1012. continue;
  1013. }
  1014. $success = 0;
  1015. if (is_array($value)) {
  1016. foreach ($value as $subkey => $subvalue) {
  1017. // if the key is an integer then this array is a simple list and
  1018. // we will insert using the primary key. Otheriwse, use the new key
  1019. if(is_int($subkey)) {
  1020. $success = chado_insert_property('pub', $pub_id, $key, 'tripal_pub', $subvalue, FALSE);
  1021. }
  1022. else {
  1023. $success = chado_insert_property('pub', $pub_id, $subkey, 'tripal_pub', $subvalue, FALSE);
  1024. }
  1025. }
  1026. }
  1027. else {
  1028. $success = chado_insert_property('pub', $pub_id, $key, 'tripal_pub', $value, TRUE);
  1029. }
  1030. if (!$success) {
  1031. tripal_report_error('tripal_pub', TRIPAL_ERROR, "Cannot add property '%prop' to publication. Skipping.",
  1032. array('%prop' => $key));
  1033. continue;
  1034. }
  1035. }
  1036. return $pub_id;
  1037. }
  1038. /**
  1039. * Add one or more authors to a publication
  1040. *
  1041. * @param $pub_id
  1042. * The publication ID of the pub in Chado.
  1043. * @param $authors
  1044. * An array of authors. Each author should have a set of keys/value pairs
  1045. * describing the author.
  1046. * @param $do_contact
  1047. * Optional. Set to TRUE if a contact entry should be added to the Chado contact table
  1048. * for authors of the publication.
  1049. * @ingroup tripal_pub
  1050. */
  1051. function tripal_pub_add_authors($pub_id, $authors, $do_contact) {
  1052. $rank = 0;
  1053. // first remove any of the existing pubauthor entires
  1054. $sql = "DELETE FROM {pubauthor} WHERE pub_id = :pub_id";
  1055. chado_query($sql, array(':pub_id' => $pub_id));
  1056. // iterate through the authors and add them to the pubauthors and contact
  1057. // tables of chado, then link them through the custom pubauthors_contact table
  1058. foreach ($authors as $author) {
  1059. // skip invalid author entires
  1060. if ($author['valid'] == 'N') {
  1061. continue;
  1062. }
  1063. // remove the 'valid' property as we don't have a CV term for it
  1064. unset($author['valid']);
  1065. // construct the contact.name field using the author information
  1066. $name = '';
  1067. $type = 'Person';
  1068. if ($author['Given Name']) {
  1069. $name .= $author['Given Name'];
  1070. }
  1071. if ($author['Surname']) {
  1072. $name .= ' ' . $author['Surname'];
  1073. }
  1074. if ($author['Suffix']) {
  1075. $name .= ' ' . $author['Suffix'];
  1076. }
  1077. if ($author['Collective']) {
  1078. $name = $author['Collective'];
  1079. $type = 'Collective';
  1080. }
  1081. $name = trim($name);
  1082. // add an entry to the pubauthors table
  1083. $values = array(
  1084. 'pub_id' => $pub_id,
  1085. 'rank' => $rank,
  1086. 'surname' => $author['Surname'] ? substr($author['Surname'], 0, 100) : substr($author['Collective'], 0, 100),
  1087. 'givennames' => $author['Given Name'],
  1088. 'suffix' => $author['Suffix'],
  1089. );
  1090. $options = array('statement_name' => 'ins_pubauthor_idrasugisu');
  1091. $pubauthor = chado_insert_record('pubauthor', $values, $options);
  1092. // if the user wants us to create a contact for each author then do it.
  1093. if ($do_contact) {
  1094. // Add the contact
  1095. $contact = tripal_insert_contact(array(
  1096. 'name' => $name,
  1097. 'description' => '',
  1098. 'type_name' => $type,
  1099. 'properties' => $author
  1100. ));
  1101. // if we have succesfully added the contact and the pubauthor entries then we want to
  1102. // link them together
  1103. if ($contact and $pubauthor) {
  1104. // link the pubauthor entry to the contact
  1105. $values = array(
  1106. 'pubauthor_id' => $pubauthor['pubauthor_id'],
  1107. 'contact_id' => $contact['contact_id'],
  1108. );
  1109. $options = array('statement_name' => 'ins_pubauthorcontact_puco');
  1110. $pubauthor_contact = chado_insert_record('pubauthor_contact', $values, $options);
  1111. if (!$pubauthor_contact) {
  1112. tripal_report_error('tripal_pub', TRIPAL_ERROR, "Cannot link pub authro and contact.", array());
  1113. }
  1114. }
  1115. }
  1116. $rank++;
  1117. }
  1118. }
  1119. /**
  1120. * This function generates an array suitable for use with the
  1121. * tripal_pub_create_citation function for any publication
  1122. * already stored in the Chado tables.
  1123. *
  1124. * @param $pub_id
  1125. * The publication ID
  1126. * @param $skip_existing
  1127. * Set to TRUE to skip publications that already have a citation
  1128. * in the pubprop table. Set to FALSE to generate a citation
  1129. * regardless if the citation already exists.
  1130. *
  1131. * @return
  1132. * An array suitable for the trpial_pub_create_citation function. On
  1133. * failure returns FALSE.
  1134. *
  1135. * @ingroup tripal_pub
  1136. */
  1137. function tripal_pub_get_publication_array($pub_id, $skip_existing = TRUE) {
  1138. $options = array('return_array' => 1);
  1139. // ---------------------------------
  1140. // get the publication
  1141. // ---------------------------------
  1142. $values = array('pub_id' => $pub_id);
  1143. $pub = chado_generate_var('pub', $values);
  1144. // expand the title
  1145. $pub = chado_expand_var($pub, 'field', 'pub.title');
  1146. $pub = chado_expand_var($pub, 'field', 'pub.volumetitle');
  1147. $pub = chado_expand_var($pub, 'field', 'pub.uniquename');
  1148. $pub_array = array();
  1149. if (trim($pub->title)) {
  1150. $pub_array['Title'] = $pub->title;
  1151. }
  1152. if (trim($pub->volumetitle)) {
  1153. $pub_array['Volume Title'] = $pub->volumetitle;
  1154. }
  1155. if (trim($pub->volume)) {
  1156. $pub_array['Volume'] = $pub->volume;
  1157. }
  1158. if (trim($pub->series_name)) {
  1159. $pub_array['Series Name'] = $pub->series_name;
  1160. }
  1161. if (trim($pub->issue)) {
  1162. $pub_array['Issue'] = $pub->issue;
  1163. }
  1164. if (trim($pub->pyear)) {
  1165. $pub_array['Year'] = $pub->pyear;
  1166. }
  1167. if (trim($pub->pages)) {
  1168. $pub_array['Pages'] = $pub->pages;
  1169. }
  1170. if (trim($pub->miniref)) {
  1171. $pub_array['Mini Ref'] = $pub->miniref;
  1172. }
  1173. if (trim($pub->uniquename)) {
  1174. $pub_array['Uniquename'] = $pub->uniquename;
  1175. }
  1176. $pub_array['Publication Type'][] = $pub->type_id->name;
  1177. // ---------------------------------
  1178. // get the citation
  1179. // ---------------------------------
  1180. $values = array(
  1181. 'pub_id' => $pub->pub_id,
  1182. 'type_id' => array(
  1183. 'name' => 'Citation',
  1184. ),
  1185. );
  1186. $citation = chado_generate_var('pubprop', $values);
  1187. if ($citation) {
  1188. $citation = chado_expand_var($citation, 'field', 'pubprop.value', $options);
  1189. if (count($citation) > 1) {
  1190. tripal_report_error('tripal_pub', TRIPAL_ERROR, "Publication has multiple citations already: %pub_id",
  1191. array('%pub_id' => $pubid));
  1192. return FALSE;
  1193. }
  1194. elseif (count($citation) == 1 and $skip_existing == TRUE) {
  1195. // skip this publication, it already has a citation
  1196. return FALSE;
  1197. }
  1198. }
  1199. // ---------------------------------
  1200. // get the publication types
  1201. // ---------------------------------
  1202. $values = array(
  1203. 'pub_id' => $pub->pub_id,
  1204. 'type_id' => array(
  1205. 'name' => 'Publication Type',
  1206. ),
  1207. );
  1208. $ptypes = chado_generate_var('pubprop', $values, $options);
  1209. if ($ptypes) {
  1210. $ptypes = chado_expand_var($ptypes, 'field', 'pubprop.value', $options);
  1211. foreach ($ptypes as $ptype) {
  1212. $pub_array['Publication Type'][] = $ptype->value;
  1213. }
  1214. }
  1215. // ---------------------------------
  1216. // get the authors list
  1217. // ---------------------------------
  1218. $values = array(
  1219. 'pub_id' => $pub->pub_id,
  1220. 'type_id' => array(
  1221. 'name' => 'Authors',
  1222. ),
  1223. );
  1224. $authors = chado_generate_var('pubprop', $values);
  1225. $authors = chado_expand_var($authors, 'field', 'pubprop.value', $options);
  1226. if (count($authors) > 1) {
  1227. tripal_report_error('tripal_pub', TRIPAL_ERROR, "Publication has multiple author lists. It should have only one list: %pub_id",
  1228. array('%pub_id' => $pubid));
  1229. return FALSE;
  1230. }
  1231. else if (trim($authors->value)) {
  1232. $pub_array['Authors'] = $authors->value;
  1233. }
  1234. // if there is no 'Author's property then try to retreive authors from the pubauthor table
  1235. else {
  1236. $sql = "
  1237. SELECT string_agg(surname || ' ' || givennames, ', ')
  1238. FROM {pubauthor}
  1239. WHERE pub_id = :pub_id
  1240. GROUP BY pub_id
  1241. ";
  1242. $au = chado_query($sql, array(':pub_id' => $pub_id))->fetchField();
  1243. if ($au) {
  1244. $pub_array['Authors'] = $au;
  1245. }
  1246. }
  1247. //Get other props
  1248. $props = array(
  1249. 'Journal Abbreviation',
  1250. 'Elocation',
  1251. 'Media Code',
  1252. 'Conference Name',
  1253. 'Keywords',
  1254. 'Series Name',
  1255. 'pISSN',
  1256. 'Publication Date',
  1257. 'Journal Code',
  1258. 'Journal Alias',
  1259. 'Journal Country',
  1260. 'Published Location',
  1261. 'Publication Model',
  1262. 'Language Abbr',
  1263. 'Alias',
  1264. 'Publication Dbxref',
  1265. 'Copyright',
  1266. 'Abstract',
  1267. 'Notes',
  1268. 'Citation',
  1269. 'Language',
  1270. 'URL',
  1271. 'eISSN',
  1272. 'DOI',
  1273. 'ISSN',
  1274. 'Publication Code',
  1275. 'Comments',
  1276. 'Publisher',
  1277. 'Media Alias',
  1278. 'Original Title'
  1279. );
  1280. foreach ($props AS $prop) {
  1281. $sql =
  1282. "SELECT value FROM {pubprop}
  1283. WHERE type_id =
  1284. (SELECT cvterm_id
  1285. FROM {cvterm}
  1286. WHERE name = :cvtname AND cv_id =
  1287. (SELECT cv_id
  1288. FROM {cv}
  1289. WHERE name = 'tripal_pub'
  1290. )
  1291. )
  1292. AND pub_id = :pub_id
  1293. ";
  1294. $val = trim(chado_query($sql, array(':cvtname' => $prop, ':pub_id' => $pub->pub_id))->fetchField());
  1295. if ($val) {
  1296. $pub_array[$prop] =$val;
  1297. }
  1298. }
  1299. return $pub_array;
  1300. }