Fixes for restoreSession logic. (#4378)
[openemr.git] / library / options.inc.php
blob8e8521cad5592a8e025a0b7072aea7f62eceac25
1 <?php
3 // Copyright (C) 2007-2021 Rod Roark <rod@sunsetsystems.com>
4 // Copyright © 2010 by Andrew Moore <amoore@cpan.org>
5 // Copyright © 2010 by "Boyd Stephen Smith Jr." <bss@iguanasuicide.net>
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // Functions for managing the lists and layouts
14 // Note: there are translation wrappers for the lists and layout labels
15 // at library/translation.inc.php. The functions are titled
16 // xl_list_label() and xl_layout_label() and are controlled by the
17 // $GLOBALS['translate_lists'] and $GLOBALS['translate_layout']
18 // flags in globals.php
20 // Documentation for layout_options.edit_options:
22 // A = Age as years or "xx month(s)"
23 // B = Gestational age as "xx week(s) y day(s)"
24 // C = Capitalize first letter of each word (text fields)
25 // D = Check for duplicates in New Patient form
26 // G = Graphable (for numeric fields in forms supporting historical data)
27 // H = Read-only field copied from static history (this is obsolete)
28 // J = Jump to Next Row
29 // K = Prepend Blank Row
30 // L = Lab Order ("ord_lab") types only (address book)
31 // M = Radio Group Master (currently for radio buttons only)
32 // m = Radio Group Member (currently for radio buttons only)
33 // N = Show in New Patient form
34 // O = Procedure Order ("ord_*") types only (address book)
35 // P = Default to previous value when current value is not yet set
36 // R = Distributor types only (address book)
37 // T = Use description as default Text
38 // U = Capitalize all letters (text fields)
39 // V = Vendor types only (address book)
40 // 0 = Read Only - the input element's "disabled" property is set
41 // 1 = Write Once (not editable when not empty) (text fields)
42 // 2 = Show descriptions instead of codes for billing code input
44 require_once("user.inc");
45 require_once("patient.inc");
46 require_once("lists.inc");
47 require_once(dirname(dirname(__FILE__)) . "/custom/code_types.inc.php");
49 use OpenEMR\Common\Acl\AclExtended;
50 use OpenEMR\Common\Acl\AclMain;
51 use OpenEMR\Services\FacilityService;
53 $facilityService = new FacilityService();
55 $date_init = "";
56 $membership_group_number = 0;
58 function get_pharmacies()
60 return sqlStatement("SELECT d.id, d.name, a.line1, a.city, " .
61 "p.area_code, p.prefix, p.number FROM pharmacies AS d " .
62 "LEFT OUTER JOIN addresses AS a ON a.foreign_id = d.id " .
63 "LEFT OUTER JOIN phone_numbers AS p ON p.foreign_id = d.id " .
64 "AND p.type = 2 " .
65 "ORDER BY a.state, a.city, d.name, p.area_code, p.prefix, p.number");
68 function optionalAge($frow, $date, &$asof, $description = '')
70 $asof = '';
71 if (empty($date)) {
72 return '';
75 $edit_options = $frow['edit_options'] ?? null;
77 $date = substr($date, 0, 10);
78 if (isOption($edit_options, 'A') !== false) {
79 $format = 0;
80 } elseif (isOption($edit_options, 'B') !== false) {
81 $format = 3;
82 } else {
83 return '';
86 if (isOption($frow['form_id'], 'LBF') === 0) {
87 $tmp = sqlQuery(
88 "SELECT date FROM form_encounter WHERE " .
89 "pid = ? AND encounter = ? ORDER BY id DESC LIMIT 1",
90 array($GLOBALS['pid'], $GLOBALS['encounter'])
92 if (!empty($tmp['date'])) {
93 $asof = substr($tmp['date'], 0, 10);
96 if ($description === '') {
97 $prefix = ($format ? xl('Gest age') : xl('Age')) . ' ';
98 } else {
99 $prefix = $description . ' ';
101 return $prefix . oeFormatAge($date, $asof, $format);
104 // Function to generate a drop-list.
106 function generate_select_list(
107 $tag_name,
108 $list_id,
109 $currvalue,
110 $title,
111 $empty_name = ' ',
112 $class = '',
113 $onchange = '',
114 $tag_id = '',
115 $custom_attributes = null,
116 $multiple = false, // new #10
117 $backup_list = '', // new #11
118 $ignore_default = false,
119 $include_inactive = false
121 $s = '';
123 $tag_name_esc = attr($tag_name);
125 if ($multiple) {
126 $tag_name_esc = $tag_name_esc . "[]";
129 $s .= "<select name='$tag_name_esc'";
131 if ($multiple) {
132 $s .= " multiple='multiple'";
135 $tag_id_esc = attr($tag_name);
137 if ($tag_id != '') {
138 $tag_id_esc = attr($tag_id);
141 $s .= " id='$tag_id_esc'";
143 if (!empty($class)) {
144 $class_esc = attr($class);
145 $s .= " class='form-control $class_esc'";
146 } else {
147 $s .= " class='form-control'";
150 if ($onchange) {
151 $s .= " onchange='$onchange'";
154 if ($custom_attributes != null && is_array($custom_attributes)) {
155 foreach ($custom_attributes as $attr => $val) {
156 if (isset($custom_attributes [$attr])) {
157 $s .= " " . attr($attr) . "='" . attr($val) . "'";
162 $selectTitle = attr($title);
163 $s .= " title='$selectTitle'>";
164 $selectEmptyName = xlt($empty_name);
165 if ($empty_name) {
166 $s .= "<option value=''>" . $selectEmptyName . "</option>";
169 $got_selected = false;
171 for ($active = 1; $active == 1 || ($active == 0 && $include_inactive); --$active) {
172 if ($include_inactive) {
173 $s .= "<optgroup label='" . ($active ? xla('Active') : xla('Inactive')) . "'>\n";
176 // List order depends on language translation options.
177 // (Note we do not need to worry about the list order in the algorithm
178 // after the below code block since that is where searches for exceptions
179 // are done which include inactive items or items from a backup
180 // list; note these will always be shown at the bottom of the list no matter the
181 // chosen order.)
182 $lang_id = empty($_SESSION['language_choice']) ? '1' : $_SESSION['language_choice'];
183 // sort by title
184 if (!$GLOBALS['translate_lists']) {
185 // do not translate
186 if ($GLOBALS['gb_how_sort_list'] == '0') {
187 // order by seq
188 $order_by_sql = "seq, title";
189 } else { //$GLOBALS['gb_how_sort_list'] == '1'
190 // order by title
191 $order_by_sql = "title, seq";
193 $lres = sqlStatement(
194 "SELECT * FROM list_options WHERE list_id = ? AND activity = ? ORDER BY "
195 . $order_by_sql,
196 array($list_id, $active)
198 } else {
199 // do translate
200 if ($GLOBALS['gb_how_sort_list'] == '0') {
201 // order by seq
202 $order_by_sql = "lo.seq, IF(LENGTH(ld.definition),ld.definition,lo.title)";
203 } else { //$GLOBALS['gb_how_sort_list'] == '1'
204 // order by title
205 $order_by_sql = "IF(LENGTH(ld.definition),ld.definition,lo.title), lo.seq";
207 $lres = sqlStatement(
208 "SELECT lo.option_id, lo.is_default, " .
209 "IF(LENGTH(ld.definition),ld.definition,lo.title) AS title " .
210 "FROM list_options AS lo " .
211 "LEFT JOIN lang_constants AS lc ON lc.constant_name = lo.title " .
212 "LEFT JOIN lang_definitions AS ld ON ld.cons_id = lc.cons_id AND " .
213 "ld.lang_id = ? " .
214 "WHERE lo.list_id = ? AND lo.activity = ? " .
215 "ORDER BY " . $order_by_sql,
216 array($lang_id, $list_id, $active)
220 while ($lrow = sqlFetchArray($lres)) {
221 $selectedValues = explode("|", $currvalue);
223 $optionValue = attr($lrow ['option_id']);
224 $s .= "<option value='$optionValue'";
226 if (
227 (strlen($currvalue) == 0 && $lrow ['is_default'] && !$ignore_default) ||
228 (strlen($currvalue) > 0 && in_array($lrow ['option_id'], $selectedValues))
230 $s .= " selected";
231 $got_selected = true;
234 // Already has been translated above (if applicable), so do not need to use
235 // the xl_list_label() function here
236 $optionLabel = text($lrow ['title']);
237 $s .= ">$optionLabel</option>\n";
240 if ($include_inactive) {
241 $s .= "</optgroup>\n";
243 } // end $active loop
246 To show the inactive item in the list if the value is saved to database
248 if (!$got_selected && strlen($currvalue) > 0) {
249 $lres_inactive = sqlStatement("SELECT * FROM list_options " .
250 "WHERE list_id = ? AND activity = 0 AND option_id = ? ORDER BY seq, title", array($list_id, $currvalue));
251 $lrow_inactive = sqlFetchArray($lres_inactive);
252 if ($lrow_inactive['option_id']) {
253 $optionValue = htmlspecialchars($lrow_inactive['option_id'], ENT_QUOTES);
254 $s .= "<option value='$optionValue' selected>" . htmlspecialchars(xl_list_label($lrow_inactive['title']), ENT_NOQUOTES) . "</option>\n";
255 $got_selected = true;
259 if (!$got_selected && strlen($currvalue) > 0 && !$multiple) {
260 $list_id = $backup_list;
261 $lrow = sqlQuery("SELECT title FROM list_options WHERE list_id = ? AND option_id = ?", array($list_id,$currvalue));
263 if ($lrow > 0 && !empty($backup_list)) {
264 $selected = text(xl_list_label($lrow ['title']));
265 $s .= "<option value='$currescaped' selected> $selected </option>";
266 $s .= "</select>";
267 } else {
268 $s .= "<option value='$currescaped' selected>* $currescaped *</option>";
269 $s .= "</select>";
270 $fontTitle = xlt('Please choose a valid selection from the list.');
271 $fontText = xlt('Fix this');
272 $s .= " <span class='text-danger' title='$fontTitle'>$fontText!</span>";
274 } elseif (!$got_selected && strlen($currvalue) > 0 && $multiple) {
275 //if not found in main list, display all selected values that exist in backup list
276 $list_id = $backup_list;
278 $got_selected_backup = false;
279 if (!empty($backup_list)) {
280 $lres_backup = sqlStatement("SELECT * FROM list_options WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
281 while ($lrow_backup = sqlFetchArray($lres_backup)) {
282 $selectedValues = explode("|", $currvalue);
284 $optionValue = attr($lrow_backup['option_id']);
286 if (in_array($lrow_backup ['option_id'], $selectedValues)) {
287 $s .= "<option value='$optionValue'";
288 $s .= " selected";
289 $optionLabel = text(xl_list_label($lrow_backup ['title']));
290 $s .= ">$optionLabel</option>\n";
291 $got_selected_backup = true;
296 if (!$got_selected_backup) {
297 $selectedValues = explode("|", $currvalue);
298 foreach ($selectedValues as $selectedValue) {
299 $s .= "<option value='" . attr($selectedValue) . "'";
300 $s .= " selected";
301 $s .= ">* " . text($selectedValue) . " *</option>\n";
304 $s .= "</select>";
305 $fontTitle = xlt('Please choose a valid selection from the list.');
306 $fontText = xlt('Fix this');
307 $s .= " <span class='text-danger' title='$fontTitle'>$fontText!</span>";
309 } else {
310 $s .= "</select>";
313 return $s;
316 // Parsing for data type 31, static text.
317 function parse_static_text($frow, $value_allowed = true)
319 $tmp = str_replace("\r\n", "\n", $frow['description']);
320 // Translate if it does not look like HTML.
321 if (substr($tmp, 0, 1) != '<') {
322 $tmp2 = $frow['description'];
323 $tmp3 = xl_layout_label($tmp);
324 if ($tmp3 == $tmp && $tmp2 != $tmp) {
325 // No translation, try again without the CRLF substitution.
326 $tmp3 = xl_layout_label($tmp2);
328 $tmp = nl2br($tmp3);
330 $s = '';
331 if ($frow['source'] == 'D' || $frow['source'] == 'H') {
332 // Source is demographics or history. This case supports value substitution.
333 while (preg_match('/^(.*?)\{(\w+)\}(.*)$/', $tmp, $matches)) {
334 $s .= $matches[1];
335 if ($value_allowed) {
336 $tmprow = $frow;
337 $tmprow['field_id'] = $matches[2];
338 $s .= lbf_current_value($tmprow, 0, 0);
340 $tmp = $matches[3];
343 $s .= $tmp;
344 return $s;
347 function genLabResultsTextItem($name, $value, $outtype, $size, $maxlength, $disabled = '')
349 $string_maxlength = $maxlength ? ("maxlength='" . attr($maxlength) . "'") : '';
350 $s = "<td align='center'>";
351 if ($outtype == 2) {
352 $s .= text($value);
353 } else {
354 $s .= "<input type='text'";
355 if ($outtype == 0) {
356 $s .= " name='" . attr($name) . "' id='" . attr($name) . "'";
358 $s .= " size='" . attr($size) . "' $string_maxlength" .
359 " value='" . attr($value) . "'" .
360 " $under $disabled />";
362 $s .= "&nbsp;</td>";
363 return $s;
366 // $outtype = 0 for form, 1 for print, 2 for display, 3 for plain text.
367 function genLabResults($frow, $currvalue, $outtype = 0, $disabled = '')
369 $field_id = $frow['field_id'];
370 $list_id = $frow['list_id'];
371 $field_id_esc = text($field_id);
372 $under = $outtype == 1 ? "class='under'" : "";
373 $s = '';
375 $avalue = json_decode($currvalue, true);
376 if (empty($avalue)) {
377 $avalue = array();
379 // $avalue[$option_id][0] : gestation
380 // $avalue[$option_id][1] : radio button value
381 // $avalue[$option_id][2] : test value
382 // $avalue[$option_id][3] : notes
384 $maxlength = $frow['max_length'];
385 $fldlength = empty($frow['fld_length']) ? 20 : $frow['fld_length'];
387 $under = $outtype == 1 ? "class='under'" : "";
389 $s .= "<table cellpadding='0' cellspacing='0'>";
390 if ($outtype < 2) {
391 $s .= "<tr>" .
392 "<td class='bold' align='center'>" . xlt('Test/Screening') . "&nbsp;</td>" .
393 "<td class='bold' align='center'>" . xlt('Gest wks') . "&nbsp;</td>" .
394 "<td class='bold' align='center'>&nbsp;" . xlt('N/A') . "&nbsp;</td>" .
395 "<td class='bold' align='center'>" . xlt('Neg/Nrml') . "</td>" .
396 "<td class='bold' align='center'>&nbsp;" . xlt('Pos/Abn') . "&nbsp;</td>" .
397 "<td class='bold' align='center'>" . xlt('Test Value') . "&nbsp;</td>" .
398 "<td class='bold' align='center'>" . xlt('Date/Notes') . "&nbsp;</td>" .
399 "</tr>";
402 $lres = sqlStatement(
403 "SELECT * FROM list_options WHERE " .
404 "list_id = ? AND activity = 1 ORDER BY seq, title",
405 array($list_id)
408 while ($lrow = sqlFetchArray($lres)) {
409 $option_id = $lrow['option_id'];
410 $option_id_esc = text($option_id);
412 if ($outtype >= 2 && empty($avalue[$option_id][1])) {
413 continue;
416 if ($outtype == 3) {
417 if (isset($avalue[$option_id][1]) && $avalue[$option_id][1] == '2') {
418 if ($s !== '') {
419 $s .= '; ';
421 $s .= text(xl_list_label($lrow['title']));
422 $s .= ':' . text($avalue[$option_id][0]);
423 $s .= ':' . text($avalue[$option_id][2]);
424 $s .= ':' . text($avalue[$option_id][3]);
426 continue;
429 $s .= "<tr>";
430 $s .= $outtype == 2 ? "<td class='bold'>" : "<td>";
431 $s .= text(xl_list_label($lrow['title'])) . "&nbsp;</td>";
433 $s .= genLabResultsTextItem(
434 "form_{$field_id_esc}[$option_id_esc][0]",
435 (isset($avalue[$option_id][0]) ? $avalue[$option_id][0] : ''),
436 $outtype,
439 $disabled,
440 $under
443 if ($outtype == 2) {
444 $tmp = isset($avalue[$option_id][1]) ? $avalue[$option_id][1] : '0';
445 $restype = ($tmp == '1') ? xl('Normal') : (($tmp == '2') ? xl('Abnormal') : xl('N/A'));
446 $s .= "<td>" . text($restype) . "&nbsp;</td>";
447 } else {
448 for ($i = 0; $i < 3; ++$i) {
449 $s .= "<td align='center'>";
450 $s .= "<input type='radio'";
451 if ($outtype == 0) {
452 $s .= " name='radio_{$field_id_esc}[$option_id_esc]'" .
453 " id='radio_{$field_id_esc}[$option_id_esc]'";
455 $s .= " value='$i' $lbfonchange";
456 if (isset($avalue[$option_id][1]) && $avalue[$option_id][1] == "$i") {
457 $s .= " checked";
459 $s .= " $disabled />";
460 $s .= "</td>";
463 $s .= genLabResultsTextItem(
464 "form_{$field_id_esc}[$option_id_esc][2]",
465 (isset($avalue[$option_id][2]) ? $avalue[$option_id][2] : ''),
466 $outtype,
469 $disabled,
470 $under
472 $s .= genLabResultsTextItem(
473 "form_{$field_id_esc}[$option_id_esc][3]",
474 (isset($avalue[$option_id][3]) ? $avalue[$option_id][3] : ''),
475 $outtype,
476 $fldlength,
477 $maxlength,
478 $disabled,
479 $under
481 $s .= "</tr>";
483 if ($outtype != 3) {
484 $s .= "</table>";
487 return $s;
490 // $frow is a row from the layout_options table.
491 // $currvalue is the current value, if any, of the associated item.
493 function generate_form_field($frow, $currvalue)
495 global $rootdir, $date_init, $ISSUE_TYPES, $code_types, $membership_group_number;
497 $currescaped = htmlspecialchars($currvalue, ENT_QUOTES);
499 $data_type = $frow['data_type'];
500 $field_id = $frow['field_id'];
501 $list_id = $frow['list_id'] ?? null;
502 $backup_list = $frow['list_backup_id'] ?? null;
503 $edit_options = $frow['edit_options'] ?? null;
504 $form_id = $frow['form_id'] ?? null;
506 // Get if we want a smaller form field
507 $smallform = $frow['smallform'] ?? null;
509 if ($smallform === 'true') {
510 $smallform = ' form-control-sm';
513 // escaped variables to use in html
514 $field_id_esc = htmlspecialchars($field_id, ENT_QUOTES);
515 $list_id_esc = htmlspecialchars($list_id, ENT_QUOTES);
517 // Added 5-09 by BM - Translate description if applicable
518 $description = (isset($frow['description']) ? htmlspecialchars(xl_layout_label($frow['description']), ENT_QUOTES) : '');
520 // Support edit option T which assigns the (possibly very long) description as
521 // the default value.
522 if (isOption($edit_options, 'T') !== false) {
523 if (strlen($currescaped) == 0) {
524 $currescaped = $description;
527 // Description used in this way is not suitable as a title.
528 $description = '';
531 // added 5-2009 by BM to allow modification of the 'empty' text title field.
532 // Can pass $frow['empty_title'] with this variable, otherwise
533 // will default to 'Unassigned'.
534 // modified 6-2009 by BM to allow complete skipping of the 'empty' text title
535 // if make $frow['empty_title'] equal to 'SKIP'
536 $showEmpty = true;
537 if (isset($frow['empty_title'])) {
538 if ($frow['empty_title'] == "SKIP") {
539 //do not display an 'empty' choice
540 $showEmpty = false;
541 $empty_title = "Unassigned";
542 } else {
543 $empty_title = $frow['empty_title'];
545 } else {
546 $empty_title = "Unassigned";
549 $disabled = isOption($edit_options, '0') === false ? '' : 'disabled';
551 $lbfchange = (
552 strpos($form_id, 'LBF') === 0 ||
553 strpos($form_id, 'LBT') === 0 ||
554 strpos($form_id, 'DEM') === 0 ||
555 strpos($form_id, 'HIS') === 0
556 ) ? "checkSkipConditions();" : "";
557 $lbfonchange = $lbfchange ? "onchange='$lbfchange'" : "";
559 // generic single-selection list or single-selection list with search or single-selection list with comment support.
560 // These data types support backup lists.
561 if ($data_type == 1 || $data_type == 43 || $data_type == 46) {
562 if ($data_type == 46) {
563 // support for single-selection list with comment support
564 $lbfchange = "processCommentField(" . attr_js($field_id) . ");" . $lbfchange;
567 echo generate_select_list(
568 "form_$field_id",
569 $list_id,
570 $currvalue,
571 $description,
572 ($showEmpty ? $empty_title : ''),
573 (($data_type == 43) ? "select-dropdown" : $smallform),
574 $lbfchange,
576 ($disabled ? array('disabled' => 'disabled') : null),
577 false,
578 $backup_list
581 if ($data_type == 46) {
582 // support for single-selection list with comment support
583 $selectedValues = explode("|", $currvalue);
584 if (!preg_match('/^comment_/', $currvalue) || (count($selectedValues) == 1)) {
585 $display = "display:none";
586 $comment = "";
587 } else {
588 $display = "display:inline-block";
589 $comment = $selectedValues[count($selectedValues) - 1];
591 echo "<input type='text'" .
592 " name='form_text_" . attr($field_id) . "'" .
593 " id='form_text_" . attr($field_id) . "'" .
594 " size='" . attr($frow['fld_length']) . "'" .
595 " class='form-control'" .
596 " " . ((!empty($frow['max_length'])) ? "maxlength='" . attr($frow['max_length']) . "'" : "") . " " .
597 " style='" . $display . "'" .
598 " value='" . attr($comment) . "'/>";
600 } elseif ($data_type == 2) { // simple text field
601 $fldlength = htmlspecialchars($frow['fld_length'], ENT_QUOTES);
602 $maxlength = $frow['max_length'];
603 $string_maxlength = "";
604 // if max_length is set to zero, then do not set a maxlength
605 if ($maxlength) {
606 $string_maxlength = "maxlength='" . attr($maxlength) . "'";
609 echo "<input type='text'" .
610 " class='form-control$smallform'" .
611 " name='form_$field_id_esc'" .
612 " id='form_$field_id_esc'" .
613 " size='$fldlength'" .
614 " $string_maxlength" .
615 " title='$description'" .
616 " value='$currescaped'";
617 $tmp = $lbfchange;
618 if (isOption($edit_options, 'C') !== false) {
619 $tmp .= "capitalizeMe(this);";
620 } elseif (isOption($edit_options, 'U') !== false) {
621 $tmp .= "this.value = this.value.toUpperCase();";
624 if ($tmp) {
625 echo " onchange='$tmp'";
628 $tmp = htmlspecialchars($GLOBALS['gbl_mask_patient_id'], ENT_QUOTES);
629 // If mask is for use at save time, treat as no mask.
630 if (strpos($tmp, '^') !== false) {
631 $tmp = '';
633 if ($field_id == 'pubpid' && strlen($tmp) > 0) {
634 echo " onkeyup='maskkeyup(this,\"$tmp\")'";
635 echo " onblur='maskblur(this,\"$tmp\")'";
638 if (isOption($edit_options, '1') !== false && strlen($currescaped) > 0) {
639 echo " readonly";
642 if ($disabled) {
643 echo ' disabled';
646 echo " />";
647 } elseif ($data_type == 3) { // long or multi-line text field
648 $textCols = htmlspecialchars($frow['fld_length'], ENT_QUOTES);
649 $textRows = htmlspecialchars($frow['fld_rows'], ENT_QUOTES);
650 echo "<textarea" .
651 " name='form_$field_id_esc'" .
652 " class='form-control$smallform'" .
653 " id='form_$field_id_esc'" .
654 " title='$description'" .
655 " cols='$textCols'" .
656 " rows='$textRows' $lbfonchange $disabled" .
657 ">" . $currescaped . "</textarea>";
658 } elseif ($data_type == 4) { // date
659 $age_asof_date = ''; // optionalAge() sets this
660 $age_format = isOption($edit_options, 'A') === false ? 3 : 0;
661 $agestr = optionalAge($frow, $currvalue, $age_asof_date, $description);
662 if ($agestr) {
663 echo "<table class='table'><tr><td class='text'>";
666 $onchange_string = '';
667 if (!$disabled && $agestr) {
668 $onchange_string = "onchange=\"if (typeof(updateAgeString) == 'function') " .
669 "updateAgeString('$field_id','$age_asof_date', $age_format, '$description')\"";
671 if ($data_type == 4) {
672 $modtmp = isOption($edit_options, 'F') === false ? 0 : 1;
673 $datetimepickerclass = $frow['validation'] === 'past_date' ? '-past' : ( $frow['validation'] === 'future_date' ? '-future' : '' );
674 if (!$modtmp) {
675 $dateValue = oeFormatShortDate(substr($currescaped, 0, 10));
676 echo "<input type='text' size='10' class='datepicker$datetimepickerclass form-control$smallform' name='form_$field_id_esc' id='form_$field_id_esc'" . " value='" . attr($dateValue) . "'";
677 } else {
678 $dateValue = oeFormatDateTime(substr($currescaped, 0, 20), 0);
679 echo "<input type='text' size='20' class='datetimepicker$datetimepickerclass form-control$smallform' name='form_$field_id_esc' id='form_$field_id_esc'" . " value='" . attr($dateValue) . "'";
682 if (!$agestr) {
683 echo " title='$description'";
686 // help chrome users avoid autocomplete interfere with datepicker widget display
687 if ($frow['field_id'] == 'DOB') {
688 echo " autocomplete='off' $onchange_string $lbfonchange $disabled />";
689 } else {
690 echo " $onchange_string $lbfonchange $disabled />";
693 // Optional display of age or gestational age.
694 if ($agestr) {
695 echo "</td></tr><tr><td id='span_$field_id' class='text'>" . text($agestr) . "</td></tr></table>";
697 } elseif ($data_type == 10) { // provider list, local providers only
698 $ures = sqlStatement("SELECT id, fname, lname, specialty FROM users " .
699 "WHERE active = 1 AND ( info IS NULL OR info NOT LIKE '%Inactive%' ) " .
700 "AND authorized = 1 " .
701 "ORDER BY lname, fname");
702 echo "<select name='form_$field_id_esc' id='form_$field_id_esc' title='$description' $lbfonchange $disabled class='form-control$smallform'>";
703 echo "<option value=''>" . xlt($empty_title) . "</option>";
704 $got_selected = false;
705 while ($urow = sqlFetchArray($ures)) {
706 $uname = text($urow['fname'] . ' ' . $urow['lname']);
707 $optionId = attr($urow['id']);
708 echo "<option value='$optionId'";
709 if ($urow['id'] == $currvalue) {
710 echo " selected";
711 $got_selected = true;
714 echo ">$uname</option>";
717 if (!$got_selected && $currvalue) {
718 echo "<option value='" . attr($currvalue) . "' selected>* " . text($currvalue) . " *</option>";
719 echo "</select>";
720 echo " <span class='text-danger' title='" . xla('Please choose a valid selection from the list.') . "'>" . xlt('Fix this') . "!</span>";
721 } else {
722 echo "</select>";
724 } elseif ($data_type == 11) { // provider list, including address book entries with an NPI number
725 $ures = sqlStatement("SELECT id, fname, lname, specialty FROM users " .
726 "WHERE active = 1 AND ( info IS NULL OR info NOT LIKE '%Inactive%' ) " .
727 "AND ( authorized = 1 OR ( username = '' AND npi != '' ) ) " .
728 "ORDER BY lname, fname");
729 echo "<select name='form_$field_id_esc' id='form_$field_id_esc' title='$description' class='form-control$smallform'";
730 echo " $lbfonchange $disabled>";
731 echo "<option value=''>" . xlt('Unassigned') . "</option>";
732 $got_selected = false;
733 while ($urow = sqlFetchArray($ures)) {
734 $uname = text($urow['fname'] . ' ' . $urow['lname']);
735 $optionId = attr($urow['id']);
736 echo "<option value='$optionId'";
737 if ($urow['id'] == $currvalue) {
738 echo " selected";
739 $got_selected = true;
742 echo ">$uname</option>";
745 if (!$got_selected && $currvalue) {
746 echo "<option value='" . attr($currvalue) . "' selected>* " . text($currvalue) . " *</option>";
747 echo "</select>";
748 echo " <span class='text-danger' title='" . xla('Please choose a valid selection from the list.') . "'>" . xlt('Fix this') . "!</span>";
749 } else {
750 echo "</select>";
752 } elseif ($data_type == 12) { // pharmacy list
753 echo "<select name='form_$field_id_esc' id='form_$field_id_esc' title='$description' class='form-control$smallform'";
754 echo " $lbfonchange $disabled>";
755 echo "<option value='0'></option>";
756 $pres = get_pharmacies();
757 $got_selected = false;
758 $zone = '';
759 while ($prow = sqlFetchArray($pres)) {
760 if ($zone != strtolower(trim($prow['city']))) {
761 if ($zone != '') {
762 echo "</optgroup>";
764 $zone = strtolower(trim($prow['city']));
765 echo "<optgroup label='" . attr($prow['city']) . "'>";
767 $key = $prow['id'];
768 $optionValue = htmlspecialchars($key, ENT_QUOTES);
769 $optionLabel = htmlspecialchars($prow['name'] . ' ' . $prow['area_code'] . '-' .
770 $prow['prefix'] . '-' . $prow['number'] . ' / ' .
771 $prow['line1'] . ' / ' . $prow['city'], ENT_NOQUOTES);
772 echo "<option value='$optionValue'";
773 if ($currvalue == $key) {
774 echo " selected";
775 $got_selected = true;
778 echo ">$optionLabel</option>";
781 if (!$got_selected && $currvalue) {
782 echo "<option value='" . attr($currvalue) . "' selected>* " . text($currvalue) . " *</option>";
783 echo "</select>";
784 echo " <span class='text-danger' title='" . xla('Please choose a valid selection from the list.') . "'>" . xlt('Fix this') . "!</span>";
785 } else {
786 echo "</select>";
788 } elseif ($data_type == 13) { // squads
789 echo "<select name='form_$field_id_esc' id='form_$field_id_esc' title='$description' class='form-control$smallform'";
790 echo " $lbfonchange $disabled>";
791 echo "<option value=''>&nbsp;</option>";
792 $squads = AclExtended::aclGetSquads();
793 if ($squads) {
794 foreach ($squads as $key => $value) {
795 $optionValue = htmlspecialchars($key, ENT_QUOTES);
796 $optionLabel = htmlspecialchars($value[3], ENT_NOQUOTES);
797 echo "<option value='$optionValue'";
798 if ($currvalue == $key) {
799 echo " selected";
802 echo ">$optionLabel</option>\n";
806 echo "</select>";
807 } elseif ($data_type == 14) {
808 // Address book, preferring organization name if it exists and is not in
809 // parentheses, and excluding local users who are not providers.
810 // Supports "referred to" practitioners and facilities.
811 // Alternatively the letter L in edit_options means that abook_type
812 // must be "ord_lab", indicating types used with the procedure
813 // lab ordering system.
814 // Alternatively the letter O in edit_options means that abook_type
815 // must begin with "ord_", indicating types used with the procedure
816 // ordering system.
817 // Alternatively the letter V in edit_options means that abook_type
818 // must be "vendor", indicating the Vendor type.
819 // Alternatively the letter R in edit_options means that abook_type
820 // must be "dist", indicating the Distributor type.
822 if (isOption($edit_options, 'L') !== false) {
823 $tmp = "abook_type = 'ord_lab'";
824 } elseif (isOption($edit_options, 'O') !== false) {
825 $tmp = "abook_type LIKE 'ord\\_%'";
826 } elseif (isOption($edit_options, 'V') !== false) {
827 $tmp = "abook_type LIKE 'vendor%'";
828 } elseif (isOption($edit_options, 'R') !== false) {
829 $tmp = "abook_type LIKE 'dist'";
830 } else {
831 $tmp = "( username = '' OR authorized = 1 )";
834 $ures = sqlStatement("SELECT id, fname, lname, organization, username, npi FROM users " .
835 "WHERE active = 1 AND ( info IS NULL OR info NOT LIKE '%Inactive%' ) " .
836 "AND $tmp " .
837 "ORDER BY organization, lname, fname, npi");
838 echo "<select name='form_$field_id_esc' id='form_$field_id_esc' title='$description' class='form-control$smallform'";
839 echo " $lbfonchange $disabled>";
840 echo "<option value=''>" . htmlspecialchars(xl('Unassigned'), ENT_NOQUOTES) . "</option>";
841 while ($urow = sqlFetchArray($ures)) {
842 $uname = $urow['organization'];
843 if (empty($uname) || substr($uname, 0, 1) == '(') {
844 $uname = $urow['lname'];
845 if ($urow['fname']) {
846 $uname .= ", " . $urow['fname'];
848 if ($urow['npi']) {
849 $uname .= ": " . $urow['npi'];
853 $optionValue = htmlspecialchars($urow['id'], ENT_QUOTES);
854 $optionLabel = htmlspecialchars($uname, ENT_NOQUOTES);
855 echo "<option value='$optionValue'";
856 // Failure to translate Local and External is not an error here;
857 // they are only used as internal flags and must not be translated!
858 $title = $urow['username'] ? 'Local' : 'External';
859 $optionTitle = htmlspecialchars($title, ENT_QUOTES);
860 echo " title='$optionTitle'";
861 if ($urow['id'] == $currvalue) {
862 echo " selected";
865 echo ">$optionLabel</option>";
868 echo "</select>";
869 } elseif ($data_type == 15) { // A billing code. If description matches an existing code type then that type is used.
870 $codetype = '';
871 if (!empty($frow['description']) && isset($code_types[$frow['description']])) {
872 $codetype = $frow['description'];
874 $fldlength = attr($frow['fld_length']);
875 $maxlength = $frow['max_length'];
876 $string_maxlength = "";
877 // if max_length is set to zero, then do not set a maxlength
878 if ($maxlength) {
879 $string_maxlength = "maxlength='" . attr($maxlength) . "'";
881 // Edit option E means allow multiple (Extra) billing codes in a field.
882 // We invent a class name for this because JavaScript needs to know.
883 $className = '';
884 if (strpos($frow['edit_options'], 'E') !== false) {
885 $className = 'EditOptionE';
888 if (isOption($edit_options, '2') !== false) {
889 // Option "2" generates a hidden input for the codes, and a matching visible field
890 // displaying their descriptions. First step is computing the description string.
891 $currdescstring = '';
892 if (!empty($currvalue)) {
893 $relcodes = explode(';', $currvalue);
894 foreach ($relcodes as $codestring) {
895 if ($codestring === '') {
896 continue;
898 if ($currdescstring !== '') {
899 $currdescstring .= '; ';
901 $currdescstring .= getCodeDescription($codestring, $codetype);
905 $currdescstring = attr($currdescstring);
907 echo "<div>"; // wrapper for myHideOrShow()
908 echo "<input type='text'" .
909 " name='form_$field_id_esc'" .
910 " id='form_related_code'" .
911 " class='" . attr($className) . "'" .
912 " size='$fldlength'" .
913 " value='$currescaped'" .
914 " style='display:none'" .
915 " $lbfonchange readonly $disabled />";
916 // Extra readonly input field for optional display of code description(s).
917 echo "<input type='text'" .
918 " name='form_$field_id_esc" . "__desc'" .
919 " size='$fldlength'" .
920 " title='$description'" .
921 " value='$currdescstring'";
922 if (!$disabled) {
923 echo " onclick='sel_related(this," . attr_js($codetype) . ")'";
926 echo "class='form-control$smallform'";
927 echo " readonly $disabled />";
928 echo "</div>";
929 } else {
930 echo "<input type='text'" .
931 " name='form_$field_id_esc'" .
932 " id='form_related_code'" .
933 " class='" . attr($className) . "'" .
934 " size='$fldlength'" .
935 " $string_maxlength" .
936 " title='$description'" .
937 " value='$currescaped'";
938 if (!$disabled) {
939 echo " onclick='sel_related(this," . attr_js($codetype) . ")'";
942 echo "class='form-control$smallform'";
943 echo " $lbfonchange readonly $disabled />";
945 } elseif ($data_type == 16) { // insurance company list
946 echo "<select name='form_$field_id_esc' id='form_$field_id_esc' class='form-control$smallform' title='$description'>";
947 echo "<option value='0'></option>";
948 $insprovs = getInsuranceProviders();
949 $got_selected = false;
950 foreach ($insprovs as $key => $ipname) {
951 $optionValue = htmlspecialchars($key, ENT_QUOTES);
952 $optionLabel = htmlspecialchars($ipname, ENT_NOQUOTES);
953 echo "<option value='$optionValue'";
954 if ($currvalue == $key) {
955 echo " selected";
956 $got_selected = true;
959 echo ">$optionLabel</option>";
962 if (!$got_selected && $currvalue) {
963 echo "<option value='" . attr($currvalue) . "' selected>* " . text($currvalue) . " *</option>";
964 echo "</select>";
965 echo " <span class='text-danger' title='" . xla('Please choose a valid selection from the list.') . "'>" . xlt('Fix this') . "!</span>";
966 } else {
967 echo "</select>";
969 } elseif ($data_type == 17) { // issue types
970 echo "<select name='form_$field_id_esc' id='form_$field_id_esc' class='form-control$smallform' title='$description'>";
971 echo "<option value='0'></option>";
972 $got_selected = false;
973 foreach ($ISSUE_TYPES as $key => $value) {
974 $optionValue = htmlspecialchars($key, ENT_QUOTES);
975 $optionLabel = htmlspecialchars($value[1], ENT_NOQUOTES);
976 echo "<option value='$optionValue'";
977 if ($currvalue == $key) {
978 echo " selected";
979 $got_selected = true;
982 echo ">$optionLabel</option>";
985 if (!$got_selected && strlen($currvalue) > 0) {
986 echo "<option value='" . attr($currvalue) . "' selected>* " . text($currvalue) . " *</option>";
987 echo "</select>";
988 echo " <span class='text-danger' title='" . xla('Please choose a valid selection from the list.') . "'>" . xlt('Fix this') . "!</span>";
989 } else {
990 echo "</select>";
992 } elseif ($data_type == 18) { // Visit categories.
993 $cres = sqlStatement("SELECT pc_catid, pc_catname " .
994 "FROM openemr_postcalendar_categories ORDER BY pc_catname");
995 echo "<select name='form_$field_id_esc' id='form_$field_id_esc' class='form-control$smallform' title='$description'" . " $lbfonchange $disabled>";
996 echo "<option value=''>" . xlt($empty_title) . "</option>";
997 $got_selected = false;
998 while ($crow = sqlFetchArray($cres)) {
999 $catid = $crow['pc_catid'];
1000 if (($catid < 9 && $catid != 5) || $catid == 11) {
1001 continue;
1004 echo "<option value='" . attr($catid) . "'";
1005 if ($catid == $currvalue) {
1006 echo " selected";
1007 $got_selected = true;
1010 echo ">" . text(xl_appt_category($crow['pc_catname'])) . "</option>";
1013 if (!$got_selected && $currvalue) {
1014 echo "<option value='" . attr($currvalue) . "' selected>* " . text($currvalue) . " *</option>";
1015 echo "</select>";
1016 echo " <span class='text-danger' title='" . xla('Please choose a valid selection from the list.') . "'>" . xlt('Fix this') . "!</span>";
1017 } else {
1018 echo "</select>";
1020 } elseif ($data_type == 21) { // a set of labeled checkboxes
1021 // If no list then it's a single checkbox and its value is "Yes" or empty.
1022 if (!$list_id) {
1023 echo "<input type='checkbox' name='form_{$field_id_esc}' " .
1024 "id='form_{$field_id_esc}' value='Yes' $lbfonchange";
1025 if ($currvalue) {
1026 echo " checked";
1028 echo " $disabled />";
1029 } else {
1030 // In this special case, fld_length is the number of columns generated.
1031 $cols = max(1, $frow['fld_length']);
1032 $avalue = explode('|', $currvalue);
1033 $lres = sqlStatement("SELECT * FROM list_options " .
1034 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
1035 echo "<table class='w-100' cellpadding='0' cellspacing='0' title='" . attr($description) . "'>";
1036 $tdpct = (int) (100 / $cols);
1037 for ($count = 0; $lrow = sqlFetchArray($lres); ++$count) {
1038 $option_id = $lrow['option_id'];
1039 $option_id_esc = htmlspecialchars($option_id, ENT_QUOTES);
1040 // if ($count) echo "<br />";
1041 if ($count % $cols == 0) {
1042 if ($count) {
1043 echo "</tr>";
1045 echo "<tr>";
1047 echo "<td width='" . attr($tdpct) . "%' nowrap>";
1048 echo "<input type='checkbox' name='form_{$field_id_esc}[$option_id_esc]'" .
1049 "id='form_{$field_id_esc}[$option_id_esc]' class='form-check-inline' value='1' $lbfonchange";
1050 if (in_array($option_id, $avalue)) {
1051 echo " checked";
1053 // Added 5-09 by BM - Translate label if applicable
1054 echo " $disabled />" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES);
1055 echo "</td>";
1057 if ($count) {
1058 echo "</tr>";
1059 if ($count > $cols) {
1060 // Add some space after multiple rows of checkboxes.
1061 $cols = htmlspecialchars($cols, ENT_QUOTES);
1062 echo "<tr><td colspan='$cols' style='height:0.7rem'></td></tr>";
1065 echo "</table>";
1067 } elseif ($data_type == 22) { // a set of labeled text input fields
1068 $tmp = explode('|', $currvalue);
1069 $avalue = array();
1070 foreach ($tmp as $value) {
1071 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
1072 $avalue[$matches[1]] = $matches[2];
1076 $lres = sqlStatement("SELECT * FROM list_options " .
1077 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
1078 echo "<table class='table'>";
1079 while ($lrow = sqlFetchArray($lres)) {
1080 $option_id = $lrow['option_id'];
1081 $option_id_esc = htmlspecialchars($option_id, ENT_QUOTES);
1082 $maxlength = $frow['max_length'];
1083 $string_maxlength = "";
1084 // if max_length is set to zero, then do not set a maxlength
1085 if ($maxlength) {
1086 $string_maxlength = "maxlength='" . attr($maxlength) . "'";
1089 $fldlength = empty($frow['fld_length']) ? 20 : $frow['fld_length'];
1091 // Added 5-09 by BM - Translate label if applicable
1092 echo "<tr><td>" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES) . "&nbsp;</td>";
1093 $fldlength = htmlspecialchars($fldlength, ENT_QUOTES);
1094 $optionValue = htmlspecialchars($avalue[$option_id], ENT_QUOTES);
1095 echo "<td><input type='text'" .
1096 " name='form_{$field_id_esc}[$option_id_esc]'" .
1097 " id='form_{$field_id_esc}[$option_id_esc]'" .
1098 " size='$fldlength'" .
1099 " class='form-control$smallform'" .
1100 " $string_maxlength" .
1101 " value='$optionValue'";
1102 echo " $lbfonchange $disabled /></td></tr>";
1105 echo "</table>";
1106 } elseif ($data_type == 23) { // a set of exam results; 3 radio buttons and a text field:
1107 $tmp = explode('|', $currvalue);
1108 $avalue = array();
1109 foreach ($tmp as $value) {
1110 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
1111 $avalue[$matches[1]] = $matches[2];
1115 $maxlength = $frow['max_length'];
1116 $string_maxlength = "";
1117 // if max_length is set to zero, then do not set a maxlength
1118 if ($maxlength) {
1119 $string_maxlength = "maxlength='" . attr($maxlength) . "'";
1122 $fldlength = empty($frow['fld_length']) ? 20 : $frow['fld_length'];
1123 $lres = sqlStatement("SELECT * FROM list_options " .
1124 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
1125 echo "<table class='table'>";
1126 echo "<tr><td>&nbsp;</td><td class='font-weight-bold'>" .
1127 htmlspecialchars(xl('N/A'), ENT_NOQUOTES) .
1128 "&nbsp;</td><td class='font-weight-bold'>" .
1129 htmlspecialchars(xl('Nor'), ENT_NOQUOTES) . "&nbsp;</td>" .
1130 "<td class='font-weight-bold'>" .
1131 htmlspecialchars(xl('Abn'), ENT_NOQUOTES) . "&nbsp;</td><td class='font-weight-bold'>" .
1132 htmlspecialchars(xl('Date/Notes'), ENT_NOQUOTES) . "</td></tr>";
1133 while ($lrow = sqlFetchArray($lres)) {
1134 $option_id = $lrow['option_id'];
1135 $option_id_esc = htmlspecialchars($option_id, ENT_QUOTES);
1136 $restype = substr(($avalue[$option_id] ?? ''), 0, 1);
1137 $resnote = substr(($avalue[$option_id] ?? ''), 2);
1139 // Added 5-09 by BM - Translate label if applicable
1140 echo "<tr><td>" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES) . "&nbsp;</td>";
1142 for ($i = 0; $i < 3; ++$i) {
1143 $inputValue = htmlspecialchars($i, ENT_QUOTES);
1144 echo "<td><input type='radio'" .
1145 " name='radio_{$field_id_esc}[$option_id_esc]'" .
1146 " id='radio_{$field_id_esc}[$option_id_esc]'" .
1147 " value='$inputValue' $lbfonchange";
1148 if ($restype === "$i") {
1149 echo " checked";
1152 echo " $disabled /></td>";
1155 $fldlength = htmlspecialchars($fldlength, ENT_QUOTES);
1156 $resnote = htmlspecialchars($resnote, ENT_QUOTES);
1157 echo "<td><input type='text'" .
1158 " name='form_{$field_id_esc}[$option_id_esc]'" .
1159 " id='form_{$field_id_esc}[$option_id_esc]'" .
1160 " size='$fldlength'" .
1161 " class='form-control'" .
1162 " $string_maxlength" .
1163 " value='$resnote' $disabled /></td>";
1164 echo "</tr>";
1167 echo "</table>";
1168 } elseif ($data_type == 24) { // the list of active allergies for the current patient
1169 // this is read-only!
1170 $query = "SELECT title, comments FROM lists WHERE " .
1171 "pid = ? AND type = 'allergy' AND enddate IS NULL " .
1172 "ORDER BY begdate";
1173 // echo "<!-- $query -->\n"; // debugging
1174 $lres = sqlStatement($query, array($GLOBALS['pid']));
1175 $count = 0;
1176 while ($lrow = sqlFetchArray($lres)) {
1177 if ($count++) {
1178 echo "<br />";
1181 echo htmlspecialchars($lrow['title'], ENT_NOQUOTES);
1182 if ($lrow['comments']) {
1183 echo ' (' . htmlspecialchars($lrow['comments'], ENT_NOQUOTES) . ')';
1186 } elseif ($data_type == 25) { // a set of labeled checkboxes, each with a text field:
1187 $tmp = explode('|', $currvalue);
1188 $avalue = array();
1189 foreach ($tmp as $value) {
1190 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
1191 $avalue[$matches[1]] = $matches[2];
1195 $maxlength = $frow['max_length'];
1196 $string_maxlength = "";
1197 // if max_length is set to zero, then do not set a maxlength
1198 if ($maxlength) {
1199 $string_maxlength = "maxlength='" . attr($maxlength) . "'";
1202 $fldlength = empty($frow['fld_length']) ? 20 : $frow['fld_length'];
1203 $lres = sqlStatement("SELECT * FROM list_options " .
1204 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
1205 echo "<table class='table'>";
1206 while ($lrow = sqlFetchArray($lres)) {
1207 $option_id = $lrow['option_id'];
1208 $option_id_esc = htmlspecialchars($option_id, ENT_QUOTES);
1209 $restype = substr($avalue[$option_id], 0, 1);
1210 $resnote = substr($avalue[$option_id], 2);
1212 // Added 5-09 by BM - Translate label if applicable
1213 echo "<tr><td>" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES) . "&nbsp;</td>";
1215 $option_id = htmlspecialchars($option_id, ENT_QUOTES);
1216 echo "<td><input type='checkbox' name='check_{$field_id_esc}[$option_id_esc]'" .
1217 " id='check_{$field_id_esc}[$option_id_esc]' class='form-check-inline' value='1' $lbfonchange";
1218 if ($restype) {
1219 echo " checked";
1222 echo " $disabled />&nbsp;</td>";
1223 $fldlength = htmlspecialchars($fldlength, ENT_QUOTES);
1224 $resnote = htmlspecialchars($resnote, ENT_QUOTES);
1225 echo "<td><input type='text'" .
1226 " name='form_{$field_id_esc}[$option_id_esc]'" .
1227 " id='form_{$field_id_esc}[$option_id_esc]'" .
1228 " size='$fldlength'" .
1229 " class='form-control$smallform' " .
1230 " $string_maxlength" .
1231 " value='$resnote' $disabled /></td>";
1232 echo "</tr>";
1235 echo "</table>";
1236 } elseif ($data_type == 26) { // single-selection list with ability to add to it
1237 echo "<div class='input-group'>";
1238 echo generate_select_list(
1239 "form_$field_id",
1240 $list_id,
1241 $currvalue,
1242 $description,
1243 ($showEmpty ? $empty_title : ''),
1244 'addtolistclass_' . $list_id . $smallform,
1245 $lbfchange,
1247 ($disabled ? array('disabled' => 'disabled') : null),
1248 false,
1249 $backup_list
1251 // show the add button if user has access to correct list
1252 $inputValue = htmlspecialchars(xl('Add'), ENT_QUOTES);
1253 $outputAddButton = "<div class='input-group-append'><input type='button' class='btn btn-primary addtolist' id='addtolistid_" . $list_id_esc . "' fieldid='form_" .
1254 $field_id_esc . "' value='$inputValue' $disabled /></div>";
1255 if (AclExtended::acoExist('lists', $list_id)) {
1256 // a specific aco exist for this list, so ensure access
1257 if (AclMain::aclCheckCore('lists', $list_id)) {
1258 echo $outputAddButton;
1260 } else {
1261 // no specific aco exist for this list, so check for access to 'default' list
1262 if (AclMain::aclCheckCore('lists', 'default')) {
1263 echo $outputAddButton;
1266 echo "</div>";
1267 } elseif ($data_type == 27) { // a set of labeled radio buttons
1268 // In this special case, fld_length is the number of columns generated.
1269 $cols = max(1, $frow['fld_length']);
1270 // Support for edit option M.
1271 if (isOption($edit_options, 'M')) {
1272 ++$membership_group_number;
1275 $lres = sqlStatement("SELECT * FROM list_options " .
1276 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
1277 echo "<table class='table w-100'>";
1278 $tdpct = (int) (100 / $cols);
1279 $got_selected = false;
1280 for ($count = 0; $lrow = sqlFetchArray($lres); ++$count) {
1281 $option_id = $lrow['option_id'];
1282 $option_id_esc = htmlspecialchars($option_id, ENT_QUOTES);
1283 if ($count % $cols == 0) {
1284 if ($count) {
1285 echo "</tr>";
1287 echo "<tr>";
1289 echo "<td width='" . attr($tdpct) . "%' nowrap>";
1290 echo "<input type='radio' name='form_{$field_id_esc}' id='form_{$field_id_esc}[$option_id_esc]'" .
1291 " value='$option_id_esc' $lbfonchange";
1292 // Support for edit options M and m.
1293 if (isOption($edit_options, 'M')) {
1294 echo " class='form-check-inline'";
1295 echo " onclick='checkGroupMembers(this, $membership_group_number);'";
1296 } elseif (isOption($edit_options, 'm')) {
1297 echo " class='form-check-inline lbf_memgroup_$membership_group_number'";
1298 } else {
1299 echo " class='form-check-inline'";
1302 if (
1303 (strlen($currvalue) == 0 && $lrow['is_default']) ||
1304 (strlen($currvalue) > 0 && $option_id == $currvalue)
1306 echo " checked";
1307 $got_selected = true;
1309 echo " $disabled />" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES);
1310 echo "</td>";
1313 if ($count) {
1314 echo "</tr>";
1315 if ($count > $cols) {
1316 // Add some space after multiple rows of radio buttons.
1317 $cols = htmlspecialchars($cols, ENT_QUOTES);
1318 echo "<tr><td colspan='$cols' style='height: 0.7rem'></td></tr>";
1322 echo "</table>";
1323 if (!$got_selected && strlen($currvalue) > 0) {
1324 $fontTitle = htmlspecialchars(xl('Please choose a valid selection.'), ENT_QUOTES);
1325 $fontText = htmlspecialchars(xl('Fix this'), ENT_NOQUOTES);
1326 echo "$currescaped <span class='text-danger' title='$fontTitle'>$fontText!</span>";
1328 } elseif ($data_type == 28 || $data_type == 32) { // special case for history of lifestyle status; 3 radio buttons
1329 // and a date text field:
1330 // VicarePlus :: A selection list box for smoking status:
1331 $tmp = explode('|', $currvalue);
1332 switch (count($tmp)) {
1333 case "4":
1334 $resnote = $tmp[0];
1335 $restype = $tmp[1];
1336 $resdate = oeFormatShortDate($tmp[2]);
1337 $reslist = $tmp[3];
1338 break;
1339 case "3":
1340 $resnote = $tmp[0];
1341 $restype = $tmp[1];
1342 $resdate = oeFormatShortDate($tmp[2]);
1343 $reslist = '';
1344 break;
1345 case "2":
1346 $resnote = $tmp[0];
1347 $restype = $tmp[1];
1348 $resdate = "";
1349 $reslist = '';
1350 break;
1351 case "1":
1352 $resnote = $tmp[0];
1353 $resdate = $restype = "";
1354 $reslist = '';
1355 break;
1356 default:
1357 $restype = $resdate = $resnote = "";
1358 $reslist = '';
1359 break;
1362 $maxlength = $frow['max_length'];
1363 $string_maxlength = "";
1364 // if max_length is set to zero, then do not set a maxlength
1365 if ($maxlength) {
1366 $string_maxlength = "maxlength='" . attr($maxlength) . "'";
1369 $fldlength = empty($frow['fld_length']) ? 20 : $frow['fld_length'];
1371 $fldlength = htmlspecialchars($fldlength, ENT_QUOTES);
1372 $resnote = htmlspecialchars($resnote, ENT_QUOTES);
1373 $resdate = htmlspecialchars($resdate, ENT_QUOTES);
1374 echo "<table class='table'>";
1375 echo "<tr>";
1376 if ($data_type == 28) {
1377 // input text
1378 echo "<td><input type='text' class='form-control'" .
1379 " name='form_$field_id_esc'" .
1380 " id='form_$field_id_esc'" .
1381 " size='$fldlength'" .
1382 " class='form-control$smallform'" .
1383 " $string_maxlength" .
1384 " value='$resnote' $disabled />&nbsp;</td>";
1385 echo "<td class='font-weight-bold'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" .
1386 "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" .
1387 htmlspecialchars(xl('Status'), ENT_NOQUOTES) . ":&nbsp;&nbsp;</td>";
1388 } elseif ($data_type == 32) {
1389 // input text
1390 echo "<tr><td><input type='text'" .
1391 " name='form_text_$field_id_esc'" .
1392 " id='form_text_$field_id_esc'" .
1393 " size='$fldlength'" .
1394 " class='form-control$smallform'" .
1395 " $string_maxlength" .
1396 " value='$resnote' $disabled />&nbsp;</td></tr>";
1397 echo "<td>";
1398 //Selection list for smoking status
1399 $onchange = 'radioChange(this.options[this.selectedIndex].value)';//VicarePlus :: The javascript function for selection list.
1400 echo generate_select_list(
1401 "form_$field_id",
1402 $list_id,
1403 $reslist,
1404 $description,
1405 ($showEmpty ? $empty_title : ''),
1406 $smallform,
1407 $onchange,
1409 ($disabled ? array('disabled' => 'disabled') : null)
1411 echo "</td>";
1412 echo "<td class='font-weight-bold'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" . xlt('Status') . ":&nbsp;&nbsp;</td>";
1415 // current
1416 echo "<td class='text'><input type='radio'" .
1417 " name='radio_{$field_id_esc}'" .
1418 " id='radio_{$field_id_esc}[current]'" .
1419 " class='form-check-inline'" .
1420 " value='current" . $field_id_esc . "' $lbfonchange";
1421 if ($restype == "current" . $field_id) {
1422 echo " checked";
1425 if ($data_type == 32) {
1426 echo " onClick='smoking_statusClicked(this)'";
1429 echo " />" . xlt('Current') . "&nbsp;</td>";
1430 // quit
1431 echo "<td class='text'><input type='radio'" .
1432 " name='radio_{$field_id_esc}'" .
1433 " id='radio_{$field_id_esc}[quit]'" .
1434 " class='form-check-inline'" .
1435 " value='quit" . $field_id_esc . "' $lbfonchange";
1436 if ($restype == "quit" . $field_id) {
1437 echo " checked";
1440 if ($data_type == 32) {
1441 echo " onClick='smoking_statusClicked(this)'";
1444 echo " $disabled />" . xlt('Quit') . "&nbsp;</td>";
1445 // quit date
1446 echo "<td class='text'><input type='text' size='6' class='form-control datepicker' name='date_$field_id_esc' id='date_$field_id_esc'" .
1447 " value='$resdate'" .
1448 " title='$description'" .
1449 " $disabled />";
1450 echo "&nbsp;</td>";
1451 // never
1452 echo "<td class='text'><input type='radio'" .
1453 " name='radio_{$field_id_esc}'" .
1454 " class='form-check-inline'" .
1455 " id='radio_{$field_id_esc}[never]'" .
1456 " value='never" . $field_id_esc . "' $lbfonchange";
1457 if ($restype == "never" . $field_id) {
1458 echo " checked";
1461 if ($data_type == 32) {
1462 echo " onClick='smoking_statusClicked(this)'";
1465 echo " />" . xlt('Never') . "&nbsp;</td>";
1466 // Not Applicable
1467 echo "<td class='text'><input type='radio'" .
1468 " class='form-check-inline' " .
1469 " name='radio_{$field_id}'" .
1470 " id='radio_{$field_id}[not_applicable]'" .
1471 " value='not_applicable" . $field_id . "' $lbfonchange";
1472 if ($restype == "not_applicable" . $field_id) {
1473 echo " checked";
1476 if ($data_type == 32) {
1477 echo " onClick='smoking_statusClicked(this)'";
1480 echo " $disabled />" . xlt('N/A') . "&nbsp;</td>";
1482 //Added on 5-jun-2k14 (regarding 'Smoking Status - display SNOMED code description')
1483 echo "<td class='text'><div id='smoke_code'></div></td>";
1484 echo "</tr>";
1485 echo "</table>";
1486 } elseif ($data_type == 31) { // static text. read-only, of course.
1487 echo parse_static_text($frow);
1488 } elseif ($data_type == 34) {
1489 // $data_type == 33
1490 // Race and Ethnicity. After added support for backup lists, this is now the same as datatype 36; so have migrated it there.
1491 // $data_type == 33
1493 $arr = explode("|*|*|*|", $currvalue);
1494 echo "<div>"; // wrapper for myHideOrShow()
1495 echo "<a href='../../../library/custom_template/custom_template.php?type=form_{$field_id}&contextName=" . htmlspecialchars($list_id_esc, ENT_QUOTES) . "' class='iframe_medium text-body text-decoration-none'>";
1496 echo "<div id='form_{$field_id}_div' class='text-area' style='min-width: 133px'>" . $arr[0] . "</div>";
1497 echo "<div style='display: none'><textarea name='form_{$field_id}' id='form_{$field_id}' class='form-control$smallform' style='display: none' $lbfonchange $disabled>" . $currvalue . "</textarea></div>";
1498 echo "</a>";
1499 echo "</div>";
1500 } elseif ($data_type == 35) { //facilities drop-down list
1501 if (empty($currvalue)) {
1502 $currvalue = 0;
1505 dropdown_facility(
1506 $selected = $currvalue,
1507 $name = "form_$field_id_esc",
1508 $allow_unspecified = true,
1509 $allow_allfacilities = false,
1510 $disabled,
1511 $lbfchange
1513 } elseif ($data_type == 36 || $data_type == 33) { //multiple select, supports backup list
1514 echo generate_select_list(
1515 "form_$field_id",
1516 $list_id,
1517 $currvalue,
1518 $description,
1519 $showEmpty ? $empty_title : '',
1520 $smallform,
1521 $lbfchange,
1523 null,
1524 true,
1525 $backup_list
1528 // A set of lab test results; Gestation, 3 radio buttons, test value, notes field:
1529 } elseif ($data_type == 37) {
1530 echo genLabResults($frow, $currvalue, 0, $disabled);
1531 } elseif ($data_type == 40) { // Canvas and related elements for browser-side image drawing.
1532 // Note you must invoke lbf_canvas_head() (below) to use this field type in a form.
1533 // Unlike other field types, width and height are in pixels.
1534 $canWidth = intval($frow['fld_length']);
1535 $canHeight = intval($frow['fld_rows']);
1536 if (empty($currvalue)) {
1537 if (preg_match('/\\bimage=([a-zA-Z0-9._-]*)/', $frow['description'], $matches)) {
1538 // If defined this is the filename of the default starting image.
1539 $currvalue = $GLOBALS['web_root'] . '/sites/' . $_SESSION['site_id'] . '/images/' . $matches[1];
1542 $mywidth = 50 + ($canWidth > 250 ? $canWidth : 250);
1543 $myheight = 31 + ($canHeight > 261 ? $canHeight : 261);
1544 echo "<div>"; // wrapper for myHideOrShow()
1545 echo "<div id='form_$field_id_esc' style='width:$mywidth; height:$myheight;'></div>";
1546 // Hidden form field exists to send updated data to the server at submit time.
1547 echo "<input type='hidden' name='form_$field_id_esc' value='' />";
1548 // Hidden image exists to support initialization of the canvas.
1549 echo "<img src='" . attr($currvalue) . "' id='form_{$field_id_esc}_img' style='display:none'>";
1550 echo "</div>";
1551 // $date_init is a misnomer but it's the place for browser-side setup logic.
1552 $date_init .= " lbfCanvasSetup('form_$field_id_esc', $canWidth, $canHeight);\n";
1553 } elseif ($data_type == 41 || $data_type == 42) {
1554 $datatype = 'patient-signature';
1555 $cpid = $GLOBALS['pid'];
1556 $cuser = $_SESSION['authUserID'];
1557 if ($data_type == 42) {
1558 $datatype = 'admin-signature';
1560 echo "<input type='hidden' id='form_$field_id_esc' name='form_$field_id_esc' value='' />\n";
1561 echo "<img class='signature' id='form_{$field_id_esc}_img' title='$description'
1562 data-pid='$cpid' data-user='$cuser' data-type='$datatype'
1563 data-action='fetch_signature' alt='Get Signature' src='" . attr($currvalue) . "'>\n";
1564 } elseif ($data_type == 44) { //multiple select facility
1565 if (empty($currvalue)) {
1566 $currvalue = 0;
1569 dropdown_facility(
1570 $selected = $currvalue,
1571 $name = "form_$field_id_esc",
1572 $allow_unspecified = false,
1573 $allow_allfacilities = false,
1574 $disabled,
1575 $lbfchange,
1576 true
1578 } elseif ($data_type == 45) { // Multiple provider list, local providers only
1579 $ures = sqlStatement("SELECT id, fname, lname, specialty FROM users " .
1580 "WHERE active = 1 AND ( info IS NULL OR info NOT LIKE '%Inactive%' ) " .
1581 "AND authorized = 1 ORDER BY lname, fname");
1582 echo "<select name='form_$field_id_esc" . "[]'" . " id='form_$field_id_esc' title='$description' $lbfonchange $disabled class='form-control$smallform select-dropdown' multiple='multiple'>";
1583 $got_selected = false;
1584 while ($urow = sqlFetchArray($ures)) {
1585 $uname = text($urow['fname'] . ' ' . $urow['lname']);
1586 $optionId = attr($urow['id']);
1587 echo "<option value='$optionId'";
1588 $selectedValues = explode("|", $currvalue);
1590 if (in_array($optionId, $selectedValues)) {
1591 echo " selected";
1592 $got_selected = true;
1595 echo ">$uname</option>";
1598 if (!$got_selected && $currvalue) {
1599 echo "<option value='" . attr($currvalue) . "' selected>* " . text($currvalue) . " *</option>";
1600 echo "</select>";
1601 echo " <span class='text-danger' title='" . xla('Please choose a valid selection from the list.') . "'>" . xlt('Fix this') . "!</span>";
1602 } else {
1603 echo "</select>";
1606 // Patient selector field.
1607 } elseif ($data_type == 51) {
1608 $fldlength = attr($frow['fld_length']);
1609 $currdescstring = '';
1610 if (!empty($currvalue)) {
1611 $currdescstring .= getPatientDescription($currvalue);
1613 $currdescstring = htmlspecialchars($currdescstring, ENT_QUOTES);
1614 echo "<div>"; // wrapper for myHideOrShow()
1615 echo "<input type='text'" .
1616 " name='form_$field_id_esc'" .
1617 " size='$fldlength'" .
1618 " value='$currescaped'" .
1619 " style='display:none'" .
1620 " $lbfonchange readonly $disabled />";
1621 // Extra readonly input field for patient description (name and pid).
1622 echo "<input type='text'" .
1623 " name='form_$field_id_esc" . "__desc'" .
1624 " size='$fldlength'" .
1625 " title='$description'" .
1626 " value='$currdescstring'";
1627 if (!$disabled) {
1628 echo " onclick='sel_patient(this, this.form.form_$field_id_esc)'";
1630 echo " readonly $disabled />";
1631 echo "</div>";
1635 function generate_print_field($frow, $currvalue, $value_allowed = true)
1637 global $rootdir, $date_init, $ISSUE_TYPES;
1639 $currescaped = htmlspecialchars($currvalue, ENT_QUOTES);
1641 $data_type = $frow['data_type'];
1642 $field_id = $frow['field_id'] ?? null;
1643 $list_id = $frow['list_id'];
1644 $fld_length = $frow['fld_length'] ?? null;
1645 $backup_list = $frow['list_backup_id'] ?? null;
1647 $description = attr(xl_layout_label($frow['description'] ?? ''));
1649 // Can pass $frow['empty_title'] with this variable, otherwise
1650 // will default to 'Unassigned'.
1651 // If it is 'SKIP' then an empty text title is completely skipped.
1652 $showEmpty = true;
1653 if (isset($frow['empty_title'])) {
1654 if ($frow['empty_title'] == "SKIP") {
1655 //do not display an 'empty' choice
1656 $showEmpty = false;
1657 $empty_title = "Unassigned";
1658 } else {
1659 $empty_title = $frow['empty_title'];
1661 } else {
1662 $empty_title = "Unassigned";
1665 // generic single-selection list
1666 // Supports backup lists.
1667 // if (false && ($data_type == 1 || $data_type == 26 || $data_type == 33 || $data_type == 43 || $data_type == 46)) {
1668 // We used to show all the list options but this was undone per CV request 2017-12-07
1669 // (see alternative code below).
1670 if ($data_type == 1 || $data_type == 26 || $data_type == 33 || $data_type == 43 || $data_type == 46) {
1671 if (empty($fld_length)) {
1672 if ($list_id == 'titles') {
1673 $fld_length = 3;
1674 } else {
1675 $fld_length = 10;
1679 $tmp = '';
1680 if ($currvalue) {
1681 if ($data_type == 46) {
1682 // support for single-selection list with comment support
1683 $selectedValues = explode("|", $currvalue);
1684 $currvalue = $selectedValues[0];
1686 $lrow = sqlQuery(
1687 "SELECT title FROM list_options " .
1688 "WHERE list_id = ? AND option_id = ? AND activity = 1",
1689 array($list_id,$currvalue)
1691 // For lists Race and Ethnicity if there is no matching value in the corresponding lists check ethrace list
1692 if (empty($lrow) && $data_type == 33) {
1693 $lrow = sqlQuery(
1694 "SELECT title FROM list_options " .
1695 "WHERE list_id = ? AND option_id = ? AND activity = 1",
1696 array('ethrace', $currvalue)
1700 $tmp = xl_list_label($lrow['title']);
1701 if ($lrow == 0 && !empty($backup_list)) {
1702 // since primary list did not map, try to map to backup list
1703 $lrow = sqlQuery("SELECT title FROM list_options " .
1704 "WHERE list_id = ? AND option_id = ?", array($backup_list,$currvalue));
1705 $tmp = xl_list_label($lrow['title']);
1708 if (empty($tmp)) {
1709 $tmp = "($currvalue)";
1712 if ($data_type == 46) {
1713 // support for single-selection list with comment support
1714 $resnote = $selectedValues[1] ?? null;
1715 if (!empty($resnote)) {
1716 $tmp .= " (" . $resnote . ")";
1721 if ($tmp === '') {
1722 $tmp = '&nbsp;';
1723 } else {
1724 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
1726 echo $tmp;
1727 } elseif ($data_type == 2 || $data_type == 15) { // simple text field
1728 if ($currescaped === '') {
1729 $currescaped = '&nbsp;';
1732 echo $currescaped;
1733 } elseif ($data_type == 3) { // long or multi-line text field
1734 $fldlength = htmlspecialchars($fld_length, ENT_QUOTES);
1735 $maxlength = htmlspecialchars($frow['fld_rows'], ENT_QUOTES);
1736 echo "<textarea" .
1737 " class='form-control' " .
1738 " cols='$fldlength'" .
1739 " rows='$maxlength'>" .
1740 $currescaped . "</textarea>";
1741 } elseif ($data_type == 4) { // date
1742 $age_asof_date = '';
1743 $agestr = optionalAge($frow, $currvalue, $age_asof_date, $description);
1744 if ($currvalue === '') {
1745 echo '&nbsp;';
1746 } else {
1747 $modtmp = isOption($frow['edit_options'], 'F') === false ? 0 : 1;
1748 if (!$modtmp) {
1749 echo text(oeFormatShortDate($currvalue));
1750 } else {
1751 echo text(oeFormatDateTime($currvalue));
1753 if ($agestr) {
1754 echo "&nbsp;(" . text($agestr) . ")";
1757 } elseif ($data_type == 10 || $data_type == 11) { // provider list
1758 $tmp = '';
1759 if ($currvalue) {
1760 $urow = sqlQuery("SELECT fname, lname, specialty FROM users " .
1761 "WHERE id = ?", array($currvalue));
1762 $tmp = ucwords($urow['fname'] . " " . $urow['lname']);
1763 if (empty($tmp)) {
1764 $tmp = "($currvalue)";
1767 if ($tmp === '') {
1768 $tmp = '&nbsp;';
1769 } else {
1770 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
1773 echo $tmp;
1774 } elseif ($data_type == 12) { // pharmacy list
1775 $tmp = '';
1776 if ($currvalue) {
1777 $pres = get_pharmacies();
1778 while ($prow = sqlFetchArray($pres)) {
1779 $key = $prow['id'];
1780 if ($currvalue == $key) {
1781 $tmp = $prow['name'] . ' ' . $prow['area_code'] . '-' .
1782 $prow['prefix'] . '-' . $prow['number'] . ' / ' .
1783 $prow['line1'] . ' / ' . $prow['city'];
1787 if (empty($tmp)) {
1788 $tmp = "($currvalue)";
1791 if ($tmp === '') {
1792 $tmp = '&nbsp;';
1793 } else {
1794 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
1797 echo $tmp;
1798 } elseif ($data_type == 13) { // squads
1799 $tmp = '';
1800 if ($currvalue) {
1801 $squads = AclExtended::aclGetSquads();
1802 if ($squads) {
1803 foreach ($squads as $key => $value) {
1804 if ($currvalue == $key) {
1805 $tmp = $value[3];
1810 if (empty($tmp)) {
1811 $tmp = "($currvalue)";
1814 if ($tmp === '') {
1815 $tmp = '&nbsp;';
1816 } else {
1817 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
1820 echo $tmp;
1821 } elseif ($data_type == 14) { // Address book.
1822 $tmp = '';
1823 if ($currvalue) {
1824 $urow = sqlQuery("SELECT fname, lname, specialty FROM users " .
1825 "WHERE id = ?", array($currvalue));
1826 $uname = $urow['lname'];
1827 if ($urow['fname']) {
1828 $uname .= ", " . $urow['fname'];
1831 $tmp = $uname;
1832 if (empty($tmp)) {
1833 $tmp = "($currvalue)";
1836 if ($tmp === '') {
1837 $tmp = '&nbsp;';
1838 } else {
1839 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
1842 echo $tmp;
1843 } elseif ($data_type == 16) { // insurance company list
1844 $tmp = '';
1845 if ($currvalue) {
1846 $insprovs = getInsuranceProviders();
1847 foreach ($insprovs as $key => $ipname) {
1848 if ($currvalue == $key) {
1849 $tmp = $ipname;
1853 if (empty($tmp)) {
1854 $tmp = "($currvalue)";
1858 if ($tmp === '') {
1859 $tmp = '&nbsp;';
1860 } else {
1861 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
1864 echo $tmp;
1865 } elseif ($data_type == 17) { // issue types
1866 $tmp = '';
1867 if ($currvalue) {
1868 foreach ($ISSUE_TYPES as $key => $value) {
1869 if ($currvalue == $key) {
1870 $tmp = $value[1];
1874 if (empty($tmp)) {
1875 $tmp = "($currvalue)";
1879 if ($tmp === '') {
1880 $tmp = '&nbsp;';
1881 } else {
1882 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
1885 echo $tmp;
1886 } elseif ($data_type == 18) { // Visit categories.
1887 $tmp = '';
1888 if ($currvalue) {
1889 $crow = sqlQuery(
1890 "SELECT pc_catid, pc_catname " .
1891 "FROM openemr_postcalendar_categories WHERE pc_catid = ?",
1892 array($currvalue)
1894 $tmp = xl_appt_category($crow['pc_catname']);
1895 if (empty($tmp)) {
1896 $tmp = "($currvalue)";
1900 if ($tmp === '') {
1901 $tmp = '&nbsp;';
1902 } else {
1903 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
1906 echo $tmp;
1907 } elseif ($data_type == 21) { // a single checkbox or set of labeled checkboxes
1908 if (!$list_id) {
1909 echo "<input type='checkbox'";
1910 if ($currvalue) {
1911 echo " checked";
1913 echo " />";
1914 } else {
1915 // In this special case, fld_length is the number of columns generated.
1916 $cols = max(1, $fld_length);
1917 $avalue = explode('|', $currvalue);
1918 $lres = sqlStatement("SELECT * FROM list_options " .
1919 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
1920 echo "<table class='w-100' cellpadding='0' cellspacing='0'>";
1921 $tdpct = (int) (100 / $cols);
1922 for ($count = 0; $lrow = sqlFetchArray($lres); ++$count) {
1923 $option_id = $lrow['option_id'];
1924 if ($count % $cols == 0) {
1925 if ($count) {
1926 echo "</tr>";
1929 echo "<tr>";
1931 echo "<td width='" . attr($tdpct) . "%' nowrap>";
1932 echo "<input type='checkbox'";
1933 if (in_array($option_id, $avalue)) {
1934 echo " checked";
1936 echo ">" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES);
1937 echo "</td>";
1939 if ($count) {
1940 echo "</tr>";
1941 if ($count > $cols) {
1942 // Add some space after multiple rows of checkboxes.
1943 $cols = htmlspecialchars($cols, ENT_QUOTES);
1944 echo "<tr><td colspan='$cols' style='height:0.7em'></td></tr>";
1947 echo "</table>";
1949 } elseif ($data_type == 22) { // a set of labeled text input fields
1950 $tmp = explode('|', $currvalue);
1951 $avalue = array();
1952 foreach ($tmp as $value) {
1953 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
1954 $avalue[$matches[1]] = $matches[2];
1958 $lres = sqlStatement("SELECT * FROM list_options " .
1959 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
1960 echo "<table class='table'>";
1961 while ($lrow = sqlFetchArray($lres)) {
1962 $option_id = $lrow['option_id'];
1963 $fldlength = empty($fld_length) ? 20 : $fld_length;
1964 echo "<tr><td>" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES) . "&nbsp;</td>";
1965 $fldlength = htmlspecialchars($fldlength, ENT_QUOTES);
1966 $inputValue = htmlspecialchars($avalue[$option_id], ENT_QUOTES);
1967 echo "<td><input type='text'" .
1968 " class='form-control' " .
1969 " size='$fldlength'" .
1970 " value='$inputValue'" .
1971 " class='under'" .
1972 " /></td></tr>";
1975 echo "</table>";
1976 } elseif ($data_type == 23) { // a set of exam results; 3 radio buttons and a text field:
1977 $tmp = explode('|', $currvalue);
1978 $avalue = array();
1979 foreach ($tmp as $value) {
1980 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
1981 $avalue[$matches[1]] = $matches[2];
1985 $fldlength = empty($fld_length) ? 20 : $fld_length;
1986 $lres = sqlStatement("SELECT * FROM list_options " .
1987 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
1988 echo "<table class='table'>";
1989 echo "<tr><td>&nbsp;</td><td class='font-weight-bold'>" .
1990 htmlspecialchars(xl('N/A'), ENT_NOQUOTES) .
1991 "&nbsp;</td><td class='font-weight-bold'>" .
1992 htmlspecialchars(xl('Nor'), ENT_NOQUOTES) . "&nbsp;</td>" .
1993 "<td class='font-weight-bold'>" .
1994 htmlspecialchars(xl('Abn'), ENT_NOQUOTES) . "&nbsp;</td><td class='font-weight-bold'>" .
1995 htmlspecialchars(xl('Date/Notes'), ENT_NOQUOTES) . "</td></tr>";
1996 while ($lrow = sqlFetchArray($lres)) {
1997 $option_id = $lrow['option_id'];
1998 $restype = substr($avalue[$option_id], 0, 1);
1999 $resnote = substr($avalue[$option_id], 2);
2000 echo "<tr><td>" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES) . "&nbsp;</td>";
2001 for ($i = 0; $i < 3; ++$i) {
2002 echo "<td><input type='radio'";
2003 if ($restype === "$i") {
2004 echo " checked";
2007 echo " /></td>";
2010 $resnote = htmlspecialchars($resnote, ENT_QUOTES);
2011 $fldlength = htmlspecialchars($fldlength, ENT_QUOTES);
2012 echo "<td><input type='text'" .
2013 " size='$fldlength'" .
2014 " value='$resnote'" .
2015 " class='under form-control' /></td>" .
2016 "</tr>";
2019 echo "</table>";
2020 } elseif ($data_type == 24) { // the list of active allergies for the current patient
2021 // this is read-only!
2022 $query = "SELECT title, comments FROM lists WHERE " .
2023 "pid = ? AND type = 'allergy' AND enddate IS NULL " .
2024 "ORDER BY begdate";
2025 $lres = sqlStatement($query, array($GLOBALS['pid']));
2026 $count = 0;
2027 while ($lrow = sqlFetchArray($lres)) {
2028 if ($count++) {
2029 echo "<br />";
2032 echo htmlspecialchars($lrow['title'], ENT_QUOTES);
2033 if ($lrow['comments']) {
2034 echo htmlspecialchars(' (' . $lrow['comments'] . ')', ENT_QUOTES);
2037 } elseif ($data_type == 25) { // a set of labeled checkboxes, each with a text field:
2038 $tmp = explode('|', $currvalue);
2039 $avalue = array();
2040 foreach ($tmp as $value) {
2041 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
2042 $avalue[$matches[1]] = $matches[2];
2046 $fldlength = empty($fld_length) ? 20 : $fld_length;
2047 $lres = sqlStatement("SELECT * FROM list_options " .
2048 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
2049 echo "<table class='table'>";
2050 while ($lrow = sqlFetchArray($lres)) {
2051 $option_id = $lrow['option_id'];
2052 $restype = substr($avalue[$option_id], 0, 1);
2053 $resnote = substr($avalue[$option_id], 2);
2054 echo "<tr><td>" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES) . "&nbsp;</td>";
2055 echo "<td><input type='checkbox'";
2056 if ($restype) {
2057 echo " checked";
2060 echo " />&nbsp;</td>";
2061 $fldlength = htmlspecialchars($fldlength, ENT_QUOTES);
2062 $resnote = htmlspecialchars($resnote, ENT_QUOTES);
2063 echo "<td><input type='text'" .
2064 " size='$fldlength'" .
2065 " class='form-control' " .
2066 " value='$resnote'" .
2067 " class='under'" .
2068 " /></td>" .
2069 "</tr>";
2072 echo "</table>";
2073 } elseif ($data_type == 27) { // Removed: || $data_type == 1 || $data_type == 26 || $data_type == 33
2074 // a set of labeled radio buttons
2075 // In this special case, fld_length is the number of columns generated.
2077 $cols = max(1, ($frow['fld_length'] ?? null));
2078 $lres = sqlStatement("SELECT * FROM list_options " .
2079 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
2080 echo "<table class='w-100' cellpadding='0' cellspacing='0'>";
2081 $tdpct = (int) (100 / $cols);
2082 for ($count = 0; $lrow = sqlFetchArray($lres); ++$count) {
2083 $option_id = $lrow['option_id'];
2084 if ($count % $cols == 0) {
2085 if ($count) {
2086 echo "</tr>";
2088 echo "<tr>";
2090 echo "<td width='" . attr($tdpct) . "%' nowrap>";
2091 echo "<input type='radio'";
2092 if (strlen($currvalue) > 0 && $option_id == $currvalue) {
2093 // Do not use defaults for these printable forms.
2094 echo " checked";
2096 echo ">" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES);
2097 echo "</td>";
2099 if ($count) {
2100 echo "</tr>";
2101 if ($count > $cols) {
2102 // Add some space after multiple rows of radio buttons.
2103 $cols = htmlspecialchars($cols, ENT_QUOTES);
2104 echo "<tr><td colspan='$cols' style='height:0.7em'></td></tr>";
2107 echo "</table>";
2109 // special case for history of lifestyle status; 3 radio buttons and a date text field:
2110 } elseif ($data_type == 28 || $data_type == 32) {
2111 $tmp = explode('|', $currvalue);
2112 switch (count($tmp)) {
2113 case "4":
2114 $resnote = $tmp[0];
2115 $restype = $tmp[1];
2116 $resdate = oeFormatShortDate($tmp[2]) ;
2117 $reslist = $tmp[3];
2118 break;
2119 case "3":
2120 $resnote = $tmp[0];
2121 $restype = $tmp[1];
2122 $resdate = oeFormatShortDate($tmp[2]);
2123 $reslist = '';
2124 break;
2125 case "2":
2126 $resnote = $tmp[0];
2127 $restype = $tmp[1];
2128 $resdate = "";
2129 $reslist = '';
2130 break;
2131 case "1":
2132 $resnote = $tmp[0];
2133 $resdate = $restype = "";
2134 $reslist = '';
2135 break;
2136 default:
2137 $restype = $resdate = $resnote = "";
2138 $reslist = '';
2139 break;
2142 $fldlength = empty($frow['fld_length']) ? 20 : $frow['fld_length'];
2143 echo "<table class='table'>";
2144 echo "<tr>";
2145 $fldlength = htmlspecialchars($fldlength, ENT_QUOTES);
2146 $resnote = htmlspecialchars($resnote, ENT_QUOTES);
2147 $resdate = htmlspecialchars($resdate, ENT_QUOTES);
2148 if ($data_type == 28) {
2149 echo "<td><input type='text'" .
2150 " size='$fldlength'" .
2151 " class='under'" .
2152 " value='$resnote' /></td>";
2153 echo "<td class='font-weight-bold'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" .
2154 "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" .
2155 htmlspecialchars(xl('Status'), ENT_NOQUOTES) . ":&nbsp;</td>";
2156 } elseif ($data_type == 32) {
2157 echo "<tr><td><input type='text'" .
2158 " size='$fldlength'" .
2159 " class='under form-control'" .
2160 " value='$resnote' /></td></tr>";
2161 $fldlength = 30;
2162 $smoking_status_title = generate_display_field(array('data_type' => '1','list_id' => $list_id), $reslist);
2163 echo "<td><input type='text'" .
2164 " size='$fldlength'" .
2165 " class='under form-control'" .
2166 " value='$smoking_status_title' /></td>";
2167 echo "<td class='font-weight-bold'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" . htmlspecialchars(xl('Status'), ENT_NOQUOTES) . ":&nbsp;&nbsp;</td>";
2170 echo "<td><input type='radio' class='form-check-inline'";
2171 if ($restype == "current" . $field_id) {
2172 echo " checked";
2175 echo "/>" . htmlspecialchars(xl('Current'), ENT_NOQUOTES) . "&nbsp;</td>";
2177 echo "<td><input type='radio' class='form-check-inline'";
2178 if ($restype == "current" . $field_id) {
2179 echo " checked";
2182 echo "/>" . htmlspecialchars(xl('Quit'), ENT_NOQUOTES) . "&nbsp;</td>";
2184 echo "<td><input type='text' size='6'" .
2185 " value='$resdate'" .
2186 " class='under form-control'" .
2187 " /></td>";
2189 echo "<td><input type='radio' class='form-check-inline'";
2190 if ($restype == "current" . $field_id) {
2191 echo " checked";
2194 echo " />" . htmlspecialchars(xl('Never'), ENT_NOQUOTES) . "</td>";
2196 echo "<td><input type='radio' class='form-check-inline'";
2197 if ($restype == "not_applicable" . $field_id) {
2198 echo " checked";
2201 echo " />" . htmlspecialchars(xl('N/A'), ENT_NOQUOTES) . "&nbsp;</td>";
2202 echo "</tr>";
2203 echo "</table>";
2204 } elseif ($data_type == 31) { // static text. read-only, of course.
2205 echo parse_static_text($frow, $value_allowed);
2206 } elseif ($data_type == 34) {
2207 echo "<a href='../../../library/custom_template/custom_template.php?type=form_{$field_id}&contextName=" . htmlspecialchars($list_id_esc, ENT_QUOTES) . "' class='iframe_medium text-body text-decoration-none'>";
2208 echo "<div id='form_{$field_id}_div' class='text-area'></div>";
2209 echo "<div style='display: none'><textarea name='form_{$field_id}' class='form-control' id='form_{$field_id}' style='display: none'></textarea></div>";
2210 echo "</a>";
2212 // Facilities. Changed 2017-12-15 to not show the choices.
2213 } elseif ($data_type == 35) {
2214 $urow = sqlQuery(
2215 "SELECT id, name FROM facility WHERE id = ?",
2216 array($currvalue)
2218 echo empty($urow['id']) ? '&nbsp;' : text($urow['name']);
2219 } elseif ($data_type == 36) { //Multi-select. Supports backup lists.
2220 if (empty($fld_length)) {
2221 if ($list_id == 'titles') {
2222 $fld_length = 3;
2223 } else {
2224 $fld_length = 10;
2228 $tmp = '';
2230 $values_array = explode("|", $currvalue);
2232 $i = 0;
2233 foreach ($values_array as $value) {
2234 if ($value) {
2235 $lrow = sqlQuery("SELECT title FROM list_options " .
2236 "WHERE list_id = ? AND option_id = ? AND activity = 1", array($list_id,$value));
2237 $tmp = xl_list_label($lrow['title']);
2238 if ($lrow == 0 && !empty($backup_list)) {
2239 // since primary list did not map, try to map to backup list
2240 $lrow = sqlQuery("SELECT title FROM list_options " .
2241 "WHERE list_id = ? AND option_id = ? AND activity = 1", array($backup_list,$currvalue));
2242 $tmp = xl_list_label($lrow['title']);
2245 if (empty($tmp)) {
2246 $tmp = "($value)";
2250 if ($tmp === '') {
2251 $tmp = '&nbsp;';
2252 } else {
2253 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
2256 if ($i != 0 && $tmp != '&nbsp;') {
2257 echo ",";
2260 echo $tmp;
2261 $i++;
2264 // A set of lab test results; Gestation, 3 radio buttons, test value, notes field:
2265 } elseif ($data_type == 37) {
2266 echo genLabResults($frow, $currvalue, 1, $disabled);
2267 } elseif ($data_type == 40) { // Image from canvas drawing
2268 if (empty($currvalue)) {
2269 if (preg_match('/\\bimage=([a-zA-Z0-9._-]*)/', $frow['description'], $matches)) {
2270 $currvalue = $GLOBALS['web_root'] . '/sites/' . $_SESSION['site_id'] . '/images/' . $matches[1];
2273 if ($currvalue) {
2274 echo "<img src='" . attr($currvalue) . "'>";
2276 } elseif ($data_type == 41 || $data_type == 42) {
2277 if ($currvalue) {
2278 echo "<img class='w-auto' style='height: 70px;' src='" . attr($currvalue) . "'>";
2280 } elseif ($data_type == 44 || $data_type == 45) {
2281 $tmp = '';
2283 $values_array = explode("|", $currvalue);
2285 $i = 0;
2286 foreach ($values_array as $value) {
2287 if ($value) {
2288 if ($data_type == 44) {
2289 $lrow = sqlQuery("SELECT name as name FROM facility WHERE id = ?", array($value));
2291 if ($data_type == 45) {
2292 $lrow = sqlQuery("SELECT CONCAT(fname,' ',lname) as name FROM users WHERE id = ?", array($value));
2294 $tmp = $lrow['name'];
2297 if ($tmp === '') {
2298 $tmp = '&nbsp;';
2299 } else {
2300 $tmp = htmlspecialchars($tmp, ENT_QUOTES);
2303 if ($i != 0 && $tmp != '&nbsp;') {
2304 echo ",";
2307 echo $tmp;
2308 $i++;
2311 // Patient selector field.
2312 } else if ($data_type == 51) {
2313 if (!empty($currvalue)) {
2314 $tmp = text(getPatientDescription($currvalue));
2315 } else {
2316 echo '&nbsp;';
2322 * @param $list_id
2323 * @param bool $translate
2324 * @return array
2326 * Generate a key-value array containing each row of the specified list,
2327 * with the option ID as the index, and the title as the element
2329 * Pass in the list_id to specify this list.
2331 * Use the translate flag to run the title element through the translator
2333 function generate_list_map($list_id, $translate = false)
2335 $result = sqlStatement("SELECT option_id, title FROM list_options WHERE list_id = ?", [$list_id]);
2336 $map = [];
2337 while ($row = sqlFetchArray($result)) {
2338 if ($translate === true) {
2339 $title = xl_list_label($row['title']);
2340 } else {
2341 $title = $row['title'];
2343 $map[$row['option_id']] = $title;
2346 return $map;
2349 function generate_display_field($frow, $currvalue)
2351 global $ISSUE_TYPES, $facilityService;
2353 $data_type = $frow['data_type'];
2354 $field_id = isset($frow['field_id']) ? $frow['field_id'] : null;
2355 $list_id = $frow['list_id'];
2356 $backup_list = isset($frow['list_backup_id']) ? $frow['list_backup_id'] : null;
2358 $s = '';
2360 // generic selection list or the generic selection list with add on the fly
2361 // feature
2362 if ($data_type == 1 || $data_type == 26 || $data_type == 43 || $data_type == 46) {
2363 if ($data_type == 46) {
2364 // support for single-selection list with comment support
2365 $selectedValues = explode("|", $currvalue);
2366 $currvalue = $selectedValues[0];
2369 $lrow = sqlQuery("SELECT title FROM list_options " .
2370 "WHERE list_id = ? AND option_id = ? AND activity = 1", array($list_id,$currvalue));
2371 $s = htmlspecialchars(xl_list_label($lrow['title'] ?? ''), ENT_NOQUOTES);
2372 //if there is no matching value in the corresponding lists check backup list
2373 // only supported in data types 1,26,43,46
2374 if ($lrow == 0 && !empty($backup_list) && ($data_type == 1 || $data_type == 26 || $$data_type == 43 || $data_type == 46)) {
2375 $lrow = sqlQuery("SELECT title FROM list_options " .
2376 "WHERE list_id = ? AND option_id = ? AND activity = 1", array($backup_list,$currvalue));
2377 $s = htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES);
2380 // If match is not found in main and backup lists, return the key with exclamation mark
2381 if ($s == '') {
2382 $s = nl2br(text(xl_list_label($currvalue))) .
2383 '<span> <i class="fa fas fa-exclamation-circle ml-1"></i></span>';
2386 if ($data_type == 46) {
2387 // support for single-selection list with comment support
2388 $resnote = $selectedValues[1] ?? null;
2389 if (!empty($resnote)) {
2390 $s .= " (" . text($resnote) . ")";
2393 } elseif ($data_type == 2) { // simple text field
2394 $s = nl2br(htmlspecialchars($currvalue, ENT_NOQUOTES));
2395 } elseif ($data_type == 3) { // long or multi-line text field
2396 $s = nl2br(htmlspecialchars($currvalue, ENT_NOQUOTES));
2397 } elseif ($data_type == 4) { // date
2398 $asof = ''; //not used here, but set to prevent a php warning when call optionalAge
2399 $s = '';
2400 $description = (isset($frow['description']) ? htmlspecialchars(xl_layout_label($frow['description']), ENT_QUOTES) : '');
2401 $age_asof_date = '';
2402 $agestr = optionalAge($frow, $currvalue, $age_asof_date, $description);
2403 if ($currvalue === '') {
2404 $s .= '&nbsp;';
2405 } else {
2406 $modtmp = isOption($frow['edit_options'], 'F') === false ? 0 : 1;
2407 if (!$modtmp) {
2408 $s .= text(oeFormatShortDate($currvalue));
2409 } else {
2410 $s .= text(oeFormatDateTime($currvalue));
2412 if ($agestr) {
2413 $s .= "&nbsp;(" . text($agestr) . ")";
2416 } elseif ($data_type == 10 || $data_type == 11) { // provider
2417 $urow = sqlQuery("SELECT fname, lname, specialty FROM users " .
2418 "WHERE id = ?", array($currvalue));
2419 $s = text(ucwords(($urow['fname'] ?? '') . " " . ($urow['lname'] ?? '')));
2420 } elseif ($data_type == 12) { // pharmacy list
2421 $pres = get_pharmacies();
2422 while ($prow = sqlFetchArray($pres)) {
2423 $key = $prow['id'];
2424 if ($currvalue == $key) {
2425 $s .= htmlspecialchars($prow['name'] . ' ' . $prow['area_code'] . '-' .
2426 $prow['prefix'] . '-' . $prow['number'] . ' / ' .
2427 $prow['line1'] . ' / ' . $prow['city'], ENT_NOQUOTES);
2430 } elseif ($data_type == 13) { // squads
2431 $squads = AclExtended::aclGetSquads();
2432 if ($squads) {
2433 foreach ($squads as $key => $value) {
2434 if ($currvalue == $key) {
2435 $s .= htmlspecialchars($value[3], ENT_NOQUOTES);
2439 } elseif ($data_type == 14) { // address book
2440 $urow = sqlQuery("SELECT fname, lname, specialty, organization FROM users " .
2441 "WHERE id = ?", array($currvalue));
2442 //ViSolve: To display the Organization Name if it exist. Else it will display the user name.
2443 if ($urow['organization'] != "") {
2444 $uname = $urow['organization'];
2445 } else {
2446 $uname = $urow['lname'];
2447 if ($urow['fname']) {
2448 $uname .= ", " . $urow['fname'];
2452 $s = htmlspecialchars($uname, ENT_NOQUOTES);
2453 } elseif ($data_type == 15) { // billing code
2454 $s = '';
2455 if (!empty($currvalue)) {
2456 $relcodes = explode(';', $currvalue);
2457 foreach ($relcodes as $codestring) {
2458 if ($codestring === '') {
2459 continue;
2461 $tmp = lookup_code_descriptions($codestring);
2462 if ($s !== '') {
2463 $s .= '; ';
2465 if (!empty($tmp)) {
2466 $s .= text($tmp);
2467 } else {
2468 $s .= text($codestring) . ' (' . xlt('not found') . ')';
2472 } elseif ($data_type == 16) { // insurance company list
2473 $insprovs = getInsuranceProviders();
2474 foreach ($insprovs as $key => $ipname) {
2475 if ($currvalue == $key) {
2476 $s .= htmlspecialchars($ipname, ENT_NOQUOTES);
2479 } elseif ($data_type == 17) { // issue types
2480 foreach ($ISSUE_TYPES as $key => $value) {
2481 if ($currvalue == $key) {
2482 $s .= htmlspecialchars($value[1], ENT_NOQUOTES);
2485 } elseif ($data_type == 18) { // visit category
2486 $crow = sqlQuery(
2487 "SELECT pc_catid, pc_catname " .
2488 "FROM openemr_postcalendar_categories WHERE pc_catid = ?",
2489 array($currvalue)
2491 $s = htmlspecialchars($crow['pc_catname'], ENT_NOQUOTES);
2492 } elseif ($data_type == 21) { // a single checkbox or set of labeled checkboxes
2493 if (!$list_id) {
2494 $s .= $currvalue ? '[ x ]' : '[ &nbsp;&nbsp; ]';
2495 } else {
2496 // In this special case, fld_length is the number of columns generated.
2497 $cols = max(1, $frow['fld_length']);
2498 $avalue = explode('|', $currvalue);
2499 $lres = sqlStatement("SELECT * FROM list_options " .
2500 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
2501 $s .= "<table cellspacing='0' cellpadding='0'>";
2502 for ($count = 0; $lrow = sqlFetchArray($lres); ++$count) {
2503 $option_id = $lrow['option_id'];
2504 $option_id_esc = text($option_id);
2505 if ($count % $cols == 0) {
2506 if ($count) {
2507 $s .= "</tr>";
2509 $s .= "<tr>";
2511 $s .= "<td nowrap>";
2512 $checked = in_array($option_id, $avalue);
2513 $s .= $checked ? '[ x ]' : '[ &nbsp;&nbsp; ]';
2514 $s .= '&nbsp;' . text(xl_list_label($lrow['title'])) . '&nbsp;&nbsp;';
2515 $s .= "</td>";
2517 if ($count) {
2518 $s .= "</tr>";
2520 $s .= "</table>";
2522 } elseif ($data_type == 22) { // a set of labeled text input fields
2523 $tmp = explode('|', $currvalue);
2524 $avalue = array();
2525 foreach ($tmp as $value) {
2526 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
2527 $avalue[$matches[1]] = $matches[2];
2531 $lres = sqlStatement("SELECT * FROM list_options " .
2532 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
2533 $s .= "<table class='table'>";
2534 while ($lrow = sqlFetchArray($lres)) {
2535 $option_id = $lrow['option_id'];
2536 if (empty($avalue[$option_id])) {
2537 continue;
2540 // Added 5-09 by BM - Translate label if applicable
2541 $s .= "<tr><td class='font-weight-bold align-top'>" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES) . ":&nbsp;</td>";
2543 $s .= "<td class='text align-top'>" . htmlspecialchars($avalue[$option_id], ENT_NOQUOTES) . "</td></tr>";
2546 $s .= "</table>";
2547 } elseif ($data_type == 23) { // a set of exam results; 3 radio buttons and a text field:
2548 $tmp = explode('|', $currvalue);
2549 $avalue = array();
2550 foreach ($tmp as $value) {
2551 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
2552 $avalue[$matches[1]] = $matches[2];
2556 $lres = sqlStatement("SELECT * FROM list_options " .
2557 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
2558 $s .= "<table class='table'>";
2559 while ($lrow = sqlFetchArray($lres)) {
2560 $option_id = $lrow['option_id'];
2561 $restype = substr(($avalue[$option_id] ?? ''), 0, 1);
2562 $resnote = substr(($avalue[$option_id] ?? ''), 2);
2563 if (empty($restype) && empty($resnote)) {
2564 continue;
2567 // Added 5-09 by BM - Translate label if applicable
2568 $s .= "<tr><td class='font-weight-bold align-top'>" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES) . "&nbsp;</td>";
2570 $restype = ($restype == '1') ? xl('Normal') : (($restype == '2') ? xl('Abnormal') : xl('N/A'));
2571 // $s .= "<td class='text align-top'>$restype</td></tr>";
2572 // $s .= "<td class='text align-top'>$resnote</td></tr>";
2573 $s .= "<td class='text align-top'>" . htmlspecialchars($restype, ENT_NOQUOTES) . "&nbsp;</td>";
2574 $s .= "<td class='text align-top'>" . htmlspecialchars($resnote, ENT_NOQUOTES) . "</td>";
2575 $s .= "</tr>";
2578 $s .= "</table>";
2579 } elseif ($data_type == 24) { // the list of active allergies for the current patient
2580 $query = "SELECT title, comments FROM lists WHERE " .
2581 "pid = ? AND type = 'allergy' AND enddate IS NULL " .
2582 "ORDER BY begdate";
2583 // echo "<!-- $query -->\n"; // debugging
2584 $lres = sqlStatement($query, array($GLOBALS['pid']));
2585 $count = 0;
2586 while ($lrow = sqlFetchArray($lres)) {
2587 if ($count++) {
2588 $s .= "<br />";
2591 $s .= htmlspecialchars($lrow['title'], ENT_NOQUOTES);
2592 if ($lrow['comments']) {
2593 $s .= ' (' . htmlspecialchars($lrow['comments'], ENT_NOQUOTES) . ')';
2596 } elseif ($data_type == 25) { // a set of labeled checkboxes, each with a text field:
2597 $tmp = explode('|', $currvalue);
2598 $avalue = array();
2599 foreach ($tmp as $value) {
2600 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
2601 $avalue[$matches[1]] = $matches[2];
2605 $lres = sqlStatement("SELECT * FROM list_options " .
2606 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
2607 $s .= "<table class='table'>";
2608 while ($lrow = sqlFetchArray($lres)) {
2609 $option_id = $lrow['option_id'];
2610 $restype = substr($avalue[$option_id], 0, 1);
2611 $resnote = substr($avalue[$option_id], 2);
2612 if (empty($restype) && empty($resnote)) {
2613 continue;
2616 // Added 5-09 by BM - Translate label if applicable
2617 $s .= "<tr><td class='font-weight-bold align-top'>" . htmlspecialchars(xl_list_label($lrow['title']), ENT_NOQUOTES) . "&nbsp;</td>";
2619 $restype = $restype ? xl('Yes') : xl('No');
2620 $s .= "<td class='text align-top'>" . htmlspecialchars($restype, ENT_NOQUOTES) . "&nbsp;</td>";
2621 $s .= "<td class='text align-top'>" . htmlspecialchars($resnote, ENT_NOQUOTES) . "</td>";
2622 $s .= "</tr>";
2625 $s .= "</table>";
2626 } elseif ($data_type == 27) { // a set of labeled radio buttons
2627 // In this special case, fld_length is the number of columns generated.
2628 $cols = max(1, $frow['fld_length']);
2629 $lres = sqlStatement("SELECT * FROM list_options " .
2630 "WHERE list_id = ? ORDER BY seq, title", array($list_id));
2631 $s .= "<table cellspacing='0' cellpadding='0'>";
2632 for ($count = 0; $lrow = sqlFetchArray($lres); ++$count) {
2633 $option_id = $lrow['option_id'];
2634 $option_id_esc = text($option_id);
2635 if ($count % $cols == 0) {
2636 if ($count) {
2637 $s .= "</tr>";
2639 $s .= "<tr>";
2641 $s .= "<td nowrap>";
2642 $checked = ((strlen($currvalue) == 0 && $lrow['is_default']) ||
2643 (strlen($currvalue) > 0 && $option_id == $currvalue));
2644 $s .= $checked ? '[ x ]' : '[ &nbsp;&nbsp; ]';
2645 $s .= '&nbsp;' . text(xl_list_label($lrow['title'])) . '&nbsp;&nbsp;';
2646 $s .= "</td>";
2648 if ($count) {
2649 $s .= "</tr>";
2651 $s .= "</table>";
2652 } elseif ($data_type == 28 || $data_type == 32) { // special case for history of lifestyle status; 3 radio buttons
2653 // and a date text field:
2654 // VicarePlus :: A selection list for smoking status.
2655 $tmp = explode('|', $currvalue);
2656 switch (count($tmp)) {
2657 case "4":
2658 $resnote = $tmp[0];
2659 $restype = $tmp[1];
2660 $resdate = oeFormatShortDate($tmp[2]);
2661 $reslist = $tmp[3];
2662 break;
2663 case "3":
2664 $resnote = $tmp[0];
2665 $restype = $tmp[1];
2666 $resdate = oeFormatShortDate($tmp[2]);
2667 $reslist = '';
2668 break;
2669 case "2":
2670 $resnote = $tmp[0];
2671 $restype = $tmp[1];
2672 $resdate = "";
2673 $reslist = '';
2674 break;
2675 case "1":
2676 $resnote = $tmp[0];
2677 $resdate = $restype = "";
2678 $reslist = '';
2679 break;
2680 default:
2681 $restype = $resdate = $resnote = "";
2682 $reslist = '';
2683 break;
2686 $s .= "<table class='table'>";
2688 $s .= "<tr>";
2689 $res = "";
2690 if ($restype == "current" . $field_id) {
2691 $res = xl('Current');
2694 if ($restype == "quit" . $field_id) {
2695 $res = xl('Quit');
2698 if ($restype == "never" . $field_id) {
2699 $res = xl('Never');
2702 if ($restype == "not_applicable" . $field_id) {
2703 $res = xl('N/A');
2706 // $s .= "<td class='text align-top'>$restype</td></tr>";
2707 // $s .= "<td class='text align-top'>$resnote</td></tr>";
2708 if ($data_type == 28) {
2709 if (!empty($resnote)) {
2710 $s .= "<td class='text align-top'>" . htmlspecialchars($resnote, ENT_NOQUOTES) . "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>";
2712 } elseif ($data_type == 32) { //VicarePlus :: Tobacco field has a listbox, text box, date field and 3 radio buttons.
2713 // changes on 5-jun-2k14 (regarding 'Smoking Status - display SNOMED code description')
2714 $smoke_codes = getSmokeCodes();
2715 if (!empty($reslist)) {
2716 if ($smoke_codes[$reslist] != "") {
2717 $code_desc = "( " . $smoke_codes[$reslist] . " )";
2720 $s .= "<td class='text align-top'>" . generate_display_field(array('data_type' => '1','list_id' => $list_id), $reslist) . "&nbsp;" . text($code_desc) . "&nbsp;&nbsp;&nbsp;&nbsp;</td>";
2723 if (!empty($resnote)) {
2724 $s .= "<td class='text align-top'>" . htmlspecialchars($resnote, ENT_NOQUOTES) . "&nbsp;&nbsp;</td>";
2728 if (!empty($res)) {
2729 $s .= "<td class='text align-top'><strong>" . htmlspecialchars(xl('Status'), ENT_NOQUOTES) . "</strong>:&nbsp;" . htmlspecialchars($res, ENT_NOQUOTES) . "&nbsp;</td>";
2732 if ($restype == "quit" . $field_id) {
2733 $s .= "<td class='text align-top'>" . htmlspecialchars($resdate, ENT_NOQUOTES) . "&nbsp;</td>";
2736 $s .= "</tr>";
2737 $s .= "</table>";
2738 } elseif ($data_type == 31) { // static text. read-only, of course.
2739 $s .= parse_static_text($frow);
2740 } elseif ($data_type == 34) {
2741 $arr = explode("|*|*|*|", $currvalue);
2742 for ($i = 0; $i < sizeof($arr); $i++) {
2743 $s .= $arr[$i];
2745 } elseif ($data_type == 35) { // facility
2746 $urow = $facilityService->getById($currvalue);
2747 $s = htmlspecialchars($urow['name'], ENT_NOQUOTES);
2748 } elseif ($data_type == 36 || $data_type == 33) { // Multi select. Supports backup lists
2749 $values_array = explode("|", $currvalue);
2750 $i = 0;
2751 foreach ($values_array as $value) {
2752 $lrow = sqlQuery("SELECT title FROM list_options " .
2753 "WHERE list_id = ? AND option_id = ? AND activity = 1", array($list_id,$value));
2754 if ($lrow == 0 && !empty($backup_list)) {
2755 //use back up list
2756 $lrow = sqlQuery("SELECT title FROM list_options " .
2757 "WHERE list_id = ? AND option_id = ? AND activity = 1", array($backup_list,$value));
2760 $title = $lrow['title'] ?? '';
2761 if ($i > 0) {
2762 $s = $s . ", " . text(xl_list_label($title));
2763 } else {
2764 $s = text(xl_list_label($title));
2767 $i++;
2770 // A set of lab test results; Gestation, 3 radio buttons, test value, notes field:
2771 } elseif ($data_type == 37) {
2772 $s .= genLabResults($frow, $currvalue, 2, '');
2773 } elseif ($data_type == 40) { // Image from canvas drawing
2774 if (empty($currvalue)) {
2775 if (preg_match('/\\bimage=([a-zA-Z0-9._-]*)/', $frow['description'], $matches)) {
2776 $currvalue = $GLOBALS['web_root'] . '/sites/' . $_SESSION['site_id'] . '/images/' . $matches[1];
2779 if ($currvalue) {
2780 $s .= "<img src='" . attr($currvalue) . "'>";
2782 } elseif ($data_type == 41 || $data_type == 42) {
2783 if ($currvalue) {
2784 $s .= "<img class='w-auto' style='height: 70px;' src='" . attr($currvalue) . "'>";
2786 } elseif ($data_type == 44 || $data_type == 45) { // Multiple select facility and provider
2787 $values_array = explode("|", $currvalue);
2788 $i = 0;
2789 foreach ($values_array as $value) {
2790 if ($data_type == 44) {
2791 $lrow = sqlQuery("SELECT name as name FROM facility WHERE id = ?", array($value));
2793 if ($data_type == 45) {
2794 $lrow = sqlQuery("SELECT CONCAT(fname,' ',lname) as name FROM users WHERE id = ?", array($value));
2796 if ($i > 0) {
2797 $s = $s . ", " . htmlspecialchars($lrow['name'], ENT_NOQUOTES);
2798 } else {
2799 $s = text($lrow['name'] ?? '');
2801 $i++;
2804 // Patient selector field.
2805 } else if ($data_type == 51) {
2806 if (!empty($currvalue)) {
2807 $s .= text(getPatientDescription($currvalue));
2811 return $s;
2814 // Generate plain text versions of selected LBF field types.
2815 // Currently used by interface/patient_file/download_template.php and interface/main/finder/dynamic_finder_ajax.php.
2816 // More field types might need to be supported here in the future.
2818 function generate_plaintext_field($frow, $currvalue)
2820 global $ISSUE_TYPES;
2822 $data_type = $frow['data_type'];
2823 $field_id = isset($frow['field_id']) ? $frow['field_id'] : null;
2824 $list_id = $frow['list_id'];
2825 $backup_list = $frow['backup_list'] ?? null;
2826 $edit_options = $frow['edit_options'] ?? null;
2827 $s = '';
2829 // generic selection list or the generic selection list with add on the fly
2830 // feature, or radio buttons
2831 // Supports backup lists (for datatypes 1,26,43)
2832 if ($data_type == 1 || $data_type == 26 || $data_type == 27 || $data_type == 43 || $data_type == 46) {
2833 if ($data_type == 46) {
2834 // support for single-selection list with comment support
2835 $selectedValues = explode("|", $currvalue);
2836 $currvalue = $selectedValues[0];
2839 $lrow = sqlQuery(
2840 "SELECT title FROM list_options " .
2841 "WHERE list_id = ? AND option_id = ? AND activity = 1",
2842 array($list_id, $currvalue)
2844 $s = xl_list_label($lrow['title']);
2845 //if there is no matching value in the corresponding lists check backup list
2846 // only supported in data types 1,26,43
2847 if ($lrow == 0 && !empty($backup_list) && ($data_type == 1 || $data_type == 26 || $data_type == 43 || $data_type == 46)) {
2848 $lrow = sqlQuery("SELECT title FROM list_options " .
2849 "WHERE list_id = ? AND option_id = ? AND activity = 1", array($backup_list, $currvalue));
2850 $s = xl_list_label($lrow['title']);
2853 if ($data_type == 46) {
2854 // support for single-selection list with comment support
2855 $resnote = $selectedValues[1] ?? null;
2856 if (!empty($resnote)) {
2857 $s .= " (" . $resnote . ")";
2860 } elseif ($data_type == 2 || $data_type == 3 || $data_type == 15) { // simple or long text field
2861 $s = $currvalue;
2862 } elseif ($data_type == 4) { // date
2863 $modtmp = isOption($edit_options, 'F') === false ? 0 : 1;
2864 if (!$modtmp) {
2865 $s = text(oeFormatShortDate($currvalue));
2866 } else {
2867 $s = text(oeFormatDateTime($currvalue));
2869 $description = (isset($frow['description']) ? htmlspecialchars(xl_layout_label($frow['description']), ENT_QUOTES) : '');
2870 $age_asof_date = '';
2871 // Optional display of age or gestational age.
2872 $tmp = optionalAge($frow, $currvalue, $age_asof_date, $description);
2873 if ($tmp) {
2874 $s .= ' ' . $tmp;
2876 } elseif ($data_type == 10 || $data_type == 11) { // provider
2877 $urow = sqlQuery("SELECT fname, lname, specialty FROM users " .
2878 "WHERE id = ?", array($currvalue));
2879 $s = ucwords($urow['fname'] . " " . $urow['lname']);
2880 } elseif ($data_type == 12) { // pharmacy list
2881 $pres = get_pharmacies();
2882 while ($prow = sqlFetchArray($pres)) {
2883 $key = $prow['id'];
2884 if ($currvalue == $key) {
2885 $s .= $prow['name'] . ' ' . $prow['area_code'] . '-' .
2886 $prow['prefix'] . '-' . $prow['number'] . ' / ' .
2887 $prow['line1'] . ' / ' . $prow['city'];
2890 } elseif ($data_type == 14) { // address book
2891 $urow = sqlQuery("SELECT fname, lname, specialty FROM users " .
2892 "WHERE id = ?", array($currvalue));
2893 $uname = $urow['lname'];
2894 if ($urow['fname']) {
2895 $uname .= ", " . $urow['fname'];
2898 $s = $uname;
2899 } elseif ($data_type == 16) { // insurance company list
2900 $insprovs = getInsuranceProviders();
2901 foreach ($insprovs as $key => $ipname) {
2902 if ($currvalue == $key) {
2903 $s .= $ipname;
2906 } elseif ($data_type == 17) { // issue type
2907 foreach ($ISSUE_TYPES as $key => $value) {
2908 if ($currvalue == $key) {
2909 $s .= $value[1];
2912 } elseif ($data_type == 18) { // visit category
2913 $crow = sqlQuery(
2914 "SELECT pc_catid, pc_catname " .
2915 "FROM openemr_postcalendar_categories WHERE pc_catid = ?",
2916 array($currvalue)
2918 $s = $crow['pc_catname'];
2919 } elseif ($data_type == 21) { // a set of labeled checkboxes
2920 if (!$list_id) {
2921 $s .= $currvalue ? xlt('Yes') : xlt('No');
2922 } else {
2923 $avalue = explode('|', $currvalue);
2924 $lres = sqlStatement("SELECT * FROM list_options " .
2925 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
2926 $count = 0;
2927 while ($lrow = sqlFetchArray($lres)) {
2928 $option_id = $lrow['option_id'];
2929 if (in_array($option_id, $avalue)) {
2930 if ($count++) {
2931 $s .= "; ";
2933 $s .= xl_list_label($lrow['title']);
2937 } elseif ($data_type == 22) { // a set of labeled text input fields
2938 $tmp = explode('|', $currvalue);
2939 $avalue = array();
2940 foreach ($tmp as $value) {
2941 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
2942 $avalue[$matches[1]] = $matches[2];
2946 $lres = sqlStatement("SELECT * FROM list_options " .
2947 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
2948 while ($lrow = sqlFetchArray($lres)) {
2949 $option_id = $lrow['option_id'];
2950 if (empty($avalue[$option_id])) {
2951 continue;
2954 if ($s !== '') {
2955 $s .= '; ';
2958 $s .= xl_list_label($lrow['title']) . ': ';
2959 $s .= $avalue[$option_id];
2961 } elseif ($data_type == 23) { // A set of exam results; 3 radio buttons and a text field.
2962 // This shows abnormal results only.
2963 $tmp = explode('|', $currvalue);
2964 $avalue = array();
2965 foreach ($tmp as $value) {
2966 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
2967 $avalue[$matches[1]] = $matches[2];
2971 $lres = sqlStatement("SELECT * FROM list_options " .
2972 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
2973 while ($lrow = sqlFetchArray($lres)) {
2974 $option_id = $lrow['option_id'];
2975 $restype = substr($avalue[$option_id], 0, 1);
2976 $resnote = substr($avalue[$option_id], 2);
2977 if (empty($restype) && empty($resnote)) {
2978 continue;
2981 if ($restype != '2') {
2982 continue; // show abnormal results only
2985 if ($s !== '') {
2986 $s .= '; ';
2989 $s .= xl_list_label($lrow['title']);
2990 if (!empty($resnote)) {
2991 $s .= ': ' . $resnote;
2994 } elseif ($data_type == 24) { // the list of active allergies for the current patient
2995 $query = "SELECT title, comments FROM lists WHERE " .
2996 "pid = ? AND type = 'allergy' AND enddate IS NULL " .
2997 "ORDER BY begdate";
2998 $lres = sqlStatement($query, array($GLOBALS['pid']));
2999 $count = 0;
3000 while ($lrow = sqlFetchArray($lres)) {
3001 if ($count++) {
3002 $s .= "; ";
3005 $s .= $lrow['title'];
3006 if ($lrow['comments']) {
3007 $s .= ' (' . $lrow['comments'] . ')';
3010 } elseif ($data_type == 25) { // a set of labeled checkboxes, each with a text field:
3011 $tmp = explode('|', $currvalue);
3012 $avalue = array();
3013 foreach ($tmp as $value) {
3014 if (preg_match('/^([^:]+):(.*)$/', $value, $matches)) {
3015 $avalue[$matches[1]] = $matches[2];
3019 $lres = sqlStatement("SELECT * FROM list_options " .
3020 "WHERE list_id = ? AND activity = 1 ORDER BY seq, title", array($list_id));
3021 while ($lrow = sqlFetchArray($lres)) {
3022 $option_id = $lrow['option_id'];
3023 $restype = substr($avalue[$option_id], 0, 1);
3024 $resnote = substr($avalue[$option_id], 2);
3025 if (empty($restype) && empty($resnote)) {
3026 continue;
3029 if ($s !== '') {
3030 $s .= '; ';
3033 $s .= xl_list_label($lrow['title']);
3034 $restype = $restype ? xl('Yes') : xl('No');
3035 $s .= $restype;
3036 if ($resnote) {
3037 $s .= ' ' . $resnote;
3040 } elseif ($data_type == 28 || $data_type == 32) { // special case for history of lifestyle status; 3 radio buttons and a date text field:
3041 // VicarePlus :: A selection list for smoking status.
3042 $tmp = explode('|', $currvalue);
3043 $resnote = count($tmp) > 0 ? $tmp[0] : '';
3044 $restype = count($tmp) > 1 ? $tmp[1] : '';
3045 $resdate = count($tmp) > 2 ? oeFormatShortDate($tmp[2]) : '';
3046 $reslist = count($tmp) > 3 ? $tmp[3] : '';
3047 $res = "";
3048 if ($restype == "current" . $field_id) {
3049 $res = xl('Current');
3052 if ($restype == "quit" . $field_id) {
3053 $res = xl('Quit');
3056 if ($restype == "never" . $field_id) {
3057 $res = xl('Never');
3060 if ($restype == "not_applicable" . $field_id) {
3061 $res = xl('N/A');
3064 if ($data_type == 28) {
3065 if (!empty($resnote)) {
3066 $s .= $resnote;
3068 } elseif ($data_type == 32) { // Tobacco field has a listbox, text box, date field and 3 radio buttons.
3069 if (!empty($reslist)) {
3070 $s .= generate_plaintext_field(array('data_type' => '1','list_id' => $list_id), $reslist);
3073 if (!empty($resnote)) {
3074 $s .= ' ' . $resnote;
3078 if (!empty($res)) {
3079 if ($s !== '') {
3080 $s .= ' ';
3083 $s .= xl('Status') . ' ' . $res;
3086 if ($restype == "quit" . $field_id) {
3087 if ($s !== '') {
3088 $s .= ' ';
3091 $s .= $resdate;
3093 } elseif ($data_type == 35) { // Facility, so facility can be listed in plain-text, as in patient finder column
3094 $facilityService = new FacilityService();
3095 $facility = $facilityService->getById($currvalue);
3096 $s = $facility['name'];
3097 } elseif ($data_type == 36 || $data_type == 33) { // Multi select. Supports backup lists
3098 $values_array = explode("|", $currvalue);
3100 $i = 0;
3101 foreach ($values_array as $value) {
3102 $lrow = sqlQuery("SELECT title FROM list_options " .
3103 "WHERE list_id = ? AND option_id = ? AND activity = 1", array($list_id,$value));
3105 if ($lrow == 0 && !empty($backup_list)) {
3106 //use back up list
3107 $lrow = sqlQuery("SELECT title FROM list_options " .
3108 "WHERE list_id = ? AND option_id = ? AND activity = 1", array($backup_list,$value));
3111 if ($i > 0) {
3112 $s = $s . ", " . xl_list_label($lrow['title']);
3113 } else {
3114 $s = xl_list_label($lrow['title']);
3117 $i++;
3120 // A set of lab test results; Gestation, 3 radio buttons, test value, notes field:
3121 } elseif ($data_type == 37) {
3122 $s .= genLabResults($frow, $currvalue, 3, '');
3123 } elseif ($data_type == 44 || $data_type == 45) {
3124 $values_array = explode("|", $currvalue);
3126 $i = 0;
3127 foreach ($values_array as $value) {
3128 if ($data_type == 44) {
3129 $lrow = sqlQuery("SELECT name as name FROM facility WHERE id = ?", array($value));
3131 if ($data_type == 45) {
3132 $lrow = sqlQuery("SELECT CONCAT(fname,' ',lname) as name FROM users WHERE id = ?", array($value));
3135 if ($i > 0) {
3136 $s = $s . ", " . $lrow['name'];
3137 } else {
3138 $s = $lrow['name'];
3141 $i++;
3144 // Patient selector field.
3145 } else if ($data_type == 51) {
3146 if (!empty($currvalue)) {
3147 $s .= getPatientDescription($currvalue);
3151 return $s;
3154 $CPR = 4; // cells per row of generic data
3155 $last_group = '';
3156 $cell_count = 0;
3157 $item_count = 0;
3159 function disp_end_cell()
3161 global $item_count, $cell_count;
3162 if ($item_count > 0) {
3163 echo "</td>";
3164 $item_count = 0;
3168 function disp_end_row()
3170 global $cell_count, $CPR;
3171 disp_end_cell();
3172 if ($cell_count > 0) {
3173 for (; $cell_count < $CPR; ++$cell_count) {
3174 echo "<td></td>";
3177 echo "</tr>\n";
3178 $cell_count = 0;
3182 function disp_end_group()
3184 global $last_group;
3185 if (strlen($last_group) > 0) {
3186 disp_end_row();
3190 function getPatientDescription($pid)
3192 $prow = sqlQuery("SELECT lname, fname FROM patient_data WHERE pid = ?", array($pid));
3193 if ($prow) {
3194 return $prow['lname'] . ", " . $prow['fname'] . " ($pid)";
3196 return xl('Unknown') . " ($pid)";
3199 // Accumulate action conditions into a JSON expression for the browser side.
3200 function accumActionConditions(&$frow, &$condition_str)
3202 $field_id = $frow['field_id'];
3203 $conditions = empty($frow['conditions']) ? array() : unserialize($frow['conditions'], ['allowed_classes' => false]);
3204 $action = 'skip';
3205 foreach ($conditions as $key => $condition) {
3206 if ($key === 'action') {
3207 // If specified this should be the first array item.
3208 if ($condition) {
3209 $action = $condition;
3211 continue;
3213 if (empty($condition['id'])) {
3214 continue;
3216 $andor = empty($condition['andor']) ? '' : $condition['andor'];
3217 if ($condition_str) {
3218 $condition_str .= ",\n";
3220 $condition_str .= "{" .
3221 "target:" . js_escape($field_id) . ", " .
3222 "action:" . js_escape($action) . ", " .
3223 "id:" . js_escape($condition['id']) . ", " .
3224 "itemid:" . js_escape($condition['itemid']) . ", " .
3225 "operator:" . js_escape($condition['operator']) . ", " .
3226 "value:" . js_escape($condition['value']) . ", ";
3227 if ($frow['data_type'] == 15 && strpos($frow['edit_options'], '2') !== false) {
3228 // For billing codes handle requirement to display its description.
3229 $tmp = explode('=', $action, 2);
3230 if (!empty($tmp[1])) {
3231 $condition_str .= "valdesc:" . js_escape(getCodeDescription($tmp[1])) . ", ";
3234 $condition_str .= "andor:" . js_escape($andor) . "}";
3238 function getCodeDescription($codestring, $defaulttype = 'ICD10')
3240 if ($codestring === '') {
3241 return '';
3243 list($ctype, $code) = explode(':', $codestring);
3244 if (empty($code)) {
3245 $code = $ctype;
3246 $ctype = $defaulttype;
3248 $desc = lookup_code_descriptions("$ctype:$code");
3249 if (!empty($desc)) {
3250 return $desc;
3251 } else {
3252 return $codestring;
3256 // This checks if the given field with the given value should have an action applied.
3257 // Originally the only action was skip, but now you can also set the field to a
3258 // specified value, or "skip and otherwise set a value".
3259 // It somewhat mirrors the checkSkipConditions function in options.js.php.
3260 // If you use this for multiple layouts in the same script, you should
3261 // clear $sk_layout_items before each layout.
3262 function isSkipped(&$frow, $currvalue)
3264 global $sk_layout_items;
3266 // Accumulate an array of the encountered fields and their values.
3267 // It is assumed that fields appear before they are tested by another field.
3268 // TBD: Bad assumption?
3269 $field_id = $frow['field_id'];
3270 if (!is_array($sk_layout_items)) {
3271 $sk_layout_items = array();
3273 $sk_layout_items[$field_id] = array('row' => $frow, 'value' => $currvalue);
3275 if (empty($frow['conditions'])) {
3276 return false;
3279 $skiprows = unserialize($frow['conditions'], ['allowed_classes' => false]);
3280 $prevandor = '';
3281 $prevcond = false;
3282 $datatype = $frow['data_type'];
3283 $action = 'skip'; // default action if none specified
3285 foreach ($skiprows as $key => $skiprow) {
3286 // id referenced field id
3287 // itemid referenced array key if applicable
3288 // operator "eq", "ne", "se" or "ns"
3289 // value if eq or ne, some string to compare with
3290 // andor "and", "or" or empty
3292 if ($key === 'action') {
3293 // Action value is a string. It can be "skip", or "value=" or "hsval=" followed by a value.
3294 $action = $skiprow;
3295 continue;
3298 if (empty($skiprow['id'])) {
3299 continue;
3302 $id = $skiprow['id'];
3303 if (!isset($sk_layout_items[$id])) {
3304 error_log("Function isSkipped() cannot find skip source field '" . errorLogEscape($id) . "'.");
3305 continue;
3307 $itemid = $skiprow['itemid'];
3308 $operator = $skiprow['operator'];
3309 $skipval = $skiprow['value'];
3310 $srcvalue = $sk_layout_items[$id]['value'];
3311 $src_datatype = $sk_layout_items[$id]['row']['data_type'];
3312 $src_list_id = $sk_layout_items[$id]['row']['list_id'];
3314 // Some data types use itemid and we have to dig for their value.
3315 if ($src_datatype == 21 && $src_list_id) { // array of checkboxes
3316 $tmp = explode('|', $srcvalue);
3317 $srcvalue = in_array($itemid, $tmp);
3318 } elseif ($src_datatype == 22 || $src_datatype == 23 || $src_datatype == 25) {
3319 $tmp = explode('|', $srcvalue);
3320 $srcvalue = '';
3321 foreach ($tmp as $tmp2) {
3322 if (strpos($tmp2, "$itemid:") === 0) {
3323 if ($datatype == 22) {
3324 $srcvalue = substr($tmp2, strlen($itemid) + 1);
3325 } else {
3326 $srcvalue = substr($tmp2, strlen($itemid) + 1, 1);
3332 // Compute the result of the test for this condition row.
3333 // PHP's looseness with variable type conversion helps us here.
3334 $condition = false;
3335 if ($operator == 'eq') {
3336 $condition = $srcvalue == $skipval;
3337 } elseif ($operator == 'ne') {
3338 $condition = $srcvalue != $skipval;
3339 } elseif ($operator == 'se') {
3340 $condition = $srcvalue == true;
3341 } elseif ($operator == 'ns') {
3342 $condition = $srcvalue != true;
3343 } else {
3344 error_log("Unknown skip operator '" . errorLogEscape($operator) . "' for field '" . errorLogEscape($field_id) . "'.");
3347 // Logic to accumulate multiple conditions for the same target.
3348 if ($prevandor == 'and') {
3349 $condition = $condition && $prevcond;
3350 } elseif ($prevandor == 'or') {
3351 $condition = $condition || $prevcond;
3353 $prevandor = $skiprow['andor'];
3354 $prevcond = $condition;
3357 if (substr($action, 0, 6) == 'hsval=') {
3358 return $prevcond ? 'skip' : ('value=' . substr($action, 6));
3360 return $prevcond ? $action : '';
3363 // Load array of names of the given layout and its groups.
3364 function getLayoutProperties($formtype, &$grparr, $sel = "grp_title")
3366 if ($sel != '*' && strpos($sel, 'grp_group_id') === false) {
3367 $sel = "grp_group_id, $sel";
3369 $gres = sqlStatement("SELECT $sel FROM layout_group_properties WHERE grp_form_id = ? " .
3370 "ORDER BY grp_group_id", array($formtype));
3371 while ($grow = sqlFetchArray($gres)) {
3372 // TBD: Remove this after grp_init_open column is implemented.
3373 if ($sel == '*' && !isset($grow['grp_init_open'])) {
3374 $tmprow = sqlQuery(
3375 "SELECT form_id FROM layout_options " .
3376 "WHERE form_id = ? AND group_id LIKE ? AND uor > 0 AND edit_options LIKE '%I%' " .
3377 "LIMIT 1",
3378 array($formtype, $grow['grp_group_id'] . '%')
3380 $grow['grp_init_open'] = !empty($tmprow['form_id']);
3382 $grparr[$grow['grp_group_id']] = $grow;
3386 function display_layout_rows($formtype, $result1, $result2 = '')
3388 global $item_count, $cell_count, $last_group, $CPR;
3390 if ('HIS' == $formtype) {
3391 $formtype .= '%'; // TBD: DEM also?
3393 $pres = sqlStatement(
3394 "SELECT grp_form_id, grp_seq, grp_title " .
3395 "FROM layout_group_properties " .
3396 "WHERE grp_form_id LIKE ? AND grp_group_id = '' " .
3397 "ORDER BY grp_seq, grp_title, grp_form_id",
3398 array("$formtype")
3400 while ($prow = sqlFetchArray($pres)) {
3401 $formtype = $prow['grp_form_id'];
3402 $last_group = '';
3403 $cell_count = 0;
3404 $item_count = 0;
3406 $grparr = array();
3407 getLayoutProperties($formtype, $grparr, '*');
3409 $TOPCPR = empty($grparr['']['grp_columns']) ? 4 : $grparr['']['grp_columns'];
3411 $fres = sqlStatement("SELECT * FROM layout_options " .
3412 "WHERE form_id = ? AND uor > 0 " .
3413 "ORDER BY group_id, seq", array($formtype));
3415 while ($frow = sqlFetchArray($fres)) {
3416 $this_group = $frow['group_id'];
3417 $titlecols = $frow['titlecols'];
3418 $datacols = $frow['datacols'];
3419 $data_type = $frow['data_type'];
3420 $field_id = $frow['field_id'];
3421 $list_id = $frow['list_id'];
3422 $currvalue = '';
3423 $jump_new_row = isOption($frow['edit_options'], 'J');
3424 $prepend_blank_row = isOption($frow['edit_options'], 'K');
3425 $portal_exclude = ($_SESSION["patient_portal_onsite_two"] && isOption($frow['edit_options'], 'EP')) ?? null;
3427 if (!empty($portal_exclude)) {
3428 continue;
3431 $CPR = empty($grparr[$this_group]['grp_columns']) ? $TOPCPR : $grparr[$this_group]['grp_columns'];
3433 if ($formtype == 'DEM') {
3434 if (strpos($field_id, 'em_') === 0) {
3435 // Skip employer related fields, if it's disabled.
3436 if ($GLOBALS['omit_employers']) {
3437 continue;
3440 $tmp = substr($field_id, 3);
3441 if (isset($result2[$tmp])) {
3442 $currvalue = $result2[$tmp];
3444 } else {
3445 if (isset($result1[$field_id])) {
3446 $currvalue = $result1[$field_id];
3449 } else {
3450 if (isset($result1[$field_id])) {
3451 $currvalue = $result1[$field_id];
3455 // Handle a data category (group) change.
3456 if (strcmp($this_group, $last_group) != 0) {
3457 $group_name = $grparr[$this_group]['grp_title'];
3458 // totally skip generating the employer category, if it's disabled.
3459 if ($group_name === 'Employer' && $GLOBALS['omit_employers']) {
3460 continue;
3463 disp_end_group();
3464 $last_group = $this_group;
3467 // filter out all the empty field data from the patient report.
3468 if (!empty($currvalue) && !($currvalue == '0000-00-00 00:00:00')) {
3469 // Handle starting of a new row.
3470 if (($titlecols > 0 && $cell_count >= $CPR) || $cell_count == 0 || $prepend_blank_row || $jump_new_row) {
3471 disp_end_row();
3472 if ($prepend_blank_row) {
3473 echo "<tr><td class='label' colspan='" . ($CPR + 1) . "'>&nbsp;</td></tr>\n";
3475 echo "<tr>";
3476 if ($group_name) {
3477 echo "<td class='groupname'>";
3478 echo text(xl_layout_label($group_name));
3479 $group_name = '';
3480 } else {
3481 echo "<td class='align-top'>&nbsp;";
3484 echo "</td>";
3487 if ($item_count == 0 && $titlecols == 0) {
3488 $titlecols = 1;
3491 // Handle starting of a new label cell.
3492 if ($titlecols > 0) {
3493 disp_end_cell();
3494 //echo "<td class='label_custom align-top' colspan='$titlecols'";
3495 $titlecols_esc = htmlspecialchars($titlecols, ENT_QUOTES);
3496 echo "<td class='label_custom' colspan='$titlecols_esc' ";
3497 //if ($cell_count == 2) echo " style='padding-left:10pt'";
3498 echo ">";
3499 $cell_count += $titlecols;
3502 ++$item_count;
3504 // Added 5-09 by BM - Translate label if applicable
3505 if ($frow['title']) {
3506 $tmp = xl_layout_label($frow['title']);
3507 echo text($tmp);
3508 // Append colon only if label does not end with punctuation.
3509 if (strpos('?!.,:-=', substr($tmp, -1, 1)) === false) {
3510 echo ':';
3512 } else {
3513 echo "&nbsp;";
3516 // Handle starting of a new data cell.
3517 if ($datacols > 0) {
3518 disp_end_cell();
3519 //echo "<td class='text data align-top' colspan='$datacols'";
3520 $datacols_esc = htmlspecialchars($datacols, ENT_QUOTES);
3521 echo "<td class='text data' colspan='$datacols_esc'";
3522 //if ($cell_count > 0) echo " style='padding-left:5pt'";
3523 echo ">";
3524 $cell_count += $datacols;
3527 ++$item_count;
3528 echo generate_display_field($frow, $currvalue);
3531 disp_end_group();
3532 } // End this layout, there may be more in the case of history.
3535 // This generates the tabs for a form.
3537 function display_layout_tabs($formtype, $result1, $result2 = '')
3539 global $item_count, $cell_count, $last_group, $CPR;
3541 if ('HIS' == $formtype) {
3542 $formtype .= '%'; // TBD: DEM also?
3544 $pres = sqlStatement(
3545 "SELECT grp_form_id, grp_seq, grp_title " .
3546 "FROM layout_group_properties " .
3547 "WHERE grp_form_id LIKE ? AND grp_group_id = '' " .
3548 "ORDER BY grp_seq, grp_title, grp_form_id",
3549 array("$formtype")
3551 $first = true;
3552 while ($prow = sqlFetchArray($pres)) {
3553 $formtype = $prow['grp_form_id'];
3554 $last_group = '';
3555 $cell_count = 0;
3556 $item_count = 0;
3558 $grparr = array();
3559 getLayoutProperties($formtype, $grparr);
3561 $fres = sqlStatement("SELECT distinct group_id FROM layout_options " .
3562 "WHERE form_id = ? AND uor > 0 " .
3563 "ORDER BY group_id", array($formtype));
3565 $prev_group = '';
3566 while ($frow = sqlFetchArray($fres)) {
3567 $this_group = $frow['group_id'];
3568 if (substr($prev_group, 0, 1) === substr($this_group, 0, 1)) {
3569 // Skip sub-groups, they will not start a new tab.
3570 continue;
3572 $prev_group = $this_group;
3573 $group_name = $grparr[$this_group]['grp_title'];
3574 if ($group_name === 'Employer' && $GLOBALS['omit_employers']) {
3575 continue;
3578 <li <?php echo $first ? 'class="current"' : '' ?>>
3579 <a href="#" id="header_tab_<?php echo attr($group_name); ?>">
3580 <?php echo text(xl_layout_label($group_name)); ?></a>
3581 </li>
3582 <?php
3583 $first = false;
3585 } // End this layout, there may be more in the case of history.
3588 // This generates the tab contents of the display version of a form.
3590 function display_layout_tabs_data($formtype, $result1, $result2 = '')
3592 global $item_count, $cell_count, $last_group, $CPR;
3594 if ('HIS' == $formtype) {
3595 $formtype .= '%'; // TBD: DEM also?
3597 $pres = sqlStatement(
3598 "SELECT grp_form_id, grp_seq, grp_title " .
3599 "FROM layout_group_properties " .
3600 "WHERE grp_form_id LIKE ? AND grp_group_id = '' " .
3601 "ORDER BY grp_seq, grp_title, grp_form_id",
3602 array("$formtype")
3604 $first = true;
3606 // This loops once per layout. Only Patient History can have multiple layouts.
3607 while ($prow = sqlFetchArray($pres)) {
3608 $formtype = $prow['grp_form_id'];
3609 $last_group = '';
3610 $cell_count = 0;
3611 $item_count = 0;
3613 $grparr = array();
3614 getLayoutProperties($formtype, $grparr, '*');
3616 $TOPCPR = empty($grparr['']['grp_columns']) ? 4 : $grparr['']['grp_columns'];
3618 // By selecting distinct group_id from layout_options we avoid empty groups.
3619 $fres = sqlStatement("SELECT distinct group_id FROM layout_options " .
3620 "WHERE form_id = ? AND uor > 0 " .
3621 "ORDER BY group_id", array($formtype));
3623 $prev_group = '';
3625 // This loops once per group within a given layout.
3626 while ($frow = sqlFetchArray($fres)) {
3627 $this_group = isset($frow['group_id']) ? $frow['group_id'] : "" ;
3629 if ($grparr[$this_group]['grp_columns'] === 'Employer' && $GLOBALS['omit_employers']) {
3630 continue;
3632 $CPR = empty($grparr[$this_group]['grp_columns']) ? $TOPCPR : $grparr[$this_group]['grp_columns'];
3633 $subtitle = empty($grparr[$this_group]['grp_subtitle']) ? '' : xl_layout_label($grparr[$this_group]['grp_subtitle']);
3635 $group_fields_query = sqlStatement(
3636 "SELECT * FROM layout_options " .
3637 "WHERE form_id = ? AND uor > 0 AND group_id = ? " .
3638 "ORDER BY seq",
3639 array($formtype, $this_group)
3642 if (substr($this_group, 0, 1) !== substr($prev_group, 0, 1)) {
3643 // Each new top level group gets its own tab div.
3644 if (!$first) {
3645 echo "</div>\n";
3647 echo "<div class='tab" . ($first ? ' current' : '') . "'>\n";
3649 echo "<table border='0' cellpadding='0'>\n";
3651 // This loops once per field within a given group.
3652 while ($group_fields = sqlFetchArray($group_fields_query)) {
3653 $titlecols = $group_fields['titlecols'];
3654 $datacols = $group_fields['datacols'];
3655 $data_type = $group_fields['data_type'];
3656 $field_id = $group_fields['field_id'];
3657 $list_id = $group_fields['list_id'];
3658 $currvalue = '';
3659 $edit_options = $group_fields['edit_options'];
3660 $jump_new_row = isOption($edit_options, 'J');
3661 $prepend_blank_row = isOption($edit_options, 'K');
3663 if ($formtype == 'DEM') {
3664 if (strpos($field_id, 'em_') === 0) {
3665 // Skip employer related fields, if it's disabled.
3666 if ($GLOBALS['omit_employers']) {
3667 continue;
3670 $tmp = substr($field_id, 3);
3671 if (isset($result2[$tmp])) {
3672 $currvalue = $result2[$tmp];
3674 } else {
3675 if (isset($result1[$field_id])) {
3676 $currvalue = $result1[$field_id];
3679 } else {
3680 if (isset($result1[$field_id])) {
3681 $currvalue = $result1[$field_id];
3685 // Skip this field if action conditions call for that.
3686 // Note this also accumulates info for subsequent skip tests.
3687 $skip_this_field = isSkipped($group_fields, $currvalue) == 'skip';
3689 // Skip this field if its do-not-print option is set.
3690 if (isOption($edit_options, 'X') !== false) {
3691 $skip_this_field = true;
3694 // Handle a data category (group) change.
3695 if (strcmp($this_group, $last_group) != 0) {
3696 $group_name = $grparr[$this_group]['grp_title'];
3697 // totally skip generating the employer category, if it's disabled.
3698 if ($group_name === 'Employer' && $GLOBALS['omit_employers']) {
3699 continue;
3701 $last_group = $this_group;
3704 // Handle starting of a new row.
3705 if (($titlecols > 0 && $cell_count >= $CPR) || $cell_count == 0 || $prepend_blank_row || $jump_new_row) {
3706 disp_end_row();
3707 if ($subtitle) {
3708 // Group subtitle exists and is not displayed yet.
3709 echo "<tr><td class='label' style='background-color: var(--gray300); padding: 4px' colspan='$CPR'>" . text($subtitle) . "</td></tr>\n";
3710 echo "<tr><td class='label' style='height: 5px' colspan='$CPR'></td></tr>\n";
3711 $subtitle = '';
3713 if ($prepend_blank_row) {
3714 echo "<tr><td class='label' style='font-size:25%' colspan='$CPR'>&nbsp;</td></tr>\n";
3716 echo "<tr>";
3719 if ($item_count == 0 && $titlecols == 0) {
3720 $titlecols = 1;
3723 // Handle starting of a new label cell.
3724 if ($titlecols > 0) {
3725 disp_end_cell();
3726 $titlecols_esc = htmlspecialchars($titlecols, ENT_QUOTES);
3727 $field_id_label = 'label_' . $group_fields['field_id'];
3728 echo "<td class='label_custom' colspan='$titlecols_esc' id='" . attr($field_id_label) . "'";
3729 echo ">";
3730 $cell_count += $titlecols;
3733 ++$item_count;
3735 $field_id_label = 'label_' . $group_fields['field_id'];
3736 echo "<span id='" . attr($field_id_label) . "'>";
3737 if ($skip_this_field) {
3738 // No label because skipping
3739 } elseif ($group_fields['title']) {
3740 $tmp = xl_layout_label($group_fields['title']);
3741 echo text($tmp);
3742 // Append colon only if label does not end with punctuation.
3743 if (strpos('?!.,:-=', substr($tmp, -1, 1)) === false) {
3744 echo ':';
3746 } else {
3747 echo "&nbsp;";
3749 echo "</span>";
3751 // Handle starting of a new data cell.
3752 if ($datacols > 0) {
3753 disp_end_cell();
3754 $datacols_esc = htmlspecialchars($datacols, ENT_QUOTES);
3755 $field_id = 'text_' . $group_fields['field_id'];
3756 echo "<td class='text data' colspan='$datacols_esc' id='" . attr($field_id) . "' data-value='" . attr($currvalue) . "'";
3757 if (!$skip_this_field && $data_type == 3) {
3758 // Textarea gets a light grey border.
3759 echo " style='border: 1px solid var(--gray400)'";
3761 echo ">";
3762 $cell_count += $datacols;
3763 } else {
3764 $field_id = 'text_' . $group_fields['field_id'];
3765 echo "<span id='" . attr($field_id) . "' style='display: none'>" . text($currvalue) . "</span>";
3768 ++$item_count;
3769 if (!$skip_this_field) {
3770 echo generate_display_field($group_fields, $currvalue);
3772 } // end field
3774 disp_end_row();
3776 // End table for the group.
3777 echo "</table>\n";
3779 $prev_group = $this_group;
3780 $first = false;
3781 } // End this group.
3782 } // End this layout, there may be more in the case of history.
3784 if (!$first) {
3785 echo "</div>\n";
3789 // This generates the tab contents of the data entry version of a form.
3791 function display_layout_tabs_data_editable($formtype, $result1, $result2 = '')
3793 global $item_count, $cell_count, $last_group, $CPR,$condition_str;
3795 if ('HIS' == $formtype) {
3796 $formtype .= '%'; // TBD: DEM also?
3798 $pres = sqlStatement(
3799 "SELECT grp_form_id, grp_seq, grp_title " .
3800 "FROM layout_group_properties " .
3801 "WHERE grp_form_id LIKE ? AND grp_group_id = '' " .
3802 "ORDER BY grp_seq, grp_title, grp_form_id",
3803 array("$formtype")
3805 $first = true;
3806 $condition_str = '';
3808 // This loops once per layout. Only Patient History can have multiple layouts.
3809 while ($prow = sqlFetchArray($pres)) {
3810 $formtype = $prow['grp_form_id'];
3811 $last_group = '';
3812 $cell_count = 0;
3813 $item_count = 0;
3815 $grparr = array();
3816 getLayoutProperties($formtype, $grparr, '*');
3818 $TOPCPR = empty($grparr['']['grp_columns']) ? 4 : $grparr['']['grp_columns'];
3820 // Check the children of each top-level group to see if any of them are initially open.
3821 // If not, make the first such child initially open.
3822 foreach ($grparr as $tmprow1) {
3823 if (strlen($tmprow1['grp_group_id']) == 1) {
3824 $got_init_open = false;
3825 $keyfirst = false;
3826 foreach ($grparr as $key2 => $tmprow2) {
3827 if (substr($tmprow2['grp_group_id'], 0, 1) == $tmprow1['grp_group_id'] && strlen($tmprow2['grp_group_id']) == 2) {
3828 if (!$keyfirst) {
3829 $keyfirst = $key2;
3831 if ($tmprow2['grp_init_open']) {
3832 $got_init_open = true;
3836 if (!$got_init_open && $keyfirst) {
3837 $grparr[$keyfirst]['grp_init_open'] = 1;
3842 // Variables $gs_* are context for the group set in the current tab.
3843 $gs_display_style = 'block';
3844 // This string is the active group levels representing the current display state.
3845 // Each leading substring represents an instance of nesting.
3846 // As each new group is encountered, groups will be closed and opened as needed
3847 // until the display state matches the new group.
3848 $gs_group_levels = '';
3850 // By selecting distinct group_id from layout_options we avoid empty groups.
3851 $fres = sqlStatement("SELECT distinct group_id FROM layout_options " .
3852 "WHERE form_id = ? AND uor > 0 " .
3853 "ORDER BY group_id", array($formtype));
3855 // This loops once per group within a given layout.
3856 while ($frow = sqlFetchArray($fres)) {
3857 $this_group = $frow['group_id'];
3858 $group_name = $grparr[$this_group]['grp_title'];
3859 $group_name_esc = text($group_name);
3861 if ($grparr[$this_group]['grp_title'] === 'Employer' && $GLOBALS['omit_employers']) {
3862 continue;
3864 $CPR = empty($grparr[$this_group]['grp_columns']) ? $TOPCPR : $grparr[$this_group]['grp_columns'];
3865 $subtitle = empty($grparr[$this_group]['grp_subtitle']) ? '' : xl_layout_label($grparr[$this_group]['grp_subtitle']);
3867 $group_fields_query = sqlStatement("SELECT * FROM layout_options " .
3868 "WHERE form_id = ? AND uor > 0 AND group_id = ? " .
3869 "ORDER BY seq", array($formtype, $this_group));
3871 $gs_this_levels = $this_group;
3872 // Compute $gs_i as the number of initial matching levels.
3873 $gs_i = 0;
3874 $tmp = min(strlen($gs_this_levels), strlen($gs_group_levels));
3875 while ($gs_i < $tmp && $gs_this_levels[$gs_i] == $gs_group_levels[$gs_i]) {
3876 ++$gs_i;
3879 // Close any groups that we are done with.
3880 while (strlen($gs_group_levels) > $gs_i) {
3881 $gs_group_name = $grparr[$gs_group_levels]['grp_title'];
3882 if (strlen($gs_group_levels) > 1) {
3883 // No div for an empty sub-group name.
3884 if (strlen($gs_group_name)) {
3885 echo "</div>\n";
3887 } else {
3888 // This is the top group level so ending this tab and will start a new one.
3889 echo "</div>\n";
3891 $gs_group_levels = substr($gs_group_levels, 0, -1); // remove last character
3894 // If there are any new groups, open them.
3895 while ($gs_i < strlen($gs_this_levels)) {
3896 $gs_group_levels .= $gs_this_levels[$gs_i++];
3897 $gs_group_name = $grparr[substr($gs_group_levels, 0, $gs_i)]['grp_title'];
3898 $gs_init_open = $grparr[substr($gs_group_levels, 0, $gs_i)]['grp_init_open'];
3899 // Compute a short unique identifier for this group.
3900 $gs_group_seq = "grp-$formtype-$gs_group_levels";
3901 if ($gs_i <= 1) {
3902 // Top level group so new tab.
3903 echo "<div class='tab" . ($first ? ' current' : '') . "' id='tab_$group_name_esc'>\n";
3904 } else {
3905 // Not a new tab so start the group inline.
3906 // If group name is blank, no checkbox or div.
3907 if (strlen($gs_group_name)) {
3908 echo "<br /><span class='bold'><input type='checkbox' name='form_cb_" .
3909 attr($gs_group_seq) . "' value='1' " .
3910 "onclick='return divclick(this," . attr_js('div_' . $gs_group_seq) . ");'";
3911 $gs_display_style = $gs_init_open ? 'block' : 'none';
3912 if ($gs_display_style == 'block') {
3913 echo " checked";
3915 echo " /><b>" . text(xl_layout_label($gs_group_name)) . "</b></span>\n";
3916 echo "<div id='div_" . attr($gs_group_seq) .
3917 "' class='section' style='display:" . attr($gs_display_style) . ";'>\n";
3922 // Each group or subgroup has its own separate table.
3923 $gs_group_table_active = true;
3924 echo " <table border='0' cellspacing='0' cellpadding='0' class='lbfdata'>\n";
3925 if ($subtitle) {
3926 // There is a group subtitle so show it.
3927 echo "<tr><td class='bold' style='color:#0000ff' colspan='$CPR'>" . text($subtitle) . "</td></tr>\n";
3928 echo "<tr><td class='bold' style='height:4pt' colspan='$CPR'></td></tr>\n";
3931 // This loops once per field within a given group.
3932 while ($group_fields = sqlFetchArray($group_fields_query)) {
3933 $titlecols = $group_fields['titlecols'];
3934 $datacols = $group_fields['datacols'];
3935 $data_type = $group_fields['data_type'];
3936 $field_id = $group_fields['field_id'];
3937 $list_id = $group_fields['list_id'];
3938 $backup_list = $group_fields['list_backup_id'];
3939 $currvalue = '';
3940 $action = 'skip';
3941 $jump_new_row = isOption($group_fields['edit_options'], 'J');
3942 $prepend_blank_row = isOption($group_fields['edit_options'], 'K');
3944 // Accumulate action conditions into a JSON expression for the browser side.
3945 accumActionConditions($group_fields, $condition_str);
3947 if ($formtype == 'DEM') {
3948 if (strpos($field_id, 'em_') === 0) {
3949 // Skip employer related fields, if it's disabled.
3950 if ($GLOBALS['omit_employers']) {
3951 continue;
3954 $tmp = substr($field_id, 3);
3955 if (isset($result2[$tmp])) {
3956 $currvalue = $result2[$tmp];
3958 } else {
3959 if (isset($result1[$field_id])) {
3960 $currvalue = $result1[$field_id];
3963 } else {
3964 if (isset($result1[$field_id])) {
3965 $currvalue = $result1[$field_id];
3969 // Handle a data category (group) change.
3970 if (strcmp($this_group, $last_group) != 0) {
3971 // totally skip generating the employer category, if it's disabled.
3972 if ($group_name === 'Employer' && $GLOBALS['omit_employers']) {
3973 continue;
3976 $last_group = $this_group;
3979 // Handle starting of a new row.
3980 if (($titlecols > 0 && $cell_count >= $CPR) || $cell_count == 0 || $prepend_blank_row || $jump_new_row) {
3981 disp_end_row();
3982 if ($subtitle) {
3983 // Group subtitle exists and is not displayed yet.
3984 echo "<tr><td class='label' style='background-color: var(--gray300); padding: 4px' colspan='$CPR'>" . text($subtitle) . "</td></tr>\n";
3985 echo "<tr><td class='label' style='height: 5px' colspan='$CPR'></td></tr>\n";
3986 $subtitle = '';
3988 if ($prepend_blank_row) {
3989 echo "<tr><td class='label' style='font-size:25%' colspan='$CPR'>&nbsp;</td></tr>\n";
3991 echo "<tr>";
3994 if ($item_count == 0 && $titlecols == 0) {
3995 $titlecols = 1;
3998 // Handle starting of a new label cell.
3999 if ($titlecols > 0) {
4000 disp_end_cell();
4001 $titlecols_esc = htmlspecialchars($titlecols, ENT_QUOTES);
4002 $field_id_label = 'label_' . $group_fields['field_id'];
4003 echo "<td class='label_custom' colspan='$titlecols_esc'";
4004 // This ID is used by skip conditions.
4005 echo " id='label_id_" . attr($field_id) . "'";
4006 echo ">";
4007 $cell_count += $titlecols;
4010 ++$item_count;
4012 if ($group_fields['title']) {
4013 $tmp = xl_layout_label($group_fields['title']);
4014 echo text($tmp);
4015 // Append colon only if label does not end with punctuation.
4016 if (strpos('?!.,:-=', substr($tmp, -1, 1)) === false) {
4017 echo ':';
4019 } else {
4020 echo "&nbsp;";
4023 // Handle starting of a new data cell.
4024 if ($datacols > 0) {
4025 disp_end_cell();
4026 $datacols_esc = htmlspecialchars($datacols, ENT_QUOTES);
4027 $field_id = 'text_' . $group_fields['field_id'];
4028 echo "<td class='text data' colspan='$datacols_esc'";
4029 // This ID is used by action conditions.
4030 echo " id='value_id_" . attr($field_id) . "'";
4031 echo ">";
4032 $cell_count += $datacols;
4035 ++$item_count;
4037 echo generate_form_field($group_fields, $currvalue);
4038 } // End of fields for this group.
4040 disp_end_row(); // TBD: Does this belong here?
4042 echo " </table>\n";
4043 $first = false;
4044 } // End this group.
4046 // Close any groups still open.
4047 while (strlen($gs_group_levels) > 0) {
4048 $gs_group_name = $grparr[$gs_group_levels]['grp_title'];
4049 if (strlen($gs_group_levels) > 1) {
4050 // No div for an empty sub-group name.
4051 if (strlen($gs_group_name)) {
4052 echo "</div>\n";
4054 } else {
4055 // This is the top group level so ending this tab and will start a new one.
4056 echo "</div>\n";
4058 $gs_group_levels = substr($gs_group_levels, 0, -1); // remove last character
4060 } // End this layout, there may be more in the case of history.
4063 // From the currently posted HTML form, this gets the value of the
4064 // field corresponding to the provided layout_options table row.
4066 function get_layout_form_value($frow, $prefix = 'form_')
4068 $maxlength = empty($frow['max_length']) ? 0 : intval($frow['max_length']);
4069 $data_type = $frow['data_type'];
4070 $field_id = $frow['field_id'];
4071 $value = '';
4072 if (isset($_POST["$prefix$field_id"])) {
4073 if ($data_type == 4) {
4074 $modtmp = isOption($frow['edit_options'], 'F') === false ? 0 : 1;
4075 if (!$modtmp) {
4076 $value = DateToYYYYMMDD($_POST["$prefix$field_id"]);
4077 } else {
4078 $value = DateTimeToYYYYMMDDHHMMSS($_POST["$prefix$field_id"]);
4080 } elseif ($data_type == 21) {
4081 if (!$frow['list_id']) {
4082 if (!empty($_POST["form_$field_id"])) {
4083 $value = xlt('Yes');
4085 } else {
4086 // $_POST["$prefix$field_id"] is an array of checkboxes and its keys
4087 // must be concatenated into a |-separated string.
4088 foreach ($_POST["$prefix$field_id"] as $key => $val) {
4089 if (strlen($value)) {
4090 $value .= '|';
4092 $value .= $key;
4095 } elseif ($data_type == 22) {
4096 // $_POST["$prefix$field_id"] is an array of text fields to be imploded
4097 // into "key:value|key:value|...".
4098 foreach ($_POST["$prefix$field_id"] as $key => $val) {
4099 $val = str_replace('|', ' ', $val);
4100 if (strlen($value)) {
4101 $value .= '|';
4104 $value .= "$key:$val";
4106 } elseif ($data_type == 23) {
4107 // $_POST["$prefix$field_id"] is an array of text fields with companion
4108 // radio buttons to be imploded into "key:n:notes|key:n:notes|...".
4109 foreach ($_POST["$prefix$field_id"] as $key => $val) {
4110 $restype = $_POST["radio_{$field_id}"][$key] ?? null;
4111 if (empty($restype)) {
4112 $restype = '0';
4115 $val = str_replace('|', ' ', $val);
4116 if (strlen($value)) {
4117 $value .= '|';
4120 $value .= "$key:$restype:$val";
4122 } elseif ($data_type == 25) {
4123 // $_POST["$prefix$field_id"] is an array of text fields with companion
4124 // checkboxes to be imploded into "key:n:notes|key:n:notes|...".
4125 foreach ($_POST["$prefix$field_id"] as $key => $val) {
4126 $restype = empty($_POST["check_{$field_id}"][$key]) ? '0' : '1';
4127 $val = str_replace('|', ' ', $val);
4128 if (strlen($value)) {
4129 $value .= '|';
4132 $value .= "$key:$restype:$val";
4134 } elseif ($data_type == 28 || $data_type == 32) {
4135 // $_POST["$prefix$field_id"] is an date text fields with companion
4136 // radio buttons to be imploded into "notes|type|date".
4137 $restype = $_POST["radio_{$field_id}"] ?? '';
4138 if (empty($restype)) {
4139 $restype = '0';
4142 $resdate = DateToYYYYMMDD(str_replace('|', ' ', $_POST["date_$field_id"]));
4143 $resnote = str_replace('|', ' ', $_POST["$prefix$field_id"]);
4144 if ($data_type == 32) {
4145 //VicarePlus :: Smoking status data is imploded into "note|type|date|list".
4146 $reslist = str_replace('|', ' ', $_POST["$prefix$field_id"]);
4147 $res_text_note = str_replace('|', ' ', $_POST["{$prefix}text_$field_id"]);
4148 $value = "$res_text_note|$restype|$resdate|$reslist";
4149 } else {
4150 $value = "$resnote|$restype|$resdate";
4152 } elseif ($data_type == 37) {
4153 // $_POST["form_$field_id"] is an array of arrays of 3 text fields with companion
4154 // radio button set to be encoded as json.
4155 $tmparr = array();
4156 foreach ($_POST["form_$field_id"] as $key => $valarr) {
4157 // Each $key here is a list item ID. $valarr has 3 text field values keyed on 0, 2 and 3.
4158 $tmparr[$key][0] = $valarr['0'];
4159 $tmparr[$key][1] = $_POST["radio_{$field_id}"][$key];
4160 $tmparr[$key][2] = $valarr['2'];
4161 $tmparr[$key][3] = $valarr['3'];
4163 $value .= json_encode($tmparr);
4164 } elseif ($data_type == 36 || $data_type == 44 || $data_type == 45 || $data_type == 33) {
4165 $value_array = $_POST["form_$field_id"];
4166 $i = 0;
4167 foreach ($value_array as $key => $valueofkey) {
4168 if ($i == 0) {
4169 $value = $valueofkey;
4170 } else {
4171 $value = $value . "|" . $valueofkey;
4174 $i++;
4176 } elseif ($data_type == 46) {
4177 $reslist = trim($_POST["$prefix$field_id"]);
4178 if (preg_match('/^comment_/', $reslist)) {
4179 $res_comment = str_replace('|', ' ', $_POST["{$prefix}text_$field_id"]);
4180 $value = $reslist . "|" . $res_comment;
4181 } else {
4182 $value = $_POST["$prefix$field_id"];
4184 } else {
4185 $value = $_POST["$prefix$field_id"];
4189 // Better to die than to silently truncate data!
4190 if ($maxlength && $maxlength != 0 && strlen(trim($value)) > $maxlength && !$frow['list_id']) {
4191 die(htmlspecialchars(xl('ERROR: Field') . " '$field_id' " . xl('is too long'), ENT_NOQUOTES) .
4192 ":<br />&nbsp;<br />" . htmlspecialchars($value, ENT_NOQUOTES));
4195 return trim($value);
4198 // Generate JavaScript validation logic for the required fields.
4200 function generate_layout_validation($form_id)
4202 if ('HIS' == $form_id) {
4203 $form_id .= '%'; // TBD: DEM also?
4205 $pres = sqlStatement(
4206 "SELECT grp_form_id, grp_seq, grp_title " .
4207 "FROM layout_group_properties " .
4208 "WHERE grp_form_id LIKE ? AND grp_group_id = '' " .
4209 "ORDER BY grp_seq, grp_title, grp_form_id",
4210 array("$form_id")
4212 while ($prow = sqlFetchArray($pres)) {
4213 $form_id = $prow['grp_form_id'];
4215 $fres = sqlStatement("SELECT * FROM layout_options " .
4216 "WHERE form_id = ? AND uor > 0 AND field_id != '' " .
4217 "ORDER BY group_id, seq", array($form_id));
4219 while ($frow = sqlFetchArray($fres)) {
4220 $data_type = $frow['data_type'];
4221 $field_id = $frow['field_id'];
4222 $fldtitle = $frow['title'];
4223 if (!$fldtitle) {
4224 $fldtitle = $frow['description'];
4227 $fldname = attr("form_$field_id");
4229 if ($data_type == 40) {
4230 $fldid = "form_" . $field_id;
4231 // Move canvas image data to its hidden form field so the server will get it.
4232 echo
4233 " var canfld = f[" . js_escape($fldid) . "];\n" .
4234 " if (canfld) canfld.value = lbfCanvasGetData(" . js_escape($fldid) . ");\n";
4235 continue;
4237 if ($data_type == 41 || $data_type == 42) {
4238 $fldid = "form_" . $field_id;
4239 // Move canvas image data to its hidden form field so the server will get it.
4240 echo " lbfSetSignature(" . js_escape($fldid) . ");\n";
4241 continue;
4243 if ($frow['uor'] < 2) {
4244 continue;
4247 echo " if (f.$fldname && !f.$fldname.disabled) {\n";
4248 switch ($data_type) {
4249 case 1:
4250 case 11:
4251 case 12:
4252 case 13:
4253 case 14:
4254 case 26:
4255 echo
4256 " if (f.$fldname.selectedIndex <= 0) {\n" .
4257 " alert(" . xlj('Please choose a value for') . " + " .
4258 "\":\\n\" + " . js_escape(xl_layout_label($fldtitle)) . ");\n" .
4259 " if (f.$fldname.focus) f.$fldname.focus();\n" .
4260 " return false;\n" .
4261 " }\n";
4262 break;
4263 case 33:
4264 echo
4265 " if (f.$fldname.selectedIndex <= 0) {\n" .
4266 " if (f.$fldname.focus) f.$fldname.focus();\n" .
4267 " errMsgs[errMsgs.length] = " . js_escape(xl_layout_label($fldtitle)) . "; \n" .
4268 " }\n";
4269 break;
4270 case 27: // radio buttons
4271 echo
4272 " var i = 0;\n" .
4273 " for (; i < f.$fldname.length; ++i) if (f.{$fldname}[i].checked) break;\n" .
4274 " if (i >= f.$fldname.length) {\n" .
4275 " alert(" . xlj('Please choose a value for') . " + " .
4276 "\":\\n\" + " . js_escape(xl_layout_label($fldtitle)) . ");\n" .
4277 " return false;\n" .
4278 " }\n";
4279 break;
4280 case 2:
4281 case 3:
4282 case 4:
4283 case 15:
4284 echo
4285 " if (trimlen(f.$fldname.value) == 0) {\n" .
4286 " if (f.$fldname.focus) f.$fldname.focus();\n" .
4287 " $('#" . $fldname . "').parents('div.tab').each( function(){ var tabHeader = $('#header_' + $(this).attr('id') ); tabHeader.css('color','var(--danger)'); } ); " .
4288 " $('#" . $fldname . "').attr('style','background: var(--danger)'); \n" .
4289 " errMsgs[errMsgs.length] = " . js_escape(xl_layout_label($fldtitle)) . "; \n" .
4290 " } else { " .
4291 " $('#" . $fldname . "').attr('style',''); " .
4292 " $('#" . $fldname . "').parents('div.tab').each( function(){ var tabHeader = $('#header_' + $(this).attr('id') ); tabHeader.css('color',''); } ); " .
4293 " } \n";
4294 break;
4295 case 36: // multi select
4296 echo
4297 " var multi_select=f['$fldname" . "[]']; \n " .
4298 " var multi_choice_made=false; \n" .
4299 " for (var options_index=0; options_index < multi_select.length; options_index++) { " .
4300 " multi_choice_made=multi_choice_made || multi_select.options[options_index].selected; \n" .
4301 " } \n" .
4302 " if(!multi_choice_made)
4303 errMsgs[errMsgs.length] = " . js_escape(xl_layout_label($fldtitle)) . "; \n" .
4305 break;
4307 echo " }\n";
4309 } // End this layout, there may be more in the case of history.
4313 * DROPDOWN FOR FACILITIES
4315 * build a dropdown with all facilities
4317 * @param string $selected - name of the currently selected facility
4318 * use '0' for "unspecified facility"
4319 * use '' for "All facilities" (the default)
4320 * @param string $name - the name/id for select form (defaults to "form_facility")
4321 * @param boolean $allow_unspecified - include an option for "unspecified" facility
4322 * defaults to true
4323 * @return void - just echo the html encoded string
4325 * Note: This should become a data-type at some point, according to Brady
4327 function dropdown_facility(
4328 $selected = '',
4329 $name = 'form_facility',
4330 $allow_unspecified = true,
4331 $allow_allfacilities = true,
4332 $disabled = '',
4333 $onchange = '',
4334 $multiple = false
4337 global $facilityService;
4339 $have_selected = false;
4340 $fres = $facilityService->getAllFacility();
4341 $id = $name;
4343 if ($multiple) {
4344 $name = $name . "[]";
4346 echo " <select class='form-control";
4347 if ($multiple) {
4348 echo " select-dropdown";
4350 echo "' name='" . attr($name) . "' id='" . attr($id) . "'";
4351 if ($onchange) {
4352 echo " onchange='$onchange'";
4355 if ($multiple) {
4356 echo " multiple='multiple'";
4359 echo " $disabled>\n";
4361 if ($allow_allfacilities) {
4362 $option_value = '';
4363 $option_selected_attr = '';
4364 if ($selected == '') {
4365 $option_selected_attr = ' selected="selected"';
4366 $have_selected = true;
4369 $option_content = '-- ' . xl('All Facilities') . ' --';
4370 echo " <option value='" . attr($option_value) . "' $option_selected_attr>" . text($option_content) . "</option>\n";
4371 } elseif ($allow_unspecified) {
4372 $option_value = '0';
4373 $option_selected_attr = '';
4374 if ($selected == '0') {
4375 $option_selected_attr = ' selected="selected"';
4376 $have_selected = true;
4379 $option_content = '-- ' . xl('Unspecified') . ' --';
4380 echo " <option value='" . attr($option_value) . "' $option_selected_attr>" . text($option_content) . "</option>\n";
4383 foreach ($fres as $frow) {
4384 $facility_id = $frow['id'];
4385 $option_value = $facility_id;
4386 $option_selected_attr = '';
4387 if ($multiple) {
4388 $selectedValues = explode("|", $selected);
4390 if (in_array($facility_id, $selectedValues)) {
4391 $option_selected_attr = ' selected="selected"';
4392 $have_selected = true;
4394 } else {
4395 if ($selected == $facility_id) {
4396 $option_selected_attr = ' selected="selected"';
4397 $have_selected = true;
4401 $option_content = $frow['name'];
4402 echo " <option value='" . attr($option_value) . "' $option_selected_attr>" . text($option_content) . "</option>\n";
4405 if ($allow_unspecified && $allow_allfacilities) {
4406 $option_value = '0';
4407 $option_selected_attr = '';
4408 if ($selected == '0') {
4409 $option_selected_attr = ' selected="selected"';
4410 $have_selected = true;
4413 $option_content = '-- ' . xl('Unspecified') . ' --';
4414 echo " <option value='" . attr($option_value) . "' $option_selected_attr>" . text($option_content) . "</option>\n";
4417 if (!$have_selected && !$multiple) {
4418 $option_value = $selected;
4419 $option_label = '(' . xl('Do not change') . ')';
4420 $option_content = xl('Missing or Invalid');
4421 echo " <option value='" . attr($option_value) . "' label='" . attr($option_label) . "' selected='selected'>" . text($option_content) . "</option>\n";
4424 echo " </select>\n";
4427 // Expand Collapse Widget
4428 // This forms the header and functionality component of the widget. The information that is displayed
4429 // then follows this function followed by a closing div tag
4431 // $title is the title of the section (already translated)
4432 // $label is identifier used in the tag id's and sql columns
4433 // $buttonLabel is the button label text (already translated)
4434 // $buttonLink is the button link information
4435 // $buttonClass is any additional needed class elements for the button tag
4436 // $linkMethod is the button link method ('javascript' vs 'html')
4437 // $bodyClass is to set class(es) of the body
4438 // $auth is a flag to decide whether to show the button
4439 // $fixedWidth is to flag whether width is fixed
4440 // $forceExpandAlways is a flag to force the widget to always be expanded
4442 // TODO: Convert to accordion
4443 function expand_collapse_widget($title, $label, $buttonLabel, $buttonLink, $buttonClass, $linkMethod, $bodyClass, $auth, $fixedWidth, $forceExpandAlways = false)
4445 if ($fixedWidth) {
4446 echo "<div class='section-header'>";
4447 } else {
4448 echo "<div class='section-header-dynamic'>";
4451 echo "<table><tr>";
4452 if ($auth) {
4453 // show button, since authorized
4454 // first prepare class string
4455 if ($buttonClass) {
4456 $class_string = "btn btn-primary btn-sm " . $buttonClass;
4457 } else {
4458 $class_string = "btn btn-primary btn-sm";
4461 // next, create the link
4462 if ($linkMethod == "javascript") {
4463 echo "<td><a class='" . attr($class_string) . "' href='javascript:;' onclick='" . $buttonLink . "'";
4464 } else {
4465 echo "<td><a class='" . attr($class_string) . "' href='" . $buttonLink . "'";
4466 if (!isset($_SESSION['patient_portal_onsite_two'])) {
4467 // prevent an error from occuring when calling the function from the patient portal
4468 echo " onclick='top.restoreSession()'";
4472 echo "><span>" .
4473 text($buttonLabel) . "</span></a></td>";
4476 if ($forceExpandAlways) {
4477 // Special case to force the widget to always be expanded
4478 echo "<td><span class='text font-weight-bold'>" . text($title) . "</span>";
4479 $indicatorTag = "style='display: none'";
4482 $indicatorTag = isset($indicatorTag) ? $indicatorTag : "";
4483 echo "<td><a " . $indicatorTag . " href='javascript:;' class='small' onclick='toggleIndicator(this," .
4484 attr_js($label . "_ps_expand") . ")'><span class='text font-weight-bold'>";
4485 echo text($title) . "</span>";
4487 if (isset($_SESSION['patient_portal_onsite_two'])) {
4488 // collapse all entries in the patient portal
4489 $text = xl('expand');
4490 } elseif (getUserSetting($label . "_ps_expand")) {
4491 $text = xl('collapse');
4492 } else {
4493 $text = xl('expand');
4496 echo " (<span class='indicator'>" . text($text) .
4497 "</span>)</a></td>";
4498 echo "</tr></table>";
4499 echo "</div>";
4500 if ($forceExpandAlways) {
4501 // Special case to force the widget to always be expanded
4502 $styling = "";
4503 } elseif (isset($_SESSION['patient_portal_onsite_two'])) {
4504 // collapse all entries in the patient portal
4505 $styling = "style='display: none'";
4506 } elseif (getUserSetting($label . "_ps_expand")) {
4507 $styling = "";
4508 } else {
4509 $styling = "style='display: none'";
4512 if ($bodyClass) {
4513 $styling .= " class='" . attr($bodyClass) . "'";
4516 //next, create the first div tag to hold the information
4517 // note the code that calls this function will then place the ending div tag after the data
4518 echo "<div id='" . attr($label) . "_ps_expand' " . $styling . ">";
4521 //billing_facility fuction will give the dropdown list which contain billing faciliies.
4522 function billing_facility($name, $select)
4524 global $facilityService;
4526 $fres = $facilityService->getAllBillingLocations();
4527 echo " <select id='" . htmlspecialchars($name, ENT_QUOTES) . "' class='form-control' name='" . htmlspecialchars($name, ENT_QUOTES) . "'>";
4528 foreach ($fres as $facrow) {
4529 $selected = ( $facrow['id'] == $select ) ? 'selected="selected"' : '' ;
4530 echo "<option value=" . htmlspecialchars($facrow['id'], ENT_QUOTES) . " $selected>" . htmlspecialchars($facrow['name'], ENT_QUOTES) . "</option>";
4533 echo "</select>";
4536 // Generic function to get the translated title value for a particular list option.
4538 function getListItemTitle($list, $option)
4540 $row = sqlQuery("SELECT title FROM list_options WHERE " .
4541 "list_id = ? AND option_id = ? AND activity = 1", array($list, $option));
4542 if (empty($row['title'])) {
4543 return $option;
4546 return xl_list_label($row['title']);
4549 //function to get the translated title value in Patient Transactions
4550 function getLayoutTitle($list, $option)
4552 $row = sqlQuery("SELECT grp_title FROM layout_group_properties " .
4553 "WHERE grp_mapping = ? AND grp_form_id = ? ", array($list, $option));
4555 if (empty($row['grp_title'])) {
4556 return $option;
4558 return xl_list_label($row['grp_title']);
4560 //Added on 5-jun-2k14 (regarding get the smoking code descriptions)
4561 function getSmokeCodes()
4563 $smoking_codes_arr = array();
4564 $smoking_codes = sqlStatement("SELECT option_id,codes FROM list_options WHERE list_id='smoking_status' AND activity = 1");
4565 while ($codes_row = sqlFetchArray($smoking_codes)) {
4566 $smoking_codes_arr[$codes_row['option_id']] = $codes_row['codes'];
4569 return $smoking_codes_arr;
4572 // Get the current value for a layout based form field.
4573 // Depending on options this might come from lbf_data, patient_data,
4574 // form_encounter, shared_attributes or elsewhere.
4575 // Returns FALSE if the field ID is invalid (layout error).
4577 function lbf_current_value($frow, $formid, $encounter)
4579 global $pid;
4580 $formname = $frow['form_id'];
4581 $field_id = $frow['field_id'];
4582 $source = $frow['source'];
4583 $currvalue = '';
4584 $deffname = $formname . '_default_' . $field_id;
4585 if ($source == 'D' || $source == 'H') {
4586 // Get from patient_data, employer_data or history_data.
4587 if ($source == 'H') {
4588 $table = 'history_data';
4589 $orderby = 'ORDER BY date DESC LIMIT 1';
4590 } elseif (strpos($field_id, 'em_') === 0) {
4591 $field_id = substr($field_id, 3);
4592 $table = 'employer_data';
4593 $orderby = 'ORDER BY date DESC LIMIT 1';
4594 } else {
4595 $table = 'patient_data';
4596 $orderby = '';
4599 // It is an error if the field does not exist, but don't crash.
4600 $tmp = sqlQuery("SHOW COLUMNS FROM " . escape_table_name($table) . " WHERE Field = ?", array($field_id));
4601 if (empty($tmp)) {
4602 return '*?*';
4605 $pdrow = sqlQuery("SELECT `$field_id` AS field_value FROM " . escape_table_name($table) . " WHERE pid = ? $orderby", array($pid));
4606 if (isset($pdrow)) {
4607 $currvalue = $pdrow['field_value'];
4609 } elseif ($source == 'E') {
4610 $sarow = false;
4611 if ($encounter) {
4612 // Get value from shared_attributes of the current encounter.
4613 $sarow = sqlQuery(
4614 "SELECT field_value FROM shared_attributes WHERE " .
4615 "pid = ? AND encounter = ? AND field_id = ?",
4616 array($pid, $encounter, $field_id)
4618 if (!empty($sarow)) {
4619 $currvalue = $sarow['field_value'];
4621 } elseif ($formid) {
4622 // Get from shared_attributes of the encounter that this form is linked to.
4623 // Note the importance of having an index on forms.form_id.
4624 $sarow = sqlQuery(
4625 "SELECT sa.field_value " .
4626 "FROM forms AS f, shared_attributes AS sa WHERE " .
4627 "f.form_id = ? AND f.formdir = ? AND f.deleted = 0 AND " .
4628 "sa.pid = f.pid AND sa.encounter = f.encounter AND sa.field_id = ?",
4629 array($formid, $formname, $field_id)
4631 if (!empty($sarow)) {
4632 $currvalue = $sarow['field_value'];
4634 } else {
4635 // New form and encounter not available, this should not happen.
4637 if (empty($sarow) && !$formid) {
4638 // New form, see if there is a custom default from a plugin.
4639 if (function_exists($deffname)) {
4640 $currvalue = call_user_func($deffname);
4643 } elseif ($source == 'V') {
4644 if ($encounter) {
4645 // Get value from the current encounter's form_encounter.
4646 $ferow = sqlQuery(
4647 "SELECT * FROM form_encounter WHERE " .
4648 "pid = ? AND encounter = ?",
4649 array($pid, $encounter)
4651 if (isset($ferow[$field_id])) {
4652 $currvalue = $ferow[$field_id];
4654 } elseif ($formid) {
4655 // Get value from the form_encounter that this form is linked to.
4656 $ferow = sqlQuery(
4657 "SELECT fe.* " .
4658 "FROM forms AS f, form_encounter AS fe WHERE " .
4659 "f.form_id = ? AND f.formdir = ? AND f.deleted = 0 AND " .
4660 "fe.pid = f.pid AND fe.encounter = f.encounter",
4661 array($formid, $formname)
4663 if (isset($ferow[$field_id])) {
4664 $currvalue = $ferow[$field_id];
4666 } else {
4667 // New form and encounter not available, this should not happen.
4669 } elseif ($formid) {
4670 // This is a normal form field.
4671 $ldrow = sqlQuery("SELECT field_value FROM lbf_data WHERE " .
4672 "form_id = ? AND field_id = ?", array($formid, $field_id));
4673 if (!empty($ldrow)) {
4674 $currvalue = $ldrow['field_value'];
4676 } else {
4677 // New form, see if there is a custom default from a plugin.
4678 if (function_exists($deffname)) {
4679 $currvalue = call_user_func($deffname);
4683 return $currvalue;
4686 function signer_head()
4688 return <<<EOD
4689 <link href="{$GLOBALS['web_root']}/portal/sign/css/signer_modal.css?v={$GLOBALS['v_js_includes']}" rel="stylesheet"/>
4690 <script src="{$GLOBALS['web_root']}/portal/sign/assets/signature_pad.umd.js?v={$GLOBALS['v_js_includes']}"></script>
4691 <script src="{$GLOBALS['web_root']}/portal/sign/assets/signer_api.js?v={$GLOBALS['v_js_includes']}"></script>
4692 EOD;
4695 // This returns stuff that needs to go into the <head> section of a caller using
4696 // the drawable image field type in a form.
4697 // A TRUE argument makes the widget controls smaller.
4699 function lbf_canvas_head($small = true)
4701 $s = <<<EOD
4702 <link href="{$GLOBALS['assets_static_relative']}/literallycanvas/css/literallycanvas.css" rel="stylesheet" />
4703 <script src="{$GLOBALS['assets_static_relative']}/react/build/react-with-addons.min.js"></script>
4704 <script src="{$GLOBALS['assets_static_relative']}/react/build/react-dom.min.js"></script>
4705 <script src="{$GLOBALS['assets_static_relative']}/literallycanvas/js/literallycanvas.min.js"></script>
4706 EOD;
4707 if ($small) {
4708 $s .= <<<EOD
4709 <style>
4710 /* Custom LiterallyCanvas styling.
4711 * This makes the widget 25% less tall and adjusts some other things accordingly.
4713 .literally {
4714 min-height: 100%;
4715 min-width: 300px; /* Was 400, unspecified */
4717 .literally .lc-picker .toolbar-button {
4718 width: 20px;
4719 height: 20px;
4720 line-height: 20px; /* Was 26, 26, 26 */
4722 .literally .color-well {
4723 font-size: 8px;
4724 width: 49px; /* Was 10, 60 */
4726 .literally .color-well-color-container {
4727 width: 21px;
4728 height: 21px; /* Was 28, 28 */
4730 .literally .lc-picker {
4731 width: 50px; /* Was 61 */
4733 .literally .lc-drawing.with-gui {
4734 left: 50px; /* Was 61 */
4736 .literally .lc-options {
4737 left: 50px; /* Was 61 */
4739 .literally .color-picker-popup {
4740 left: 49px;
4741 bottom: 0px; /* Was 60, 31 */
4743 </style>
4744 EOD;
4747 return $s;
4751 * Test if modifier($test) is in array of options for data type.
4753 * @param json array $options ["G","P","T"], ["G"] or could be legacy string with form "GPT", "G", "012"
4754 * @param string $test
4755 * @return boolean
4757 function isOption($options, $test)
4759 if (empty($options) || !isset($test) || $options == "null") {
4760 return false; // why bother?
4762 if (strpos($options, ',') === false) { // not json array of modifiers.
4763 // could be string of char's or single element of json ["RO"] or "TP" or "P" e.t.c.
4764 json_decode($options, true); // test if options json. json_last_error() will return JSON_ERROR_SYNTAX if not.
4765 // if of form ["RO"] (single modifier) means not legacy so continue on.
4766 if (is_string($options) && (json_last_error() !== JSON_ERROR_NONE)) { // nope, it's string.
4767 $t = str_split(trim($options)); // very good chance it's legacy modifier string.
4768 $options = json_encode($t); // make it json array to convert from legacy to new modifier json schema.
4772 $options = json_decode($options, true); // all should now be json
4774 return is_array($options) && in_array($test, $options, true); // finally the truth!