Tripal Plant PopGen Submit
/home/docs/checkouts/readthedocs.org/user_builds/tpps/checkouts/latest/tpps.module
Go to the documentation of this file.
1 <?php
2 
8 define("TPPS_MAJOR_VERSION", 1);
9 define("TPPS_MINOR_VERSION", 2);
10 define("TPPS_JS_PATH", '/js/tpps.js');
11 define("TPPS_CSS_PATH", '/css/tpps.css');
12 define("TPPS_PAGE_1", 1);
13 define("TPPS_PAGE_2", 2);
14 define("TPPS_PAGE_3", 3);
15 define("TPPS_PAGE_4", 4);
16 define("TPPS_TEMP_XLSX", "temporary://tpps_xlsx");
17 define("TPPS_TEMP_ZIP", "temporary://tpps_zip");
18 define("TPPS_OLS_BASE", "http://www.ebi.ac.uk/ols/api/");
19 require_once 'includes/display.inc';
20 require_once 'includes/chado_utils.inc';
21 require_once 'includes/init_project.inc';
22 require_once 'includes/standard_coord.inc';
23 require_once 'includes/cron.inc';
24 require_once 'includes/file_utils.inc';
25 require_once 'includes/submit_email.inc';
26 require_once 'includes/status_bar.inc';
27 require_once 'includes/accession_coordinates.inc';
28 require_once 'includes/submissions.inc';
29 require_once 'includes/zenodo.inc';
30 require_once 'includes/match_trees.inc';
31 require_once 'includes/ncbi_utils.inc';
32 require_once 'includes/form_utils.inc';
33 require_once 'includes/details.inc';
34 require_once 'includes/cvterm_utils.inc';
35 require_once 'api/tpps.api.inc';
36 
40 function tpps_menu() {
41 
42  $items = array();
43 
44  $items['tpps'] = array(
45  'title' => 'Tripal Plant PopGen Submit',
46  'page callback' => 'drupal_get_form',
47  'page arguments' => array('tpps_main'),
48  'access arguments' => array('access content'),
49  // 'access callback' => 'tpps_access',
50  // 'access arguments' => array('access tpps form'),
51  'type' => MENU_NORMAL_ITEM,
52  );
53 
54  $items['tpps/%'] = array(
55  'title' => 'Tripal Plant PopGen Submit',
56  'page callback' => 'drupal_get_form',
57  'page arguments' => array('tpps_main', 1),
58  'access callback' => 'tpps_access',
59  'access arguments' => array('access tpps form', 1),
60  'type' => MENU_NORMAL_ITEM,
61  );
62 
63  $items['tpps/%/pre-validate'] = array(
64  'title' => 'TPPS File Pre-Validation',
65  'page callback' => 'tpps_pre_validate_init',
66  'page arguments' => array(1),
67  'access callback' => 'tpps_access',
68  'access arguments' => array('access tpps form', 1),
69  'type' => MENU_CALLBACK,
70  );
71 
72  $items['tpps/%/pre-validate/%/status'] = array(
73  'title' => 'TPPS File Pre-Validation',
74  'page callback' => 'tpps_pre_validate_status',
75  'page arguments' => array(1, 3),
76  'access callback' => 'tpps_access',
77  'access arguments' => array('access tpps form', 1),
78  'type' => MENU_CALLBACK,
79  );
80 
81  $items['tpps/%/edit-publication'] = array(
82  'title' => 'TPPS Edit Publication Information',
83  'page callback' => 'drupal_get_form',
84  'page arguments' => array('tpps_submission_edit_publication', 1),
85  'access callback' => 'tpps_access',
86  'access arguments' => array('view own tpps submission', 1),
87  'type' => MENU_NORMAL_ITEM,
88  );
89 
90  $items['tpps/details'] = array(
91  'title' => 'TPPS Details',
92  'page callback' => 'tpps_details',
93  'page arguments' => array(),
94  'access callback' => 'tpps_access',
95  'access arguments' => array('access tpps details'),
96  'type' => MENU_NORMAL_ITEM,
97  );
98 
99  $items['tpps/details/top'] = $items['tpps/details'];
100  $items['tpps/details/top']['page callback'] = 'tpps_details_top_callback';
101  $items['tpps/details/top']['type'] = MENU_CALLBACK;
102 
103  $items['tpps/details/%'] = $items['tpps/details'];
104  $items['tpps/details/%']['page arguments'] = array(2);
105 
106  $items['tpps/details/%/%'] = $items['tpps/details/%'];
107  $items['tpps/details/%/%']['page arguments'] = array(2, 3);
108  $items['tpps/details/%/%']['page callback'] = 'tpps_details_tab';
109  $items['tpps/details/%/%']['type'] = MENU_CALLBACK;
110 
111  $items['user/%/tpps'] = array(
112  'title' => 'TPPS Submissions',
113  'page callback' => 'tpps_tab_create',
114  'page arguments' => array(1),
115  'access callback' => 'tpps_access',
116  'access arguments' => array('user tpps submissions', 1),
117  'type' => MENU_LOCAL_TASK,
118  );
119 
120  $items['tpps-submission/%/delete'] = array(
121  'title' => 'TPPS Delete Submission',
122  'page callback' => 'tpps_delete_submission',
123  'page arguments' => array(1),
124  'access callback' => 'tpps_access',
125  'access arguments' => array('tpps delete submission', 1),
126  'type' => MENU_CALLBACK,
127  );
128 
129  $items['completed-submission/%'] = array(
130  'title' => 'TPPS Completed Submission',
131  'page callback' => 'tpps_completed_display',
132  'page arguments' => array(1),
133  'access callback' => 'tpps_access',
134  'access arguments' => array('view own tpps submission', 1),
135  'type' => MENU_NORMAL_ITEM,
136  );
137 
138  $items['tpps-admin-panel'] = array(
139  'title' => 'TPPS Admin Panel',
140  'page callback' => 'drupal_get_form',
141  'page arguments' => array('tpps_admin_panel'),
142  'access callback' => 'tpps_access',
143  'access arguments' => array('approve tpps submissions'),
144  'type' => MENU_NORMAL_ITEM,
145  'file' => 'admin/panel.php',
146  );
147 
148  $items['tpps-admin-panel/%'] = array(
149  'title' => 'TPPS Admin Panel',
150  'page callback' => 'drupal_get_form',
151  'page arguments' => array('tpps_admin_panel', 1),
152  'access callback' => 'tpps_access',
153  'access arguments' => array('approve tpps submissions'),
154  'type' => MENU_NORMAL_ITEM,
155  'file' => 'admin/panel.php',
156  );
157 
158  $items['tpps-admin-panel-logs/%'] = array(
159  'title' => 'TPPS Admin Panel',
160  'page callback' => 'drupal_get_form',
161  'page arguments' => array('tpps_admin_panel_logs', 1),
162  'access callback' => 'tpps_access',
163  'access arguments' => array('approve tpps submissions'),
164  'type' => MENU_NORMAL_ITEM,
165  'file' => 'admin/logs.php',
166  );
167 
168  $items['tpps-admin-panel/file-diagnostics/%'] = array(
169  'title' => 'TPPS Admin Panel',
170  'page callback' => 'drupal_get_form',
171  'page arguments' => array('tpps_admin_files_diagnostics_page', 2),
172  'access callback' => 'tpps_access',
173  'access arguments' => array('administer tpps module'),
174  'type' => MENU_NORMAL_ITEM,
175  'file' => 'admin/pages.php',
176  );
177 
178  $items['tpps-admin-panel/state-compare/%/%'] = array(
179  'title' => 'TPPS Admin Panel',
180  'page callback' => 'drupal_get_form',
181  'page arguments' => array('tpps_admin_state_compare_page', 2, 3),
182  'access callback' => 'tpps_access',
183  'access arguments' => array('administer tpps module'),
184  'type' => MENU_NORMAL_ITEM,
185  'file' => 'admin/pages.php',
186  );
187 
188  $items['tpps/doi/%'] = array(
189  'title' => 'TPPS DOI',
190  'page callback' => 'tpps_manage_doi',
191  'page arguments' => array(2),
192  'access callback' => 'tpps_access',
193  'access arguments' => array('access content'),
194  'type' => MENU_NORMAL_ITEM,
195  'file' => 'includes/manage_doi.inc',
196  );
197 
198  $items['admin/config/content/tpps'] = array(
199  'title' => 'TPPS Settings',
200  'description' => 'Configuration for TPPS module',
201  'page callback' => 'drupal_get_form',
202  'page arguments' => array('tpps_admin_settings'),
203  'access callback' => 'tpps_access',
204  'access arguments' => array('administer tpps module'),
205  'type' => MENU_NORMAL_ITEM,
206  'file' => 'admin/config.php',
207  );
208 
209  $items['tpps/autocomplete/%'] = array(
210  'title' => 'TPPS Autocomplete',
211  'description' => 'Autocomplete functions for TPPS module',
212  'page callback' => 'tpps_autocomplete',
213  'page arguments' => array(2),
214  'access callback' => 'tpps_access',
215  'access arguments' => array('access content'),
216  'type' => MENU_NORMAL_ITEM,
217  'file' => 'ajax/tpps_ajax.php',
218  );
219 
220  /*
221  * Ajax Callback for accession coordinates.
222  */
223  $items['tpps-accession'] = array(
224  'title' => 'TPPS Accession coordinates',
225  'page callback' => 'tpps_accession_coordinates',
226  'access callback' => 'tpps_access',
227  'access arguments' => array('access content'),
228  'type' => MENU_CALLBACK,
229  );
230 
231  $items['tpps-preview-file'] = array(
232  'title' => 'TPPS Preview File',
233  'page callback' => 'tpps_preview_file',
234  'access callback' => 'tpps_access',
235  'access arguments' => array('access content'),
236  'type' => MENU_CALLBACK,
237  );
238 
239  $items['tpps-tag'] = array(
240  'title' => 'TPPS Submission Tags',
241  'page callback' => 'tpps_submission_tag_manage',
242  'access callback' => 'tpps_access',
243  'access arguments' => array('administer tpps module'),
244  'type' => MENU_NORMAL_ITEM,
245  );
246 
247  $items['tpps-tag/create'] = array(
248  'title' => 'Create new TPPS Submission Tag',
249  'page callback' => 'drupal_get_form',
250  'page arguments' => array('tpps_submission_tag_create'),
251  'access callback' => 'tpps_access',
252  'access arguments' => array('administer tpps module'),
253  'type' => MENU_LOCAL_ACTION,
254  );
255 
256  $items['tpps-tag/edit/%'] = array(
257  'title' => 'TPPS Edit Tag',
258  'page callback' => 'drupal_get_form',
259  'page arguments' => array('tpps_submission_tag_edit', 2),
260  'access callback' => 'tpps_access',
261  'access arguments' => array('administer tpps module'),
262  'type' => MENU_NORMAL_ITEM,
263  );
264 
265  $items['tpps-tag/%/%/%'] = array(
266  'title' => 'TPPS Add/Remove Tag',
267  'page callback' => 'tpps_submission_add_remove_tag',
268  'page arguments' => array(1, 2, 3),
269  'access callback' => 'tpps_access',
270  'access arguments' => array('administer tpps module'),
271  'type' => MENU_CALLBACK,
272  );
273 
274  $items['snp-assay-file/upload'] = array(
275  'title' => 'Autocomplete for snp files',
276  'page callback' => 'tpps_snpassay_file_selector',
277  'access arguments' => array('access content'),
278  'type' => MENU_CALLBACK
279  );
280 
281  $items = array_merge($items, tpps_api_paths());
282 
283  return $items;
284 }
285 
291 function tpps_permission() {
292  $perms = array();
293 
294  $perms['access tpps form'] = array(
295  'title' => t('Access TPPS Form'),
296  'description' => t('Access TPPS Submission form and create submissions.'),
297  );
298 
299  $perms['access tpps details'] = array(
300  'title' => t('Access TPPS Details'),
301  'description' => t('Access TPPS Complete Submissions Details page.'),
302  );
303 
304  $perms['administer tpps module'] = array(
305  'title' => t('Administer TPPS module'),
306  'description' => t('Make changes to TPPS configuration.'),
307  );
308 
309  $perms['user tpps submissions'] = array(
310  'title' => t('User TPPS Submissions'),
311  'description' => t('View all TPPS Submissions for a particular user.'),
312  );
313 
314  $perms['approve tpps submissions'] = array(
315  'title' => t('Approve/Reject TPPS submissions'),
316  'description' => t('Approve or reject pending TPPS submissions.'),
317  );
318 
319  $perms['tpps delete submission'] = array(
320  'title' => t('Delete TPPS submissions'),
321  'description' => t('Delete incomplete TPPS submissions.'),
322  );
323 
324  $perms['view own tpps submission'] = array(
325  'title' => t('View own TPPS submissions'),
326  'description' => t('View TPPS submissions as a particular user.'),
327  );
328 
329  return $perms;
330 }
331 
341 function tpps_access() {
342  global $user;
343 
344  if ($user->uid == 1) {
345  return TRUE;
346  }
347 
348  $args = func_get_args();
349  $permission = $args[0] ?? NULL;
350  if (gettype($permission) != 'string') {
351  return FALSE;
352  }
353 
354  if (!user_access($permission)) {
355  return FALSE;
356  }
357 
358  switch ($permission) {
359  case 'access tpps form':
360  $accession = $args[1] ?? NULL;
361  if (empty($accession) or $accession == 'new') {
362  return TRUE;
363  }
364 
365  $params = drupal_get_query_parameters(NULL, array());
366  $path = $params['q'];
367  preg_match('/^([^\/]+)\/?.*$/', $path, $matches);
368  $form_type = $matches[1] ?? NULL;
369  $full_state = tpps_load_submission($accession);
370  $submission_type = $full_state['tpps_type'] ?? 'tpps';
371 
372  if (($state = tpps_load_submission($accession, FALSE))) {
373  $type_pass = ($submission_type == $form_type) || preg_match('/^tpps\/TGDR[0-9]+\/.+$/', $path);
374  if ($state->status == "Incomplete" and $state->uid == $user->uid and $type_pass) {
375  return TRUE;
376  }
377  }
378  return FALSE;
379 
380  case 'user tpps submissions':
381  $uid = $args[1] ?? NULL;
382  if (!empty($uid) and $uid == $user->uid) {
383  return TRUE;
384  }
385 
386  return FALSE;
387 
388  case 'view own tpps submission':
389  $accession = $args[1] ?? NULL;
390  if (($state = tpps_load_submission($accession, FALSE))) {
391  if ($state->status != "Incomplete" and $state->uid == $user->uid) {
392  return TRUE;
393  }
394  }
395  return FALSE;
396 
397  case 'tpps delete submission':
398  $accession = $args[1] ?? NULL;
399  if (($state = tpps_load_submission($accession, FALSE))) {
400  if ($state->status == "Incomplete" and $user->uid == $state->uid) {
401  return TRUE;
402  }
403  }
404  return FALSE;
405 
406  default:
407  return TRUE;
408  }
409 }
410 
416 function tpps_cronapi() {
417  $items = array();
418 
419  $freq = variable_get('tpps_refresh_views_job_frequency', '0 */12 * * *');
420  $items['tpps_refresh_views'] = array(
421  'title' => t('Refresh TPPS and CartograPlant views'),
422  'callback' => 'tpps_refresh_views',
423  'scheduler' => array(
424  'name' => 'crontab',
425  'crontab' => array(
426  'rules' => array($freq),
427  ),
428  ),
429  );
430 
431  $freq = variable_get('tpps_delayed_submissions_job_frequency', '0 */6 * * *');
432  $items['tpps_delayed_submissions'] = array(
433  'title' => t('Check to see if any of the delayed TPPS submissions should be published yet'),
434  'callback' => 'tpps_delayed_submissions',
435  'scheduler' => array(
436  'name' => 'crontab',
437  'crontab' => array(
438  'rules' => array($freq),
439  ),
440  ),
441  );
442 
443  return $items;
444 }
445 
451 function tpps_mail($key, array &$message, array $params) {
452  if (isset($params['subject'])) {
453  $message['subject'] = $params['subject'];
454  }
455  if (isset($params['body'])) {
456  $message['body'][] = $params['body'];
457  }
458  if (isset($params['headers']) && is_array($params['headers'])) {
459  $message['headers'] += $params['headers'];
460  }
461 
462  switch ($key) {
463  case 'user_recieved':
464  $message['body'][] = "Congratulations!<br><br>
465  Your TPPS submission has been received and is pending approval from a site administrator! Here's a brief summary of the information you provided:<ul>
466  <li>Primary Author: {$params['author']}</li>
467  <li>Organization: {$params['org']}</li>
468  <li>Publication title: {$params['title']}</li>
469  <li>Journal: {$params['journal']}</li>
470  <li>Organisms: {$params['organisms']['number']}</li>";
471  for ($i = 1; $i <= $params['organisms']['number']; $i++) {
472  $message['body'][] = " <li>Organism $i: {$params['organisms'][$i]}</li>";
473  }
474 
475  $message['body'][] =
476  "<li>Study Type: {$params['study_type']}</li>
477  <li>Data Type: {$params['data_type']}</li></ul>
478  You can view your submission <a href='{$params['base_url']}/completed-submission/{$params['accession']}' style='text-decoration: underline;'>here.</a><br>
479  If you have any questions about your submission, please feel free to contact us <a href='{$params['base_url']}/contactform'>here</a>.<br><br>";
480  break;
481 
482  case 'admin_recieved':
483  $message['body'][] = "Attention:<br><br>
484  User {$params['user_mail']} has completed a TPPS Submission, titled {$params['title']}.<br>
485  Click <a href='{$params['base_url']}/tpps-admin-panel/{$params['accession']}' style='text-decoration: underline;'>here</a> to manage or approve this submission.";
486  break;
487 
488  case 'user_rejected':
489  $message['body'][] =
490  "To whom it may concern:<br><br>
491  Unfortunately, your submission to TPPS has been rejected. If you would like, you can log into TPPS and edit your submission <a href='{$params['base_url']}/user/{$params['uid']}/TPPS'>here</a><br><br>
492  The administrator who rejected your submission provided the following reason:<br>
493  <blockquote>
494  {$params['reject-reason']}
495  </blockquote>";
496  break;
497 
498  case 'user_approved':
499  $message['body'][] =
500  "Congratulations! Your submission to TPPS has been approved!<br><br>
501  You may now refer to your submitted data with accession number {$params['accession']}.<br><br>
502  You can still view your submission from your <a href=\"{$params['base_url']}/completed-submission/{$params['accession']}\">TPPS Completed Submissions</a> tab.<br>
503  Your submission should be public on the <a href=\"{$params['base_url']}/tpps/details\">TPPS/TGDR Landing Page</a> within the next 24 hours.<br>
504  To generate a DOI for your submission, please click <a href=\"{$params['base_url']}/tpps/doi/{$params['accession']}\">here</a>.";
505  break;
506 
507  default:
508  break;
509  }
510 }
511 
518 function tpps_element_info_alter(&$type) {
519  if (isset($type['textfield']['#maxlength'])) {
520  $type['textfield']['#maxlength'] = 512;
521  }
522  $type['managed_file']['#process'][] = 'tpps_managed_file_process';
523 }
524 
541 function tpps_managed_file_process(array $element, array &$form_state, array $form) {
542  if ($form_state['build_info']['form_id'] !== 'tpps_main') {
543  return $element;
544  }
545  if (isset($element['columns'])) {
546  require_once 'ajax/tpps_ajax.php';
547  $fid = $element['#value']['fid'];
548  $wrapper = substr($element['#id'], 0, -7) . '-ajax-wrapper';
549 
550  $saved_value_parents = $no_header_parents = $element['#parents'];
551  $no_header_parents[] = '#value';
552  $no_header_parents[] = 'no-header';
553 
554  $no_header = drupal_array_get_nested_value($form_state['complete form'], $no_header_parents);
555  $callback = isset($form_state['triggering_element']['#ajax']['callback']) ? $form_state['triggering_element']['#ajax']['callback'] : NULL;
556  if (!$no_header and ($callback != 'tpps_no_header_callback')) {
557  $end = array_pop($saved_value_parents);
558  $saved_value_parents[] = $end . "-no-header";
559  $no_header = drupal_array_get_nested_value($form_state['saved_values'][$form_state['stage']], $saved_value_parents);
560  }
561 
562  $element['no-header'] = array(
563  '#type' => 'checkbox',
564  '#title' => 'My file has no header row',
565  '#ajax' => array(
566  'wrapper' => $wrapper,
567  'callback' => 'tpps_no_header_callback',
568  ),
569  '#states' => isset($element['#states']) ? $element['#states'] : NULL,
570  '#default_value' => $no_header ? $no_header : NULL,
571  );
572 
573  if (!empty($fid) and ($file = file_load($fid))) {
574 
575  $saved_vals = $form_state['saved_values'][$form_state['stage']];
576  $element['columns']['#type'] = 'fieldset';
577  $element['columns']['#title'] = t('<div class="fieldset-title" style="font-size:.8em">Define Data</div>');
578  $element['columns']['#collapsible'] = TRUE;
579 
580  // Stop using the file so it can be deleted if the user clicks 'remove'.
581  file_usage_delete($file, 'tpps', 'tpps_project', substr($form_state['accession'], 4));
582  $content = tpps_parse_file($fid, 3, !empty($no_header));
583 
584  $options = $element['columns-options']['#value'];
585 
586  $first = TRUE;
587 
588  foreach ($content['headers'] as $key => $item) {
589  $item_parents = $element['#parents'];
590  array_pop($item_parents);
591  $item_parents[] = end($element['#parents']) . '-columns';
592  $item_parents[] = $key;
593 
594  $default = drupal_array_get_nested_value($saved_vals, $item_parents);
595 
596  if (!isset($default)) {
597  foreach ($options as $k => $val) {
598  similar_text(strtolower($val), strtolower($item), $percent);
599  if ($percent > 85) {
600  $default = $k;
601  break;
602  }
603  }
604  }
605  // dpm($item_parents);
606  $element['columns'][$key] = array(
607  '#type' => 'select',
608  '#title' => $item,
609  '#options' => $options,
610  '#default_value' => $default,
611  '#prefix' => "<th>",
612  '#suffix' => "</th>",
613  '#attributes' => array(
614  'data-toggle' => array('tooltip'),
615  'data-placement' => array('top'),
616  'title' => array("Select the type of data the '$item' column holds"),
617  ),
618  );
619 
620  if ($first) {
621  $first = FALSE;
622  $first_col = $key;
623  }
624 
625  if (!empty($no_header)) {
626  $element['columns'][$key]['#title'] = '';
627  $element['columns'][$key]['#attributes']['title'] = array("Select the type of data column $item holds");
628  }
629 
630  if ($form_state['stage'] == TPPS_PAGE_3) {
631  $species_num = $element['#parents'];
632  array_pop($species_num);
633  $species_num = "-" . end($species_num);
634  $element['columns'][$key]['#ajax'] = array(
635  'callback' => 'tpps_accession_pop_group',
636  'wrapper' => "population-mapping$species_num",
637  );
638  }
639  }
640 
641  $rows = $content;
642  unset($rows['headers']);
643  $vars = array(
644  'header' => $content['headers'],
645  'rows' => $rows,
646  'attributes' => array('class' => array('view')),
647  'caption' => '',
648  'colgroups' => NULL,
649  'sticky' => FALSE,
650  'empty' => '',
651  );
652  $table = theme('table', $vars);
653  preg_match('/(*UTF8)\A(.*<thead[A-Z|a-z|"|\'|-|_|0-9]*>).*(<\/thead>.*<\/table>)/us', $table, $matches);
654 
655  $element['columns'][$first_col]['#prefix'] = "<div style=\"overflow-x:auto\">" . $matches[1] . "<tr>" . $element['columns'][$first_col]['#prefix'];
656  $element['columns'][$key]['#suffix'] = "</tr>" . $matches[2] . "</div>";
657  $warning = "Please note that if you remain idle on a TPPS page with files for more than 6 hours, you run the risk of having those files reset if you do not click \"Save\".";
658  $element['columns'][$key]['#suffix'] = $element['columns'][$key]['#suffix'] . $warning;
659  }
660  }
661 
662  if (isset($element['empty'])) {
663 
664  $element['empty']['#type'] = 'textfield';
665  $element['empty']['#title'] = t('File Upload empty field:');
666  $element['empty']['#states'] = isset($element['#states']) ? $element['#states'] : NULL;
667  $element['empty']['#description'] = t('By default, TPPS will treat cells with the value "NA" as empty. If you used a different empty value indicator, please provide it here.');
668  }
669 
670  return $element;
671 }
672 
679 function tpps_form_alter(&$form, &$form_state, $form_id) {
680  if ($form['#form_id'] == 'tpps_main') {
681  $stage = $form_state['stage'];
682 
683  if (!isset($form_state['saved_values'][$stage])) {
684  $form_state['saved_values'][$stage] = array();
685  }
686  if (!isset($form_state['values'])) {
687  $form_state['values'] = array();
688  }
689 
690  tpps_leaves($form, $form_state['values'], $form_state['saved_values'][$stage]);
691  }
692 }
693 
704 function tpps_leaves(array &$elements, array $vals, array $saved_vals) {
705  foreach ($elements as $key => &$element) {
706  if ((gettype($key) != 'string' or $key[0] != '#') and isset($element['#type'])) {
707 
708  // If #tree is not set in the current element, and #tree is set and false
709  // in the parent element, then set #tree to false in the current element.
710  if (!isset($element['#tree']) and isset($elements['#tree']) and !$elements['#tree']) {
711  $element['#tree'] = FALSE;
712  }
713 
714  // If #tree is not set or is set to true, then populate the #parents array
715  // with the parents of the parent element plus the current key. Otherwise,
716  // the #parents array should just be the current key.
717  if (!isset($element['#tree']) or $element['#tree']) {
718  $element['#parents'] = array_merge($elements['#parents'], array($key));
719  }
720  else {
721  $element['#parents'] = array($key);
722  }
723 
724  // Element types that should be loading some default value, usually for
725  // the purposes of persistent form data.
726  $load_defaults = array(
727  'textfield',
728  'textarea',
729  'checkbox',
730  'select',
731  'managed_file',
732  );
733  // If element is a type that should pull from 'saved_values', try to load
734  // the old value.
735  if (in_array($element['#type'], $load_defaults) and !isset($element['#default_value']) and isset($saved_vals[$key])) {
736  $element['#default_value'] = $saved_vals[$key];
737  }
738  // If element is a select type and still has no default value, then there
739  // is no saved value, so the default should be 0.
740  elseif ($element['#type'] == 'select' and !isset($element['#default_value'])) {
741  $element['#default_value'] = 0;
742  }
743 
744  // Checkboxes elements work differently in terms of default values.
745  if ($element['#type'] == 'checkboxes') {
746  $options = $element['#options'];
747  // Get checkboxes options.
748  foreach ($options as $option) {
749  // If the option does not have a default, pull from 'saved_values'.
750  if (!isset($element[$option]['#default_value']) and isset($saved_vals[$key][$option])) {
751  $element[$option]['#default_value'] = $saved_vals[$key][$option];
752  }
753  }
754  }
755 
756  if ($element['#type'] == 'fieldset') {
757  if (empty($saved_vals[$key]) or !is_array($saved_vals[$key])) {
758  $saved_vals[$key] = array();
759  }
760  if (empty($vals[$key]) or !is_array($vals[$key])) {
761  $vals[$key] = array();
762  }
763  tpps_leaves($element, $vals[$key], $saved_vals[$key]);
764  }
765  }
766  }
767 }
768 
774 function tpps_page_build(&$page) {
775  $js_settings = drupal_static('drupal_add_js', array())['settings']['data'] ?? array();
776  $step = NULL;
777  foreach ($js_settings as $info) {
778  if (array_key_exists('tpps', $info)) {
779  $step = $info['tpps']['stage'] ?? NULL;
780  if (!empty($step)) {
781  break;
782  }
783  }
784  }
785 
786  if (empty($page['content']['system_main']['#form_id']) or $page['content']['system_main']['#form_id'] != 'tpps_main' or empty($step)) {
787  return $page;
788  }
789 
790  if ($step != 'frontpage' and $step != TPPS_PAGE_1 and $step != 'summarypage') {
791  $blockObject = block_load('views', 'tpps_status');
792  $blockObject->title = 'TPPS Status';
793  $blockObject->subject = '';
794  $blockObject->region = 'Content';
795  $block = _block_get_renderable_array(_block_render_blocks(array($blockObject)));
796  $tpps_status = "<div class='block block-system contextual-links-region block-menu tpps-status-block'>{$block['views_tpps_status']['#markup']}</div>";
797  drupal_add_region_content('sidebar_second', $tpps_status);
798  }
799 
800  return $page;
801 }
802 
821 function tpps_main(array $form, array &$form_state, $accession = NULL) {
822 
823  require_once 'forms/build/front.php';
824  global $user;
825 
826  if (!isset($form_state['stage'])) {
827  if (!isset($accession)) {
828  // First access, no accession in link.
829  $form_state['stage'] = 'frontpage';
830 
831  tpps_front_create_form($form, $form_state);
832 
833  drupal_add_js(drupal_get_path('module', 'tpps') . TPPS_JS_PATH);
834  drupal_add_css(drupal_get_path('module', 'tpps') . TPPS_CSS_PATH);
835 
836  return $form;
837  }
838  else {
839  // First access, and with accession in link.
840  $old_form_state = tpps_load_submission($accession);
841  if (empty($old_form_state)) {
842  drupal_goto('tpps');
843  }
844  tpps_form_state_info($form_state, $old_form_state);
845  }
846  }
847  else {
848  // Not first access.
849  if (!isset($form_state['saved_values']['frontpage']['accession']) or (isset($form_state['saved_values']['frontpage']['accession']) and $form_state['saved_values']['frontpage']['accession'] === 'new')) {
850  // No submissions, or selected to create new submission.
851  if (tpps_access('administer tpps module') and !empty($form_state['saved_values']['frontpage']['custom_accession_check'])) {
852  $accession = $form_state['saved_values']['frontpage']['custom_accession'];
853  }
854  tpps_init_project($form_state, $accession);
855  tpps_create_submission($form_state, $user->uid);
856  }
857  $old_form_state = tpps_load_submission($form_state['saved_values']['frontpage']['accession']);
858  tpps_form_state_info($form_state, $old_form_state);
859  }
860 
861  drupal_add_js(array('tpps' => array('stage' => $form_state['stage'])), 'setting');
862 
863  $form['accession'] = array(
864  '#type' => 'hidden',
865  '#value' => $form_state['accession'],
866  );
867 
868  if (!isset($form_state['dbxref_id']) or !isset($form_state['accession'])) {
869  tpps_init_project($form_state);
870  }
871 
872  tpps_status_bar($form, $form_state);
873 
874 
875  if ((!isset($form_state['tpps_type']) or $form_state['tpps_type'] != 'tppsc') and (!isset($form_state['saved_values'][TPPS_PAGE_1]['primaryAuthor']) or !isset($form_state['saved_values'][TPPS_PAGE_1]['organization']))) {
876 
877  $contact_bundle = tripal_load_bundle_entity(array('label' => 'Tripal Contact Profile'));
878  if ($contact_bundle) {
879  $query = new EntityFieldQuery();
880  $results = $query->entityCondition('entity_type', 'TripalEntity')
881  ->entityCondition('bundle', $contact_bundle->name)
882  ->fieldCondition('local__email', 'value', $user->mail)
883  ->range(0, 1)
884  ->execute();
885  $entity = current(array_reverse(entity_load('TripalEntity', array_keys($results['TripalEntity']))));
886  $form_state['saved_values'][TPPS_PAGE_1]['primaryAuthor'] = $form_state['saved_values'][TPPS_PAGE_1]['primaryAuthor'] ?? $entity->title;
887  $form_state['saved_values'][TPPS_PAGE_1]['organization'] = $form_state['saved_values'][TPPS_PAGE_1]['organization'] ?? $entity->tcontact__organization[LANGUAGE_NONE][0]['value'];
888  }
889  }
890 
891  switch ($form_state['stage']) {
892  case TPPS_PAGE_1:
893  require_once 'forms/build/page_1.php';
894  tpps_page_1_create_form($form, $form_state);
895  break;
896 
897  case TPPS_PAGE_2:
898  require_once 'forms/build/page_2.php';
899  tpps_page_2_create_form($form, $form_state);
900  break;
901 
902  case TPPS_PAGE_3:
903  require_once 'forms/build/page_3.php';
904  tpps_page_3_create_form($form, $form_state);
905  break;
906 
907  case TPPS_PAGE_4:
908  require_once 'forms/build/page_4.php';
909  tpps_page_4_create_form($form, $form_state);
910  break;
911 
912  case 'summarypage':
913  require_once 'forms/build/summary.php';
914  tpps_summary_create_form($form, $form_state);
915  break;
916 
917  default:
918  drupal_set_message(t('Invalid form stage.'), 'error');
919  break;
920  }
921 
922  $suffix = '
923  <script>
924  jQuery(document).ready(function(){
925  jQuery(\'[data-toggle="tooltip"]\').tooltip();
926  });
927  </script>';
928 
929  if (isset($form['#suffix'])) {
930  $form['#suffix'] .= $suffix;
931  }
932  else {
933  $form['#suffix'] = $suffix;
934  }
935 
936  drupal_add_js(drupal_get_path('module', 'tpps') . TPPS_JS_PATH);
937  drupal_add_css(drupal_get_path('module', 'tpps') . TPPS_CSS_PATH);
938 
939  return $form;
940 }
941 
948 function tpps_main_validate(&$form, &$form_state) {
949  global $user;
950 
951  if ($form_state['triggering_element']['#value'] == 'Back' or $form_state['triggering_element']['#value'] == 'Save') {
952 
953  tpps_save_file_columns($form, $form_state);
954  return;
955  }
956 
957  switch ($form_state['stage']) {
958  case 'frontpage':
959  require_once 'forms/validate/front.php';
960  tpps_front_page_validate_form($form, $form_state);
961  break;
962 
963  case TPPS_PAGE_1:
964  require_once 'forms/validate/page_1.php';
965  tpps_page_1_validate_form($form, $form_state);
966  break;
967 
968  case TPPS_PAGE_2:
969  require_once 'forms/validate/page_2.php';
970  tpps_page_2_validate_form($form, $form_state);
971  break;
972 
973  case TPPS_PAGE_3:
974  require_once 'forms/validate/page_3.php';
975  tpps_page_3_validate_form($form, $form_state);
976  break;
977 
978  case TPPS_PAGE_4:
979  require_once 'forms/validate/page_4.php';
980  tpps_page_4_validate_form($form, $form_state);
981  break;
982 
983  default:
984  break;
985  }
986 
987  drupal_add_js(drupal_get_path('module', 'tpps') . TPPS_JS_PATH);
988 
989  if ($user->uid !== 0 and !form_get_errors()) {
990  $form_state['values']['#cleared'] = TRUE;
991  if ($form_state['submitted'] == '1') {
992  tpps_submission_update_stats($form_state);
993  }
994  }
995  else {
996  $form_state['values']['#cleared'] = FALSE;
997  }
998 }
999 
1006 function tpps_main_submit($form, &$form_state) {
1007 
1008  $form_state['saved_values'][$form_state['stage']] = $form_state['values'];
1009  $persist = TRUE;
1010 
1011  if ($form_state['triggering_element']['#value'] == 'Save') {
1012  drupal_set_message(t('Your information has been saved!'), 'status');
1013 
1014  if (isset($form_state['saved_values']['form_build_id'])) {
1015  $form_state['values']['form_build_id'] = $form_state['saved_values']['form_build_id'];
1016  }
1017  $form_state['saved_values']['form_build_id'] = $form_state['values']['form_build_id'];
1018  $form_state['rebuild'] = TRUE;
1019 
1020  tpps_update_submission($form_state);
1021  return;
1022  }
1023 
1024  switch ($form_state['stage']) {
1025  case 'frontpage':
1026  $persist = FALSE;
1027  $form_state['stage'] = TPPS_PAGE_1;
1028  break;
1029 
1030  case TPPS_PAGE_1:
1031  $form_state['stage'] = TPPS_PAGE_2;
1032  break;
1033 
1034  case TPPS_PAGE_2:
1035  if ($form_state['triggering_element']['#value'] == 'Back') {
1036  $form_state['stage'] = TPPS_PAGE_1;
1037  }
1038  else {
1039  $form_state['stage'] = TPPS_PAGE_3;
1040  }
1041  break;
1042 
1043  case TPPS_PAGE_3:
1044  if ($form_state['triggering_element']['#value'] == 'Back') {
1045  $form_state['stage'] = TPPS_PAGE_2;
1046  }
1047  else {
1048  $form_state['stage'] = TPPS_PAGE_4;
1049  }
1050  break;
1051 
1052  case TPPS_PAGE_4:
1053  if ($form_state['triggering_element']['#value'] == 'Back') {
1054  $form_state['stage'] = TPPS_PAGE_3;
1055  }
1056  else {
1057  $form_state['stage'] = 'summarypage';
1058  }
1059  break;
1060 
1061  case 'summarypage':
1062  if ($form_state['triggering_element']['#value'] == 'Back') {
1063  $form_state['stage'] = TPPS_PAGE_4;
1064  }
1065  else {
1066  $form_state['status'] = 'Pending Approval';
1067  $form_state['completed'] = time();
1068  tpps_update_submission($form_state);
1069  tpps_submit_email($form_state);
1070  drupal_goto("completed-submission/{$form_state['accession']}");
1071  return;
1072  }
1073  break;
1074 
1075  default:
1076  drupal_set_message(t('Invalid form stage.'), 'error');
1077  break;
1078  }
1079 
1080  if (isset($form_state['saved_values']['form_build_id'])) {
1081  $form_state['values']['form_build_id'] = $form_state['saved_values']['form_build_id'];
1082  }
1083  $form_state['saved_values']['form_build_id'] = $form_state['values']['form_build_id'];
1084  $form_state['rebuild'] = TRUE;
1085 
1086  if ($persist) {
1087  tpps_update_submission($form_state);
1088  }
1089 }
1090 
1096 function tpps_block_info() {
1097  // dpm("BLOCK INFO");.
1098  $blocks['tpps_status'] = array(
1099  // info: The name of the block.
1100  'info' => t('TPPS Status'),
1101  );
1102 
1103  return $blocks;
1104 }
1105 
1112 function tpps_block_view_alter(&$data, $block) {
1113  global $base_url;
1114  switch ($block->delta) {
1115  case 'tpps_status':
1116  $css = "
1117  .tgdr_status_block img {
1118  vertical-align: middle;
1119  margin-bottom: 4px;
1120  margin-right: 2px;
1121  }
1122  ";
1123  drupal_add_css($css, 'inline');
1124 
1125  $data['subject'] = t('TPPS Status');
1126  $content = "<div class='tgdr_status_block'>";
1127  $params = drupal_get_query_parameters(NULL, array());
1128  if (preg_match('/tppsc?\/(TGDR.*)/', $params['q'], $matches)) {
1129  $accession = $matches[1];
1130  $form_state = tpps_load_submission($accession);
1131  }
1132  elseif (isset($_REQUEST['accession'])) {
1133  $accession = $_REQUEST['accession'];
1134  $form_state = tpps_load_submission($accession);
1135  }
1136  else {
1137  $content .= '</div>';
1138  $data['content'] = filter_xss($content);
1139  break;
1140  }
1141  $ok = "<img src='$base_url/misc/message-16-ok.png'>";
1142  $form_state['saved_values'][TPPS_PAGE_2]['study_info'] = NULL;
1143  $flat = tpps_flatten($form_state);
1144 
1145  $map_api_key = variable_get('tpps_maps_api_key', NULL);
1146  foreach ($flat as $item => $val) {
1147  if ($item[0] !== '#') {
1148  $item_str = filter_xss(check_plain($item));
1149  $val_str = filter_xss(check_plain($val));
1150  if (preg_match('/(Abstract|Organization)/', $item)) {
1151  continue;
1152  }
1153  elseif (preg_match('/File/', $item) and ($file_name = file_load($val)->filename)) {
1154  // Create links to files.
1155  $file_url = check_plain(file_create_url(file_load($val)->uri));
1156  $val_str = "<a href='$file_url' target='blank'>$file_name</a>";
1157  if (!$flat['#skip_loc'] and preg_match('/^(.*)Accession File/', $item, $matches)) {
1158  $fid = $val;
1159  $wrapper_id = "{$fid}_map_wrapper";
1160  $button_id = "{$fid}_map_button";
1161  $val_str .= "<div id=\"$wrapper_id\"></div>"
1162  . "<input id=\"$button_id\" type=\"button\" value=\"Click here to view plants on map!\"></input>";
1163 
1164  drupal_add_js(array(
1165  'tpps' => array(
1166  'map_buttons' => array(
1167  $fid => array(
1168  'wrapper' => $wrapper_id,
1169  'button' => $button_id,
1170  'fid' => $fid,
1171  ),
1172  ),
1173  ),
1174  ), 'setting');
1175  }
1176  }
1177  elseif (preg_match('/species photo/', $item) and (file_load($val)) and ($file_name = file_load($val)->filename)) {
1178  $file_url = check_plain(file_create_url(file_load($val)->uri));
1179  $val_str = "<img src='$file_url' width='100%'>";
1180  $val_str .= "<br><a href='$file_url' target='blank'>$file_name</a>";
1181  }
1182  elseif (preg_match('/Month/', $item)) {
1183  // Skip experiment start/end month.
1184  continue;
1185  }
1186  elseif (preg_match('/^(.*)Year/', $item, $matches)) {
1187  // Combine experiment start/end month + year.
1188  if (isset($flat[$matches[1] . 'Month'])) {
1189  $item_str = $matches[1] . 'Date';
1190  $val_str = "{$flat[$matches[1] . 'Month']} $val_str";
1191  }
1192  else {
1193  continue;
1194  }
1195  }
1196  elseif (preg_match('/Study Location/', $item) and isset($flat['#location_type']) and $flat['#location_type']) {
1197  // Add map capability to location.
1198  if ($flat['#location_type'] == '2') {
1199  $query = $val_str;
1200  }
1201  elseif ($flat['#location_type'] != '2' and ($standard = tpps_standard_coord($val_str))) {
1202  $query = $standard;
1203  }
1204  $val_str = "<a id=\"sidebar_map\" style=\"cursor:pointer\">$val_str</a>";
1205  if (isset($query) and !empty($map_api_key)) {
1206  $map = "<iframe frameborder=\\\"0\\\" style=\\\"border:0;width:100%;height:100%\\\" src=\\\"https://www.google.com/maps?q=$query&output=embed&key=$map_api_key&z=5\\\" allowfullscreen> </iframe></div>";
1207  $js = "jQuery(document).ready(function ($) {
1208  jQuery(\"#sidebar_map\").click(function() {
1209  jQuery(\"#sidebar_map_wrapper\").remove();
1210  jQuery(\"#sidebar_map\").after( \"<br><div id=\\\"sidebar_map_wrapper\\\">$map</div>\" );
1211  });
1212  });";
1213  drupal_add_js($js, 'inline');
1214  }
1215  }
1216  elseif (preg_match('/Publication DOI/', $item)) {
1217  $link = preg_match('/https?:\/\//', $val_str) ? $val_str : "https://doi.org/$val_str";
1218  $val_str = "<a href=\"$link\" target=\"blank\">$val_str</a>";
1219  }
1220  $content .= "$ok $item_str: $val_str <br>";
1221  }
1222  elseif (preg_match('/#page_(.)_cleared/', $item, $matches)) {
1223  // Break between pages.
1224  if ($val) {
1225  $step_arr = array(
1226  1 => 'Author and Species Information',
1227  2 => 'Experimental Conditions',
1228  3 => 'Plant Accession',
1229  4 => 'Submit Data',
1230  );
1231  if ($matches[1] > 1) {
1232  $content .= '<br />';
1233  }
1234  $content .= "$ok Step {$matches[1]} - Complete<br />{$step_arr[$matches[1]]}<br /><hr />";
1235  }
1236  else {
1237  // If page not cleared, do not display remaining form state data.
1238  break;
1239  }
1240  }
1241  elseif (preg_match('/^#(.*)accession_(.*)/', $item, $matches)) {
1242  $val_str = filter_xss(check_plain($val));
1243  $parts = explode(" ", substr($matches[0], 1));
1244  $item_id = implode("_", $parts);
1245  $content .= "<div id=\"$item_id\" style=\"display:none;\">$val_str</div>";
1246  }
1247  }
1248  if (!empty($flat['#page_3_cleared']) and !empty($map_api_key)) {
1249  $content .= "<script src=\"https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/markerclusterer.js\"></script><script src=\"https://maps.googleapis.com/maps/api/js?key=$map_api_key&callback=initMap\"
1250  async defer></script>";
1251  }
1252  $content .= "</div>";
1253  $data['content'] = $content;
1254 
1255  break;
1256 
1257  default:
1258  break;
1259  }
1260 }
1261 
1265 function tpps_snpassay_file_selector($string) {
1266  $matches = array();
1267  $result = db_select('file_managed', 'f')
1268  ->fields('f', array('fid', 'filename'))
1269  ->condition('f.filename', '%' . db_like($string) . '%', 'LIKE')
1270  ->condition('f.filename', '%SNP%', 'LIKE')
1271  ->orderBy('f.timestamp', 'DESC')
1272  ->execute();
1273 
1274  // save the query to matches
1275  foreach ($result as $row) {
1276  $value = $row->filename . ' (' . $row->fid . ')';
1277  $matches[$row->fid] = $row->filename;
1278  }
1279 
1280  // Return the result to the form in json
1281  drupal_json_output($matches);
1282 }
1283 
1285  //if (variable_get('disable_media_upload', 0)) {
1286  unset($plugins['upload']);
1287  unset($plugins['media_default--media_browser_my_files']);
1288  // }
1289  }
tpps_standard_coord($raw_coordinate)
const TPPS_PAGE_1
Definition: tpps.module:12
tpps_api_paths()
Definition: tpps.api.inc:33
tpps_element_info_alter(&$type)
Definition: tpps.module:518
tpps_page_2_validate_form(array &$form, array &$form_state)
Definition: page_2.php:16
tpps_update_submission(array $state, array $options=array())
tpps_media_browser_plugins_alter(&$plugins)
Definition: tpps.module:1284
tpps_create_submission(array $state, $uid)
tpps_main_submit($form, &$form_state)
Definition: tpps.module:1006
tpps_flatten(array $state)
Definition: display.inc:20
tpps_page_4_validate_form(array &$form, array &$form_state)
Definition: page_4.php:16
tpps_main_validate(&$form, &$form_state)
Definition: tpps.module:948
tpps_page_3_create_form(array &$form, array &$form_state)
Definition: page_3.php:24
const TPPS_CSS_PATH
Definition: tpps.module:11
tpps_front_page_validate_form(array &$form, array &$form_state)
Definition: front.php:16
tpps_block_info()
Definition: tpps.module:1096
const TPPS_JS_PATH
Definition: tpps.module:10
tpps_front_create_form(array &$form, array $form_state)
Definition: front.php:27
tpps_main(array $form, array &$form_state, $accession=NULL)
Definition: tpps.module:821
tpps_mail($key, array &$message, array $params)
Definition: tpps.module:451
tpps_access()
Definition: tpps.module:341
tpps_menu()
Definition: tpps.module:40
tpps_summary_create_form(array &$form, array $form_state)
Definition: summary.php:23
tpps_page_1_create_form(array &$form, array &$form_state)
Definition: page_1.php:25
tpps_form_state_info(array &$new, array &$old)
Definition: form_utils.inc:290
tpps_cronapi()
Definition: tpps.module:416
tpps_managed_file_process(array $element, array &$form_state, array $form)
Definition: tpps.module:541
tpps_status_bar(array &$form, array $form_state)
Definition: status_bar.inc:22
tpps_save_file_columns(array &$form, array &$form_state)
Definition: file_utils.inc:533
tpps_page_1_validate_form(array &$form, array &$form_state)
Definition: page_1.php:16
tpps_load_submission($accession, $state=TRUE)
Definition: submissions.inc:27
tpps_form_alter(&$form, &$form_state, $form_id)
Definition: tpps.module:679
tpps_submission_update_stats(array &$form_state)
tpps_snpassay_file_selector($string)
Definition: tpps.module:1265
tpps_page_build(&$page)
Definition: tpps.module:774
tpps_permission()
Definition: tpps.module:291
tpps_page_3_validate_form(array &$form, array &$form_state)
Definition: page_3.php:16
const TPPS_PAGE_4
Definition: tpps.module:15
tpps_leaves(array &$elements, array $vals, array $saved_vals)
Definition: tpps.module:704
tpps_page_4_create_form(array &$form, array &$form_state)
Definition: page_4.php:23
tpps_block_view_alter(&$data, $block)
Definition: tpps.module:1112
tpps_submit_email(array &$form_state)
tpps_init_project(array &$form_state, $accession=NULL)
const TPPS_PAGE_3
Definition: tpps.module:14
const TPPS_PAGE_2
Definition: tpps.module:13
tpps_page_2_create_form(array &$form, array $form_state)
Definition: page_2.php:25
tpps_parse_file($fid, $max_rows=0, $no_header=FALSE, $columns=NULL)
Definition: file_utils.inc:25