tripal_chado.pub_search.inc 27 KB

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