tripal_chado.pub_search.inc

Functions responsible for creating the publication search form that allows a user of the site to search for publications that are currently in Chado.

File

tripal_chado/includes/tripal_chado.pub_search.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. *
  5. * Functions responsible for creating the publication search form that
  6. * allows a user of the site to search for publications that are currently
  7. * in Chado.
  8. */
  9. function tripal_chado_pub_search_admin_form($form, &$form_state) {
  10. // -----------------------------------------
  11. // add in the fields for selecting which fields are used when search for pubs
  12. $form['searching'] = array(
  13. '#type' => 'fieldset',
  14. '#title' => t('Searching Options'),
  15. '#description' => t("The list of checkboxes below indicate which fields a user
  16. can search with when using the publication search tool. Check the fields that you want
  17. to allow users to search with. Click the 'Save configuration' button below to save changes."),
  18. );
  19. // get publication properties list
  20. $properties = array();
  21. $properties[] = 'Any Field';
  22. $sql = "
  23. SELECT DISTINCT CVTS.cvterm_id, CVTS.name, CVTS.definition
  24. FROM {cvtermpath} CVTP
  25. INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id
  26. INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id
  27. INNER JOIN {cv} ON CVTO.cv_id = CV.cv_id
  28. WHERE CV.name = 'tripal_pub' and
  29. (CVTO.name = 'Publication Details' or CVTS.name = 'Publication Type') and
  30. NOT CVTS.is_obsolete = 1
  31. ORDER BY CVTS.name ASC
  32. ";
  33. $prop_types = chado_query($sql);
  34. while ($prop = $prop_types->fetchObject()) {
  35. $properties[$prop->cvterm_id] = $prop->name;
  36. }
  37. $form['allowed_search_fields'] = array(
  38. '#type' => 'checkboxes',
  39. '#options' => $properties,
  40. '#default_value' => variable_get('tripal_pub_allowed_search_fields', array()),
  41. );
  42. $form['button'] = array(
  43. '#type' => 'submit',
  44. '#value' => 'Save configuration',
  45. '#name' => 'sumbit',
  46. );
  47. return $form;
  48. }
  49. /**
  50. *
  51. */
  52. function tripal_chado_pub_search_admin_form_submit($form, &$form_state) {
  53. // set the allowed search fields
  54. $allowed_fields = $form_state['values']['allowed_search_fields'];
  55. foreach ($allowed_fields as $cvterm_id => $selected) {
  56. if (!$selected) {
  57. unset($allowed_fields[$cvterm_id]);
  58. }
  59. }
  60. variable_set('tripal_pub_allowed_search_fields', $allowed_fields);
  61. drupal_set_message('Changes saved.');
  62. }
  63. /**
  64. * The page that contains the publication search form and the results for the search
  65. *
  66. * @ingroup tripal_pub
  67. */
  68. function tripal_chado_pub_search_page() {
  69. // This line may not be required, but on some sites the $_SESSION
  70. // variable wasn't being set for anonymous users. This line solves that
  71. // problem
  72. drupal_session_start();
  73. $limit = 25;
  74. // generate the search form
  75. $form = drupal_get_form('tripal_chado_pub_search_form');
  76. $output = drupal_render($form);
  77. // retrieve any results
  78. if (array_key_exists('tripal_chado_pub_search_form', $_SESSION) and
  79. $_SESSION['tripal_chado_pub_search_form']['perform_search']) {
  80. $num_criteria = $_SESSION['tripal_chado_pub_search_form']['num_criteria'];
  81. $from_year = $_SESSION['tripal_chado_pub_search_form']['from_year'];
  82. $to_year = $_SESSION['tripal_chado_pub_search_form']['to_year'];
  83. $search_array = array();
  84. $search_array['num_criteria'] = $num_criteria;
  85. $search_array['from_year'] = $from_year;
  86. $search_array['to_year'] = $to_year;
  87. for ($i = 0; $i <= $num_criteria; $i++) {
  88. $search_array['criteria'][$i]['search_terms'] = $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['search_terms'];
  89. $search_array['criteria'][$i]['scope'] = $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['scope'];
  90. $search_array['criteria'][$i]['mode'] = $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['mode'];
  91. $search_array['criteria'][$i]['operation'] = $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['operation'];
  92. }
  93. // get the list of publications from the remote database using the search criteria.
  94. $page = isset($_GET['page']) ? $_GET['page'] : '0';
  95. $offset = $page * $limit;
  96. $total_records = 0;
  97. $pubs = tripal_search_publications($search_array, $offset, $limit, $total_records);
  98. pager_default_initialize($total_records, $limit, 0);
  99. // iterate through the results and construct the table displaying the publications
  100. $rows = array();
  101. $i = $page * $limit + 1;
  102. foreach ($pubs as $pub) {
  103. // get the citation for this publication
  104. $values = array(
  105. 'pub_id' => $pub->pub_id,
  106. 'type_id' => array(
  107. 'name' => 'Citation',
  108. ),
  109. );
  110. $citation_rec = chado_generate_var('pubprop', $values);
  111. $citation_rec = chado_expand_var($citation_rec, 'field', 'pubprop.value');
  112. // if we have the citation then use it, otherwise, just use the title
  113. $title = htmlspecialchars($pub->title);
  114. $result = $title;
  115. $link = NULL;
  116. // tripal v2 link (node)
  117. if (module_exists('tripal_pub')) {
  118. $nid = chado_get_nid_from_id ('pub', $pub->pub_id);
  119. if ($nid) {
  120. $link = "/node/$nid";
  121. }
  122. }
  123. // try tripal v3 link (entity), if it exists, update the link to entity
  124. $entity_id = chado_get_record_entity_by_table('pub', $pub->pub_id);
  125. if ($entity_id) {
  126. $link = "/bio_data/$entity_id";
  127. }
  128. if ($link) {
  129. $result = l($title , $link, array('attributes' => array('target' => '_blank')));
  130. }
  131. if ($citation_rec->value) {
  132. $citation = htmlspecialchars($citation_rec->value);
  133. $result .= '<br>' . $citation;
  134. }
  135. $rows[] = array(
  136. number_format($i) . ".",
  137. $pub->pyear,
  138. $result
  139. );
  140. $i++;
  141. }
  142. $headers = array('', 'Year', 'Reference');
  143. $table = array(
  144. 'header' => $headers,
  145. 'rows' => $rows,
  146. 'attributes' => array(
  147. 'id' => 'tripal-pub-search-results-table',
  148. 'border' => '0',
  149. 'class' => array('tripal-data-table')
  150. ),
  151. 'sticky' => TRUE,
  152. 'caption' => '',
  153. 'colgroups' => array(),
  154. 'empty' => 'No publications found',
  155. );
  156. $results = theme_table($table);
  157. // generate the pager
  158. $pager = array(
  159. 'tags' => array(),
  160. 'element' => 0,
  161. 'parameters' => array(),
  162. 'quantity' => $limit,
  163. );
  164. $pager = theme_pager($pager);
  165. // join all to form the results
  166. $output .= "<p><b>Found " . number_format($total_records) .
  167. " Results</b></br>" . $results . $pager;
  168. }
  169. return $output;
  170. }
  171. /**
  172. * Provides the form to search pubmed
  173. *
  174. * @ingroup tripal_pub
  175. */
  176. function tripal_chado_pub_search_form($form, &$form_state) {
  177. // Default values can come in the following ways:
  178. //
  179. // 1) as elements of the $pub_importer object. This occurs when editing an existing importer
  180. // 2) in the $form_state['values'] array which occurs on a failed validation or
  181. // ajax callbacks from non submit form elements
  182. // 3) in the $form_state['input'] array which occurs on ajax callbacks from submit
  183. // form elements and the form is being rebuilt
  184. //
  185. // Set the default values. If the pub_import_id isn't already defined by the form values
  186. // and one is provided then look it up in the database
  187. $criteria = NULL;
  188. $num_criteria = 2;
  189. $from_year = '';
  190. $to_year = '';
  191. // if the session has variables then use those. This should only happen when
  192. // the 'Test Criteria' button is clicked.
  193. if (array_key_exists('storage', $form_state)) {
  194. $num_criteria = $form_state['storage']['num_criteria'];
  195. }
  196. if (array_key_exists('tripal_chado_pub_search_form', $_SESSION)) {
  197. $num_criteria = $_SESSION['tripal_chado_pub_search_form']['num_criteria'] ? $_SESSION['tripal_chado_pub_search_form']['num_criteria'] : $num_criteria;
  198. $from_year = $_SESSION['tripal_chado_pub_search_form']['from_year'] ? $_SESSION['tripal_chado_pub_search_form']['from_year'] : '';
  199. $to_year = $_SESSION['tripal_chado_pub_search_form']['to_year'] ? $_SESSION['tripal_chado_pub_search_form']['to_year'] : '';
  200. }
  201. if (array_key_exists('values', $form_state)) {
  202. $from_year = $form_state['values']['from_year'] ? $form_state['values']['from_year'] : $from_year;
  203. $to_year = $form_state['values']['to_year'] ? $form_state['values']['to_year'] : $to_year;
  204. }
  205. if (array_key_exists('input', $form_state) and !empty($form_state['input'])) {
  206. $from_year = $form_state['input']['from_year'] ? $form_state['input']['from_year'] : $from_year;
  207. $to_year = $form_state['input']['to_year'] ? $form_state['input']['to_year'] : $to_year;
  208. }
  209. if (array_key_exists('triggering_element', $form_state) and
  210. $form_state['triggering_element']['#name'] == 'add') {
  211. $num_criteria++;
  212. }
  213. if (array_key_exists('triggering_element', $form_state) and
  214. $form_state['triggering_element']['#name'] == 'remove') {
  215. $num_criteria--;
  216. }
  217. $form_state['storage']['num_criteria'] = $num_criteria;
  218. $form['admin-instructions'] = array(
  219. '#markup' => tripal_set_message(
  220. t('Administrators, you can select the fields with which a user can use to search, by checking the desired fields on the ' .
  221. l('Publication Search Settings Page', 'admin/tripal/storage/chado/pub-search-config', array('attributes' => array('target' => '_blank'))) . '
  222. in the section titled "Search Options". The selected fields will appear in the dropdowns below.'),
  223. TRIPAL_INFO,
  224. array('return_html' => 1)),
  225. );
  226. $form['instructions'] = array(
  227. '#markup' => t('To search for publications enter keywords in the text boxes below.
  228. You can limit your search by selecting the field in the dropdown box. Click the
  229. add and remove buttons to add additional fields for searching. '),
  230. );
  231. // get publication properties list
  232. $properties = array();
  233. $properties[] = 'Any Field';
  234. $sql = "
  235. SELECT DISTINCT CVTS.cvterm_id, CVTS.name, CVTS.definition
  236. FROM {cvtermpath} CVTP
  237. INNER JOIN {cvterm} CVTS ON CVTP.subject_id = CVTS.cvterm_id
  238. INNER JOIN {cvterm} CVTO ON CVTP.object_id = CVTO.cvterm_id
  239. INNER JOIN {cv} ON CVTO.cv_id = CV.cv_id
  240. WHERE CV.name = 'tripal_pub' and
  241. (CVTO.name = 'Publication Details' or CVTS.name = 'Publication Type') and
  242. NOT CVTS.is_obsolete = 1
  243. ORDER BY CVTS.name ASC
  244. ";
  245. $allowed_fields = variable_get('tripal_pub_allowed_search_fields', array());
  246. $prop_types = chado_query($sql);
  247. foreach ($prop_types as $prop) {
  248. if(array_key_exists($prop->cvterm_id, $allowed_fields) and $allowed_fields[$prop->cvterm_id] > 0) {
  249. $properties[$prop->cvterm_id] = $prop->name;
  250. }
  251. }
  252. for($i = 1; $i <= $num_criteria; $i++) {
  253. $search_terms = '';
  254. $scope = '';
  255. $operation = '';
  256. $mode = '';
  257. // first populate defaults using any values in the SESSION variable
  258. if (array_key_exists('tripal_chado_pub_search_form', $_SESSION)) {
  259. $search_terms = $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['search_terms'] ? $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['search_terms'] : $search_terms;
  260. $scope = $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['scope'] ? $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['scope'] : $scope;
  261. $mode = $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['mode'] ? $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['mode'] : $mode;
  262. $operation = $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['operation'] ? $_SESSION['tripal_chado_pub_search_form']['criteria'][$i]['operation'] : $operation;
  263. }
  264. if (array_key_exists('values', $form_state)) {
  265. $search_terms = array_key_exists("search_terms-$i", $form_state['values']) ? $form_state['values']["search_terms-$i"] : $search_terms;
  266. $scope = array_key_exists("scope-$i", $form_state['values']) ? $form_state['values']["scope-$i"] : $scope;
  267. $mode = array_key_exists("mode-$i", $form_state['values']) ? $form_state['values']["mode-$i"] : $mode;
  268. $operation = array_key_exists("operation-$i", $form_state['values']) ? $form_state['values']["operation-$i"] : $operation;
  269. }
  270. if (array_key_exists('input', $form_state)) {
  271. $search_terms = array_key_exists("search_terms-$i", $form_state['input']) ? $form_state['input']["search_terms-$i"] : $search_terms;
  272. $scope = array_key_exists("scope-$i", $form_state['input']) ? $form_state['input']["scope-$i"] : $scope;
  273. $mode = array_key_exists("mode-$i", $form_state['input']) ? $form_state['input']["mode-$i"] : $mode;
  274. $operation = array_key_exists("operation-$i", $form_state['input']) ? $form_state['input']["operation-$i"] : $operation;
  275. }
  276. // default to searching the title and abstract
  277. if (!$scope) {
  278. $scope = 'abstract';
  279. }
  280. $form['criteria'][$i]["search_terms-$i"] = array(
  281. '#type' => 'textfield',
  282. '#default_value' => $search_terms,
  283. '#required' => FALSE,
  284. );
  285. $form['criteria'][$i]["scope-$i"] = array(
  286. '#type' => 'select',
  287. '#options' => $properties,
  288. '#default_value' => $scope,
  289. '#attributes' => array('class' => array('tripal-pub-search-form-scope-select')),
  290. );
  291. /*
  292. $form['criteria'][$i]["mode-$i"] = array(
  293. '#type' => 'select',
  294. '#options' => array(
  295. 'Contains' => 'Contains',
  296. 'Starts With' => 'Starts With',
  297. 'Ends With' => 'Ends With',
  298. 'Exactly' => 'Exactly'),
  299. '#default_value' => $mode,
  300. );*/
  301. if ($i > 1) {
  302. $form['criteria'][$i]["operation-$i"] = array(
  303. '#type' => 'select',
  304. '#options' => array(
  305. 'AND' => 'AND',
  306. 'OR' => 'OR',
  307. 'NOT' => 'NOT'),
  308. '#default_value' => $operation,
  309. );
  310. }
  311. if ($i == $num_criteria) {
  312. if($i > 1) {
  313. $form['criteria'][$i]["remove-$i"] = array(
  314. '#type' => 'button',
  315. '#name' => 'remove',
  316. '#value' => t('Remove'),
  317. '#ajax' => array(
  318. 'callback' => "tripal_pubs_search_form_ajax_update",
  319. 'wrapper' => 'tripal-pub-search-form-criteria',
  320. 'effect' => 'fade',
  321. 'method' => 'replace',
  322. 'prevent' => 'click'
  323. ),
  324. // When this button is clicked, the form will be validated and submitted.
  325. // Therefore, we set custom submit and validate functions to override the
  326. // default form submit. In the validate function we set the form_state
  327. // to rebuild the form so the submit function never actually gets called,
  328. // but we need it or Drupal will run the default validate anyway.
  329. // we also set #limit_validation_errors to empty so fields that
  330. // are required that don't have values won't generate warnings.
  331. '#submit' => array('tripal_chado_pub_search_form_ajax_button_submit'),
  332. '#validate' => array('tripal_chado_pub_search_form_ajax_button_validate'),
  333. '#limit_validation_errors' => array(),
  334. );
  335. }
  336. $form['criteria'][$i]["add-$i"] = array(
  337. '#type' => 'button',
  338. '#name' => 'add',
  339. '#value' => t('Add'),
  340. '#ajax' => array(
  341. 'callback' => "tripal_pubs_search_form_ajax_update",
  342. 'wrapper' => 'tripal-pub-search-form-criteria',
  343. 'effect' => 'fade',
  344. 'method' => 'replace',
  345. 'prevent' => 'click'
  346. ),
  347. // When this button is clicked, the form will be validated and submitted.
  348. // Therefore, we set custom submit and validate functions to override the
  349. // default form submit. In the validate function we set the form_state
  350. // to rebuild the form so the submit function never actually gets called,
  351. // but we need it or Drupal will run the default validate anyway.
  352. // we also set #limit_validation_errors to empty so fields that
  353. // are required that don't have values won't generate warnings.
  354. '#submit' => array('tripal_chado_pub_search_form_ajax_button_submit'),
  355. '#validate' => array('tripal_chado_pub_search_form_ajax_button_validate'),
  356. '#limit_validation_errors' => array(),
  357. );
  358. }
  359. }
  360. $form['criteria']["date"] = array(
  361. '#type' => 'select',
  362. '#options' => array('Years' => 'Years'),
  363. '#attributes' => array('class' => array('tripal-pub-search-form-scope-select')),
  364. );
  365. $form['criteria']["from_year"] = array(
  366. '#type' => 'textfield',
  367. '#default_value' => $from_year,
  368. '#required' => FALSE,
  369. '#title' => 'from',
  370. '#size' => 4,
  371. '#maxlength' => 4,
  372. );
  373. $form['criteria']["to_year"] = array(
  374. '#type' => 'textfield',
  375. '#default_value' => $to_year,
  376. '#required' => FALSE,
  377. '#title' => 'to',
  378. '#size' => 4,
  379. '#maxlength' => 4,
  380. );
  381. $form['search'] = array(
  382. '#type' => 'submit',
  383. '#value' => t('Search'),
  384. );
  385. $form['reset'] = array(
  386. '#type' => 'submit',
  387. '#value' => t('Reset'),
  388. );
  389. $form['criteria']['#theme'] = 'tripal_chado_pub_search_setup_form_elements';
  390. return $form;
  391. }
  392. /**
  393. * This function is used to rebuild the form if an ajax call is made vai a button.
  394. * The button causes the form to be submitted. We don't want this so we override
  395. * the validate and submit routines on the form button. Therefore, this function
  396. * only needs to tell Drupal to rebuild the form
  397. *
  398. * @ingroup tripal_pub
  399. */
  400. function tripal_chado_pub_search_form_ajax_button_submit() {
  401. $form_state['rebuild'] = TRUE;
  402. }
  403. /**
  404. * This function is just a dummy to override the default form submit on ajax calls for buttons
  405. *
  406. * @ingroup tripal_pub
  407. */
  408. function tripal_chado_pub_search_form_ajax_button_validate() {
  409. // do nothing
  410. }
  411. /**
  412. * Validate the tripal_chado_pub_search_form form
  413. *
  414. * @ingroup tripal_pub
  415. */
  416. function tripal_chado_pub_search_form_validate($form, &$form_state) {
  417. $num_criteria = $form_state['storage']['num_criteria'];
  418. $from_year = $form_state['values']['from_year'];
  419. $to_year = $form_state['values']['to_year'];
  420. $op = $form_state['values']['op'];
  421. // no need to vlaidate on a reset
  422. if ($op == 'Reset') {
  423. return;
  424. }
  425. if($from_year and !$to_year) {
  426. form_set_error('to_year', 'Please provide a 4-digit year.');
  427. }
  428. if(!$from_year and $to_year) {
  429. form_set_error('from_year', 'Please provide a 4-digit year.');
  430. }
  431. if($from_year and !preg_match('/\d\d\d\d/' , $from_year)) {
  432. form_set_error('from_year', 'Please provide a 4-digit year.');
  433. }
  434. if($to_year and !preg_match('/\d\d\d\d/' , $to_year)) {
  435. form_set_error('to_year', 'Please provide a 4-digit year.');
  436. }
  437. }
  438. /**
  439. * Submit the tripal_chado_pub_search_form form
  440. *
  441. * @ingroup tripal_pub
  442. */
  443. function tripal_chado_pub_search_form_submit($form, &$form_state) {
  444. $num_criteria = $form_state['storage']['num_criteria'];
  445. $from_year = $form_state['values']['from_year'];
  446. $to_year = $form_state['values']['to_year'];
  447. $op = $form_state['values']['op'];
  448. // set the session variables
  449. if($op == 'Search') {
  450. $_SESSION['tripal_chado_pub_search_form']['num_criteria'] = $num_criteria;
  451. unset($_SESSION['tripal_chado_pub_search_form']['criteria']);
  452. for ($i = 0; $i <= $num_criteria; $i++) {
  453. $search_terms = '';
  454. $scope = '';
  455. $mode = 'Contains';
  456. $operation = '';
  457. if (array_key_exists("search_terms-$i", $form_state['values'])) {
  458. $search_terms = trim($form_state['values']["search_terms-$i"]);
  459. }
  460. if (array_key_exists("scope-$i", $form_state['values'])) {
  461. $scope = $form_state['values']["scope-$i"];
  462. }
  463. if (array_key_exists("operation-$i", $form_state['values'])) {
  464. $operation = $form_state['values']["operation-$i"];
  465. }
  466. //$mode = $form_state['values']["mode-$i"];
  467. $_SESSION['tripal_chado_pub_search_form']['criteria'][$i] = array(
  468. 'search_terms' => $search_terms,
  469. 'scope' => $scope,
  470. 'mode' => $mode,
  471. 'operation' => $operation
  472. );
  473. }
  474. $_SESSION['tripal_chado_pub_search_form']['from_year'] = $from_year;
  475. $_SESSION['tripal_chado_pub_search_form']['to_year'] = $to_year;
  476. $_SESSION['tripal_chado_pub_search_form']['perform_search'] = 1;
  477. }
  478. if($op == 'Reset') {
  479. unset($_SESSION['tripal_chado_pub_search_form']);
  480. }
  481. }
  482. /**
  483. * Ajax callback to update the form
  484. *
  485. * @param $form
  486. * The form array
  487. * @param $form_state
  488. * The form state array
  489. *
  490. * @ingroup tripal_pub
  491. */
  492. function tripal_pubs_search_form_ajax_update($form, $form_state) {
  493. return $form['criteria'];
  494. }
  495. /**
  496. * Theme the tripal_chado_pub_search_setup_form form
  497. *
  498. * @ingroup tripal_pub
  499. */
  500. function theme_tripal_chado_pub_search_setup_form_elements($variables) {
  501. $form = $variables['form'];
  502. $rows = array();
  503. // put each criteria element in a single table row
  504. foreach ($form as $i => $element) {
  505. if(is_numeric($i)) {
  506. $rows[] = array(
  507. drupal_render($element["operation-$i"]),
  508. drupal_render($element["scope-$i"]),
  509. //drupal_render($element["mode-$i"]) .
  510. drupal_render($element["search_terms-$i"]),
  511. array(
  512. 'data' => drupal_render($element["add-$i"]) . drupal_render($element["remove-$i"]),
  513. 'nowrap' => 'nowrap',
  514. ),
  515. );
  516. }
  517. }
  518. // add in the from_year and to_year elements as the final row of the table
  519. $rows[] = array(
  520. '&nbsp;',
  521. drupal_render($form['date']),
  522. array(
  523. 'data' =>
  524. "<div id=\"pub-search-form-dates-row\">
  525. <div id=\"pub-search-form-dates\"> ".
  526. drupal_render($form['from_year']) .
  527. drupal_render($form['to_year']) . "
  528. </div>
  529. </div>
  530. ",
  531. ),
  532. ''
  533. );
  534. $headers = array();
  535. $table = array(
  536. 'header' => $headers,
  537. 'rows' => $rows,
  538. 'attributes' => array(
  539. 'id' => 'tripal-pub-search-form-table',
  540. 'border' => '0',
  541. 'class' => 'tripal-data-table'
  542. ),
  543. 'sticky' => TRUE,
  544. 'caption' => '',
  545. 'colgroups' => array(),
  546. 'empty' => '',
  547. );
  548. $results = '<div id="tripal-pub-search-form-criteria">';
  549. $results .= theme_table($table);
  550. $results .= '</div>';
  551. return $results;
  552. }
  553. /**
  554. * Builds the SQL statement need to search Chado for the publications
  555. * that match the user supplied criteria. Tpyically, this function is
  556. * called by the search form generated by the tripal_chado_pub_search_form()
  557. * function but this function is included in the API for calling by anyone.
  558. *
  559. * @param $search_array
  560. * An array of search criteria provided by the user. The search array is
  561. * an associative array with the following keys:
  562. * 'num_criteria': an integer indicating the number of search criteria
  563. * supplied
  564. * 'from_year': filters records by a start year
  565. * 'to_year': filters records by an end year
  566. * 'criteria': an array of criteria. Each criteria is an associative
  567. * array with the following keys:
  568. * 'search_terms': The text used for searching
  569. * 'scope': The cvterm_id of the property used for
  570. * filtering
  571. * 'mode': The operation (e.g. AND, OR or NOT)
  572. * @param $offset
  573. * The offset for paging records. The first record returned will be
  574. * at the offset indicated here, and the next $limit number of records
  575. * will be returned.
  576. *
  577. * @param $limit
  578. * The number of records to retrieve
  579. *
  580. * @param total_records
  581. * A value passed by reference. This value will get set to the total
  582. * number of matching records
  583. *
  584. * @return
  585. * a PDO database object of the query results.
  586. *
  587. * @ingroup tripal_pub
  588. */
  589. function tripal_search_publications($search_array, $offset, $limit, &$total_records) {
  590. // Build the SQL based on the criteria provided by the user
  591. $select = "SELECT DISTINCT P.* ";
  592. $from = "FROM {pub} P INNER JOIN {cvterm} CVT on CVT.cvterm_id = P.type_id ";
  593. $where = "WHERE (NOT P.title = 'null') ";
  594. $order = "ORDER BY P.pyear DESC, P.title ASC";
  595. $args = array();
  596. $join = 0;
  597. $num_criteria = $search_array['num_criteria'];
  598. $from_year = $search_array['from_year'];
  599. $to_year = $search_array['to_year'];
  600. for ($i = 1; $i <= $num_criteria; $i++) {
  601. $value = $search_array['criteria'][$i]['search_terms'];
  602. $type_id = $search_array['criteria'][$i]['scope'];
  603. $mode = $search_array['criteria'][$i]['mode'];
  604. $op = $search_array['criteria'][$i]['operation'];
  605. // skip criteria with no values
  606. if(!$value) {
  607. continue;
  608. }
  609. // to prevent SQL injection make sure our operator is
  610. // what we expect
  611. if ($op and $op != "AND" and $op != "OR" and $op != 'NOT') {
  612. $op = 'AND';
  613. }
  614. if ($op == 'NOT') {
  615. $op = 'AND NOT';
  616. }
  617. if (!$op) {
  618. $op = 'AND';
  619. }
  620. // get the scope type
  621. $values = array('cvterm_id' => $type_id);
  622. $cvterm = chado_select_record('cvterm', array('name'), $values);
  623. $type_name = '';
  624. if (count($cvterm) > 0) {
  625. $type_name = $cvterm[0]->name;
  626. }
  627. if ($type_name == 'Title') {
  628. $where .= " $op (lower(P.title) LIKE lower(:crit$i)) ";
  629. $args[":crit$i"] = '%' . $value . '%';
  630. }
  631. elseif ($type_name == 'Year') {
  632. $where .= " $op (lower(P.pyear) = lower(:crit$i)) ";
  633. $args[":crit$i"] = '%' . $value . '%';
  634. }
  635. elseif ($type_name == 'Volume') {
  636. $where .= " $op (lower(P.volume) = lower(:crit$i)) ";
  637. $args[":crit$i"] = '%' . $value . '%';
  638. }
  639. elseif ($type_name == 'Issue') {
  640. $where .= " $op (lower(P.issue) = lower(:crit$i)) ";
  641. $args[":crit$i"] = '%' . $value . '%';
  642. }
  643. elseif ($type_name == 'Journal Name') {
  644. $from .= " LEFT JOIN {pubprop} PP$i ON PP$i.pub_id = P.pub_id AND PP$i.type_id = :crit$i ";
  645. $where .= " $op ((lower(P.series_name) = lower(:crit$i) and CVT.name = 'Journal Article') OR
  646. (lower(PP$i.value) = lower(:crit$i))) ";
  647. $args[":crit$i"] = $type_id;
  648. }
  649. elseif ($type_name == 'Conference Name') {
  650. $from .= " LEFT JOIN {pubprop} PP$i ON PP$i.pub_id = P.pub_id AND PP$i.type_id = :crit$i ";
  651. $where .= " $op ((lower(P.series_name) = lower(:crit$i) and CVT.name = 'Conference Proceedings') OR
  652. (lower(PP$i.value) = lower(:crit$i))) ";
  653. $args[":crit$i"] = $type_id;
  654. }
  655. elseif ($type_name == 'Publication Type') {
  656. $where .= " $op (lower(CVT.name) = lower(:crit$i))";
  657. $args[":crit$i"] = $value;
  658. }
  659. elseif ($type_id == 0) { //'Any Field'
  660. $from .= " LEFT JOIN {pubprop} PP$i ON PP$i.pub_id = P.pub_id ";
  661. $where .= " $op (lower(PP$i.value) LIKE lower(:crit$i) OR
  662. lower(P.title) LIKE lower(:crit$i) OR
  663. lower(P.volumetitle) LIKE lower(:crit$i) OR
  664. lower(P.publisher) LIKE lower(:crit$i) OR
  665. lower(P.uniquename) LIKE lower(:crit$i) OR
  666. lower(P.pubplace) LIKE lower(:crit$i) OR
  667. lower(P.miniref) LIKE lower(:crit$i) OR
  668. lower(P.series_name) LIKE lower(:crit$i)) ";
  669. $args[":crit$i"] = '%' . $value . '%';
  670. }
  671. // for all other properties
  672. else {
  673. $from .= " LEFT JOIN {pubprop} PP$i ON PP$i.pub_id = P.pub_id AND PP$i.type_id = :type_id$i ";
  674. $where .= " $op (lower(PP$i.value) LIKE lower(:crit$i)) ";
  675. $args[":crit$i"] = '%' . $value . '%';
  676. $args[":type_id$i"] = $type_id;
  677. }
  678. }
  679. if($from_year and $to_year) {
  680. $where .= " AND (P.pyear ~ '....' AND to_number(P.pyear,'9999') >= :from$i AND to_number(P.pyear,'9999') <= :to$i) ";
  681. $args[":from$i"] = $from_year;
  682. $args[":to$i"] = $to_year;
  683. }
  684. $sql = "$select $from $where $order LIMIT " . (int) $limit . ' OFFSET ' . (int) $offset;
  685. $count = "SELECT count(*) FROM ($select $from $where $order) as t1";
  686. // first get the total number of matches
  687. $total_records = chado_query($count, $args)->fetchField();
  688. $results = chado_query($sql, $args);
  689. return $results;
  690. }