Portal and core fixups. (#3525)
[openemr.git] / interface / super / edit_globals.php
blobcf47f806898a388962b4cd15961951c2a23e4963
1 <?php
3 /**
4 * Script for the globals editor.
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @author Ranganath Pathak <pathak@scrs1.org>
11 * @author Jerry Padgett <sjpadgett@gmail.com>
12 * @copyright Copyright (c) 2010 Rod Roark <rod@sunsetsystems.com>
13 * @copyright Copyright (c) 2016-2019 Brady Miller <brady.g.miller@gmail.com>
14 * @copyright Copyright (c) 2019 Ranganath Pathak <pathak@scrs1.org>
15 * @copyright Copyright (c) 2020 Jerry Padgett <sjpadgett@gmail.com>
16 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
19 require_once("../globals.php");
20 require_once("../../custom/code_types.inc.php");
21 require_once("$srcdir/globals.inc.php");
22 require_once("$srcdir/user.inc");
23 require_once(__DIR__ . "/../../myportal/soap_service/portal_connectivity.php");
25 use OpenEMR\Common\Acl\AclMain;
26 use OpenEMR\Common\Crypto\CryptoGen;
27 use OpenEMR\Common\Csrf\CsrfUtils;
28 use OpenEMR\Common\Logging\EventAuditLogger;
29 use OpenEMR\Core\Header;
30 use OpenEMR\OeUI\OemrUI;
31 use Ramsey\Uuid\Uuid;
33 // Set up crypto object
34 $cryptoGen = new CryptoGen();
36 $userMode = (array_key_exists('mode', $_GET) && $_GET['mode'] == 'user');
38 if (!$userMode) {
39 // Check authorization.
40 $thisauth = AclMain::aclCheckCore('admin', 'super');
41 if (!$thisauth) {
42 die(xlt('Not authorized'));
46 function checkCreateCDB()
48 $globalsres = sqlStatement("SELECT gl_name, gl_index, gl_value FROM globals WHERE gl_name IN
49 ('couchdb_host','couchdb_user','couchdb_pass','couchdb_port','couchdb_dbase','document_storage_method')");
50 $options = array();
51 while ($globalsrow = sqlFetchArray($globalsres)) {
52 $GLOBALS[$globalsrow['gl_name']] = $globalsrow['gl_value'];
55 $directory_created = false;
56 if (!empty($GLOBALS['document_storage_method'])) {
57 // /documents/temp/ folder is required for CouchDB
58 if (!is_dir($GLOBALS['OE_SITE_DIR'] . '/documents/temp/')) {
59 $directory_created = mkdir($GLOBALS['OE_SITE_DIR'] . '/documents/temp/', 0777, true);
60 if (!$directory_created) {
61 echo xlt("Failed to create temporary folder. CouchDB will not work.");
65 $couch = new CouchDB();
66 if (!$couch->check_connection()) {
67 echo "<script type='text/javascript'>alert(" . xlj("CouchDB Connection Failed.") . ");</script>";
68 return false;
71 if ($GLOBALS['couchdb_host'] || $GLOBALS['couchdb_port'] || $GLOBALS['couchdb_dbase']) {
72 $couch->createDB($GLOBALS['couchdb_dbase']);
73 $couch->createView($GLOBALS['couchdb_dbase']);
77 return true;
80 /**
81 * Update background_services table for a specific service following globals save.
82 * @author EMR Direct
84 function updateBackgroundService($name, $active, $interval)
86 //order important here: next_run change dependent on _old_ value of execute_interval so it comes first
87 $sql = 'UPDATE background_services SET active=?, '
88 . 'next_run = next_run + INTERVAL (? - execute_interval) MINUTE, execute_interval=? WHERE name=?';
89 return sqlStatement($sql, array($active,$interval,$interval,$name));
92 /**
93 * Make any necessary changes to background_services table when globals are saved.
94 * To prevent an unexpected service call during startup or shutdown, follow these rules:
95 * 1. Any "startup" operations should occur _before_ the updateBackgroundService() call.
96 * 2. Any "shutdown" operations should occur _after_ the updateBackgroundService() call. If these operations
97 * would cause errors in a running service call, it would be best to make the shutdown function itself is
98 * a background service that is activated here, does nothing if active=1 or running=1 for the
99 * parent service. Then it deactivates itself by setting active=0 when it is done shutting the parent service
100 * down. This will prevent non-responsiveness to the user by waiting for a service to finish.
101 * 3. If any "previous" values for globals are required for startup/shutdown logic, they need to be
102 * copied to a temp variable before the while($globalsrow...) loop.
103 * @author EMR Direct
105 function checkBackgroundServices()
107 //load up any necessary globals
108 $bgservices = sqlStatement("SELECT gl_name, gl_index, gl_value FROM globals WHERE gl_name IN
109 ('phimail_enable','phimail_interval')");
110 while ($globalsrow = sqlFetchArray($bgservices)) {
111 $GLOBALS[$globalsrow['gl_name']] = $globalsrow['gl_value'];
114 //Set up phimail service
115 $phimail_active = empty($GLOBALS['phimail_enable']) ? '0' : '1';
116 $phimail_interval = max(0, (int) $GLOBALS['phimail_interval']);
117 updateBackgroundService('phimail', $phimail_active, $phimail_interval);
120 <!DOCTYPE html>
121 <html>
122 <head>
123 <?php
124 // If we are saving user_specific globals.
126 if (array_key_exists('form_save', $_POST) && $_POST['form_save'] && $userMode) {
127 //verify csrf
128 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
129 CsrfUtils::csrfNotVerified();
132 $i = 0;
133 foreach ($GLOBALS_METADATA as $grpname => $grparr) {
134 if (in_array($grpname, $USER_SPECIFIC_TABS)) {
135 foreach ($grparr as $fldid => $fldarr) {
136 if (in_array($fldid, $USER_SPECIFIC_GLOBALS)) {
137 list($fldname, $fldtype, $flddef, $flddesc) = $fldarr;
138 $label = "global:" . $fldid;
139 if ($fldtype == "encrypted") {
140 if (empty(trim($_POST["form_$i"]))) {
141 $fldvalue = '';
142 } else {
143 $fldvalue = $cryptoGen->encryptStandard(trim($_POST["form_$i"]));
145 } else {
146 $fldvalue = trim($_POST["form_$i"]);
148 setUserSetting($label, $fldvalue, $_SESSION['authUserID'], false);
149 if ($_POST["toggle_$i"] == "YES") {
150 removeUserSetting($label);
153 ++$i;
159 echo "<script type='text/javascript'>";
160 echo "if (parent.left_nav.location) {";
161 echo " parent.left_nav.location.reload();";
162 echo " parent.Title.location.reload();";
163 echo " if(self.name=='RTop'){";
164 echo " parent.RBot.location.reload();";
165 echo " }else{";
166 echo " parent.RTop.location.reload();";
167 echo " }";
168 echo "}";
169 echo "self.location.href='edit_globals.php?mode=user&unique=yes';";
170 echo "</script>";
173 if (array_key_exists('form_download', $_POST) && $_POST['form_download']) {
174 //verify csrf
175 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
176 CsrfUtils::csrfNotVerified();
179 $client = portal_connection();
180 try {
181 $response = $client->getPortalConnectionFiles($credentials);
182 } catch (SoapFault $e) {
183 error_log('SoapFault Error');
184 error_log(errorLogEscape(var_dump(get_object_vars($e))));
185 } catch (Exception $e) {
186 error_log('Exception Error');
187 error_log(errorLogEscape(var_dump(get_object_vars($e))));
190 if (array_key_exists('status', $response) && $response['status'] == "1") {//WEBSERVICE RETURNED VALUE SUCCESSFULLY
191 $tmpfilename = realpath(sys_get_temp_dir()) . "/" . date('YmdHis') . ".zip";
192 $fp = fopen($tmpfilename, "wb");
193 fwrite($fp, base64_decode($response['value']));
194 fclose($fp);
195 $practice_filename = $response['file_name'];//practicename.zip
196 ob_clean();
197 // Set headers
198 header("Cache-Control: public");
199 header("Content-Description: File Transfer");
200 header("Content-Disposition: attachment; filename=" . $practice_filename);
201 header("Content-Type: application/zip");
202 header("Content-Transfer-Encoding: binary");
203 // Read the file from disk
204 readfile($tmpfilename);
205 unlink($tmpfilename);
206 exit;
207 } else {//WEBSERVICE CALL FAILED AND RETURNED AN ERROR MESSAGE
208 ob_end_clean();
210 <script>
211 alert(<?php echo xlj('Offsite Portal web Service Failed') ?> + ":\\n" + <?php echo js_escape($response['value']); ?>);
212 </script>
213 <?php
218 <?php
219 // If we are saving main globals.
221 if (array_key_exists('form_save', $_POST) && $_POST['form_save'] && !$userMode) {
222 //verify csrf
223 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
224 CsrfUtils::csrfNotVerified();
227 // Aug 22, 2014: Ensoftek: For Auditable events and tamper-resistance (MU2)
228 // Check the current status of Audit Logging
229 $auditLogStatusFieldOld = $GLOBALS['enable_auditlog'];
230 $forceBreakglassLogStatusFieldOld = $GLOBALS['gbl_force_log_breakglass'];
233 * Compare form values with old database values.
234 * Only save if values differ. Improves speed.
237 // Get all the globals from DB
238 $old_globals = sqlGetAssoc('SELECT gl_name, gl_index, gl_value FROM `globals` ORDER BY gl_name, gl_index', false, true);
240 $i = 0;
241 foreach ($GLOBALS_METADATA as $grpname => $grparr) {
242 foreach ($grparr as $fldid => $fldarr) {
243 list($fldname, $fldtype, $flddef, $flddesc) = $fldarr;
244 if ($fldtype == 'pwd') {
245 $pass = sqlQuery("SELECT gl_value FROM globals WHERE gl_name = ?", array($fldid));
246 $fldvalueold = $pass['gl_value'];
249 /* Multiple choice fields - do not compare , overwrite */
250 if (!is_array($fldtype) && substr($fldtype, 0, 2) == 'm_') {
251 if (isset($_POST["form_$i"])) {
252 $fldindex = 0;
254 sqlStatement("DELETE FROM globals WHERE gl_name = ?", array( $fldid ));
256 foreach ($_POST["form_$i"] as $fldvalue) {
257 $fldvalue = trim($fldvalue);
258 sqlStatement('INSERT INTO `globals` ( gl_name, gl_index, gl_value ) VALUES ( ?,?,?)', array( $fldid, $fldindex, $fldvalue ));
259 ++$fldindex;
262 } else {
263 /* check value of single field. Don't update if the database holds the same value */
264 if (isset($_POST["form_$i"])) {
265 $fldvalue = trim($_POST["form_$i"]);
266 } else {
267 $fldvalue = "";
270 if ($fldtype == 'pwd') {
271 $fldvalue = $fldvalue ? SHA1($fldvalue) : $fldvalueold; // TODO: salted passwords?
274 if ($fldtype == 'encrypted') {
275 if (empty(trim($fldvalue))) {
276 $fldvalue = '';
277 } else {
278 $fldvalue = $cryptoGen->encryptStandard($fldvalue);
282 // We rely on the fact that set of keys in globals.inc === set of keys in `globals` table!
284 if (
285 !isset($old_globals[$fldid]) // if the key not found in database - update database
287 ( isset($old_globals[$fldid]) && $old_globals[ $fldid ]['gl_value'] !== $fldvalue ) // if the value in database is different
289 // special treatment for some vars
290 switch ($fldid) {
291 case 'first_day_week':
292 // update PostCalendar config as well
293 sqlStatement("UPDATE openemr_module_vars SET pn_value = ? WHERE pn_name = 'pcFirstDayOfWeek'", array($fldvalue));
294 break;
297 // Replace old values
298 sqlStatement('DELETE FROM `globals` WHERE gl_name = ?', array( $fldid ));
299 sqlStatement('INSERT INTO `globals` ( gl_name, gl_index, gl_value ) VALUES ( ?, ?, ? )', array( $fldid, 0, $fldvalue ));
300 } else {
301 //error_log("No need to update $fldid");
305 ++$i;
309 checkCreateCDB();
310 checkBackgroundServices();
312 // July 1, 2014: Ensoftek: For Auditable events and tamper-resistance (MU2)
313 // If Audit Logging status has changed, log it.
314 $auditLogStatusNew = sqlQuery("SELECT `gl_value` FROM `globals` WHERE `gl_name` = 'enable_auditlog'");
315 $auditLogStatusFieldNew = $auditLogStatusNew['gl_value'];
316 if ($auditLogStatusFieldOld != $auditLogStatusFieldNew) {
317 EventAuditLogger::instance()->auditSQLAuditTamper('enable_auditlog', $auditLogStatusFieldNew);
319 $forceBreakglassLogStatusNew = sqlQuery("SELECT `gl_value` FROM `globals` WHERE `gl_name` = 'gbl_force_log_breakglass'");
320 $forceBreakglassLogStatusFieldNew = $forceBreakglassLogStatusNew['gl_value'];
321 if ($forceBreakglassLogStatusFieldOld != $forceBreakglassLogStatusFieldNew) {
322 EventAuditLogger::instance()->auditSQLAuditTamper('gbl_force_log_breakglass', $forceBreakglassLogStatusFieldNew);
325 echo "<script>";
326 echo "if (parent.left_nav.location) {";
327 echo " parent.left_nav.location.reload();";
328 echo " parent.Title.location.reload();";
329 echo " if(self.name=='RTop'){";
330 echo " parent.RBot.location.reload();";
331 echo " }else{";
332 echo " parent.RTop.location.reload();";
333 echo " }";
334 echo "}";
335 echo "self.location.href='edit_globals.php?unique=yes';";
336 echo "</script>";
340 <?php if ($userMode) { ?>
341 <title><?php echo xlt('User Settings'); ?></title>
342 <?php } else { ?>
343 <title><?php echo xlt('Global Settings'); ?></title>
344 <?php } ?>
346 <?php Header::setupHeader(['common','jscolor']); ?>
348 <script>
349 function validate_file() {
350 $.ajax({
351 type: "POST",
352 url: "<?php echo $GLOBALS['webroot']?>/library/ajax/offsite_portal_ajax.php",
353 data: {
354 csrf_token_form: <?php echo js_escape(CsrfUtils::collectCsrfToken()); ?>,
355 action: 'check_file'
357 cache: false,
358 success: function(message) {
359 if (message == 'OK') {
360 document.getElementById('form_download').value = 1;
361 document.getElementById('file_error_message').innerHTML = '';
362 document.forms[0].submit();
363 } else {
364 document.getElementById('form_download').value = 0;
365 document.getElementById('file_error_message').innerHTML = message;
366 return false;
371 </script>
372 <style>
373 #oe-nav-ul.tabNav {
374 display: flex !important;
375 flex-flow: column !important;
378 #oe-nav-ul.tabNav.tabWidthFull {
379 width: 10%;
382 #oe-nav-ul.tabNav.tabWidthUser {
383 width: 12%;
386 #oe-nav-ul.tabNav.tabWidthWide {
387 width: 15%;
390 #oe-nav-ul.tabNav.tabWidthVertical {
391 width: 25%;
393 </style>
394 <?php
395 if ($userMode) {
396 $heading_title = xl('Edit User Settings');
397 } else {
398 $heading_title = xl('Edit Global Settings');
400 $arrOeUiSettings = array(
401 'heading_title' => $heading_title,
402 'include_patient_name' => false,// use only in appropriate pages
403 'expandable' => true,
404 'expandable_files' => array("edit_globals_xpd"),//all file names need suffix _xpd
405 'action' => "",//conceal, reveal, search, reset, link or back
406 'action_title' => "",
407 'action_href' => "",//only for actions - reset, link or back
408 'show_help_icon' => false,
409 'help_file_name' => ""
411 $oemr_ui = new OemrUI($arrOeUiSettings);
413 </head>
415 <body class="body_top m-0" <?php if ($userMode) {
416 echo 'style="min-width: 700px;"'; } ?>>
418 <div id="container_div" class="<?php echo $oemr_ui->oeContainer();?>">
419 <div class="row">
420 <div class="col-sm-12">
421 <div class="page-header mt-3">
422 <?php echo $oemr_ui->pageHeading() . "\r\n"; ?>
423 </div>
424 </div>
425 </div>
426 <div class="row">
427 <div class="col-sm-12">
428 <?php if ($userMode) { ?>
429 <form method='post' name='theform' id='theform' class='form-horizontal' action='edit_globals.php?mode=user' onsubmit='return top.restoreSession()'>
430 <?php } else { ?>
431 <form method='post' name='theform' id='theform' class='form-horizontal' action='edit_globals.php' onsubmit='return top.restoreSession()'>
432 <?php } ?>
433 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
434 <div class="clearfix">
435 <div class="btn-group oe-margin-b-10">
436 <button type='submit' class='btn btn-secondary btn-save oe-pull-toward' name='form_save' value='<?php echo xla('Save'); ?>'><?php echo xlt('Save'); ?></button>
437 </div>
438 <div class="input-group col-sm-4 oe-pull-away">
439 <?php // mdsupport - Optional server based searching mechanism for large number of fields on this screen.
440 if (!$userMode) {
441 $placeholder = xla('Search global settings');
442 } else {
443 $placeholder = xla('Search user settings');
446 <input name='srch_desc' id='srch_desc' class='form-control' type='text' placeholder='<?php echo $placeholder; ?>' value='<?php echo (!empty($_POST['srch_desc']) ? attr($_POST['srch_desc']) : '') ?>' />
447 <span class="input-group-append">
448 <button class="btn btn-secondary btn-search" type='submit' id='globals_form_search' name='form_search'><?php echo xlt('Search'); ?></button>
449 </span>
450 </div><!-- /input-group -->
451 </div>
452 <br />
453 <div id="globals-div">
454 <ul class="tabNav tabWidthWide" id="oe-nav-ul">
455 <?php
456 $i = 0;
457 foreach ($GLOBALS_METADATA as $grpname => $grparr) {
458 if (!$userMode || in_array($grpname, $USER_SPECIFIC_TABS)) {
459 echo " <li" . ($i ? "" : " class='current'") .
460 "><a href='#'>" .
461 xlt($grpname) . "</a></li>\n";
462 ++$i;
466 </ul>
467 <div class="tabContainer">
468 <?php
469 $i = 0;
470 $srch_item = 0;
471 foreach ($GLOBALS_METADATA as $grpname => $grparr) {
472 if (!$userMode || in_array($grpname, $USER_SPECIFIC_TABS)) {
473 echo " <div class='tab w-100 h-auto" . ($i ? "" : " current") . "' style='font-size: 0.9rem'>\n";
475 echo "<div class=''>";
476 $addendum = $grpname == 'Appearance' ? ' (*' . xl("need to logout/login after changing these settings") . ')' : '';
477 echo "<div class='col-sm-12 oe-global-tab-heading'><div class='oe-pull-toward' style='font-size: 1.4rem'>" . xlt($grpname) . " &nbsp;</div><div style='margin-top: 5px'>" . text($addendum) . "</div></div>";
478 echo "<div class='clearfix'></div>";
479 if ($userMode) {
480 echo "<div class='row'>";
481 echo "<div class='col-sm-4'>&nbsp</div>";
482 echo "<div class='col-sm-4 font-weight-bold'>" . xlt('User Specific Setting') . "</div>";
483 echo "<div class='col-sm-2 font-weight-bold'>" . xlt('Default Setting') . "</div>";
484 echo "<div class='col-sm-2 font-weight-bold'>" . xlt('Default') . "</div>";
485 echo "</div>";
488 foreach ($grparr as $fldid => $fldarr) {
489 if (!$userMode || in_array($fldid, $USER_SPECIFIC_GLOBALS)) {
490 list($fldname, $fldtype, $flddef, $flddesc) = $fldarr;
491 // mdsupport - Check for matches
492 $srch_cl = '';
493 $highlight_search = false;
495 if (!empty($_POST['srch_desc']) && (stristr(($fldname . $flddesc), $_POST['srch_desc']) !== false)) {
496 $srch_cl = ' srch';
497 $srch_item++;
498 $highlight_search = true;
501 // Most parameters will have a single value, but some will be arrays.
502 // Here we cater to both possibilities.
503 $glres = sqlStatement("SELECT gl_index, gl_value FROM globals WHERE " .
504 "gl_name = ? ORDER BY gl_index", array($fldid));
505 $glarr = array();
506 while ($glrow = sqlFetchArray($glres)) {
507 $glarr[] = $glrow;
510 // $fldvalue is meaningful only for the single-value cases.
511 $fldvalue = count($glarr) ? $glarr[0]['gl_value'] : $flddef;
513 // Collect user specific setting if mode set to user
514 $userSetting = "";
515 $settingDefault = "checked='checked'";
516 if ($userMode) {
517 $userSettingArray = sqlQuery("SELECT * FROM user_settings WHERE setting_user=? AND setting_label=?", array($_SESSION['authUserID'],"global:" . $fldid));
518 $userSetting = $userSettingArray['setting_value'];
519 $globalValue = $fldvalue;
520 if (!empty($userSettingArray)) {
521 $fldvalue = $userSetting;
522 $settingDefault = "";
526 if ($userMode) {
527 echo " <div class='row form-group" . $srch_cl . "'><div class='col-sm-4 font-weight-bold'>" . ($highlight_search ? '<mark>' : '') . text($fldname) . ($highlight_search ? '</mark>' : '') . "</div><div class='col-sm-4 oe-input' title='" . attr($flddesc) . "'>\n";
528 } else {
529 echo " <div class='row form-group" . $srch_cl . "'><div class='col-sm-6 font-weight-bold'>" . ($highlight_search ? '<mark>' : '') . text($fldname) . ($highlight_search ? '</mark>' : '') . "</div><div class='col-sm-6 oe-input' title='" . attr($flddesc) . "'>\n";
532 if (is_array($fldtype)) {
533 echo " <select class='form-control' name='form_$i' id='form_$i'>\n";
534 foreach ($fldtype as $key => $value) {
535 if ($userMode) {
536 if ($globalValue == $key) {
537 $globalTitle = $value;
541 echo " <option value='" . attr($key) . "'";
543 //Casting value to string so the comparison will be always the same type and the only thing that will check is the value
544 //Tried to use === but it will fail in already existing variables
545 if ((string)$key == (string)$fldvalue) {
546 echo " selected";
549 echo ">";
550 echo text($value);
551 echo "</option>\n";
553 echo " </select>\n";
554 } elseif ($fldtype == 'bool') {
555 if ($userMode) {
556 if ($globalValue == 1) {
557 $globalTitle = xlt('Checked');
558 } else {
559 $globalTitle = xlt('Not Checked');
562 echo " <input type='checkbox' class='checkbox' name='form_$i' id='form_$i' value='1'";
563 if ($fldvalue) {
564 echo " checked";
566 echo " />\n";
567 } elseif ($fldtype == 'num') {
568 if ($userMode) {
569 $globalTitle = $globalValue;
571 echo " <input type='text' class='form-control' name='form_$i' id='form_$i' " .
572 "maxlength='15' value='" . attr($fldvalue) . "' />\n";
573 } elseif ($fldtype == 'text') {
574 if ($userMode) {
575 $globalTitle = $globalValue;
577 echo " <input type='text' class='form-control' name='form_$i' id='form_$i' " .
578 "maxlength='255' value='" . attr($fldvalue) . "' />\n";
579 } elseif ($fldtype == 'if_empty_create_random_uuid') {
580 if ($userMode) {
581 $globalTitle = $globalValue;
583 if (empty($fldvalue)) {
584 // if empty, then create a random uuid
585 $uuid4 = Uuid::uuid4();
586 $fldvalue = $uuid4->toString();
588 echo " <input type='text' class='form-control' name='form_$i' id='form_$i' " .
589 "maxlength='255' value='" . attr($fldvalue) . "' />\n";
590 } elseif ($fldtype == 'encrypted') {
591 if (empty($fldvalue)) {
592 // empty value
593 $fldvalueDecrypted = '';
594 } elseif ($cryptoGen->cryptCheckStandard($fldvalue)) {
595 // normal behavior when not empty
596 $fldvalueDecrypted = $cryptoGen->decryptStandard($fldvalue);
597 } else {
598 // this is used when value has not yet been encrypted (only happens once when upgrading)
599 $fldvalueDecrypted = $fldvalue;
601 echo " <input type='text' class='form-control' name='form_$i' id='form_$i' " .
602 "maxlength='255' value='" . attr($fldvalueDecrypted) . "' />\n";
603 if ($userMode) {
604 if (empty($globalValue)) {
605 // empty value
606 $globalTitle = '';
607 } elseif ($cryptoGen->cryptCheckStandard($globalValue)) {
608 // normal behavior when not empty
609 $globalTitle = $cryptoGen->decryptStandard($globalValue);
610 } else {
611 // this is used when value has not yet been encrypted (only happens once when upgrading)
612 $globalTitle = $globalValue;
615 $fldvalueDecrypted = '';
616 } elseif ($fldtype == 'pwd') {
617 if ($userMode) {
618 $globalTitle = $globalValue;
620 echo " <input type='password' class='form-control' name='form_$i' " .
621 "maxlength='255' value='' />\n";
622 } elseif ($fldtype == 'pass') {
623 if ($userMode) {
624 $globalTitle = $globalValue;
626 echo " <input type='password' class='form-control' name='form_$i' " .
627 "maxlength='255' value='" . attr($fldvalue) . "' />\n";
628 } elseif ($fldtype == 'lang') {
629 $res = sqlStatement("SELECT * FROM lang_languages ORDER BY lang_description");
630 echo " <select class='form-control' name='form_$i' id='form_$i'>\n";
631 while ($row = sqlFetchArray($res)) {
632 echo " <option value='" . attr($row['lang_description']) . "'";
633 if ($row['lang_description'] == $fldvalue) {
634 echo " selected";
637 echo ">";
638 echo xlt($row['lang_description']);
639 echo "</option>\n";
642 echo " </select>\n";
643 } elseif ($fldtype == 'all_code_types') {
644 global $code_types;
645 echo " <select class='form-control' name='form_$i' id='form_$i'>\n";
646 foreach (array_keys($code_types) as $code_key) {
647 echo " <option value='" . attr($code_key) . "'";
648 if ($code_key == $fldvalue) {
649 echo " selected";
652 echo ">";
653 echo xlt($code_types[$code_key]['label']);
654 echo "</option>\n";
657 echo " </select>\n";
658 } elseif ($fldtype == 'm_lang') {
659 $res = sqlStatement("SELECT * FROM lang_languages ORDER BY lang_description");
660 echo " <select multiple class='form-control' name='form_{$i}[]' id='form_{$i}[]' size='3'>\n";
661 while ($row = sqlFetchArray($res)) {
662 echo " <option value='" . attr($row['lang_description']) . "'";
663 foreach ($glarr as $glrow) {
664 if ($glrow['gl_value'] == $row['lang_description']) {
665 echo " selected";
666 break;
669 echo ">";
670 echo xlt($row['lang_description']);
671 echo "</option>\n";
673 echo " </select>\n";
674 } elseif ($fldtype == 'color_code') {
675 if ($userMode) {
676 $globalTitle = $globalValue;
678 echo " <input type='text' class='form-control jscolor {hash:true}' name='form_$i' id='form_$i' " .
679 "maxlength='15' value='" . attr($fldvalue) . "' />" .
680 "<input type='button' value='" . xla('Default') . "' onclick=\"document.forms[0].form_$i.jscolor.fromString(" . attr_js($flddef) . ")\">\n";
681 } elseif ($fldtype == 'default_visit_category') {
682 $sql = "SELECT pc_catid, pc_catname, pc_cattype
683 FROM openemr_postcalendar_categories
684 WHERE pc_active = 1 ORDER BY pc_seq";
685 $result = sqlStatement($sql);
686 echo "<select class='form-control' name='form_{$i}' id='form_{$i}'>\n";
687 echo "<option value='_blank'>" . xlt('None{{Category}}') . "</option>";
688 while ($row = sqlFetchArray($result)) {
689 $catId = $row['pc_catid'];
690 $name = $row['pc_catname'];
691 if ($catId < 9 && $catId != "5") {
692 continue;
695 if ($row['pc_cattype'] == 3 && !$GLOBALS['enable_group_therapy']) {
696 continue;
699 $optionStr = '<option value="%pc_catid%"%selected%>%pc_catname%</option>';
700 $optionStr = str_replace("%pc_catid%", attr($catId), $optionStr);
701 $optionStr = str_replace("%pc_catname%", text(xl_appt_category($name)), $optionStr);
702 $selected = ($fldvalue == $catId) ? " selected" : "";
703 $optionStr = str_replace("%selected%", $selected, $optionStr);
704 echo $optionStr;
706 echo "</select>";
707 } elseif ($fldtype == 'css' || $fldtype == 'tabs_css') {
708 if ($userMode) {
709 $globalTitle = $globalValue;
711 $themedir = "$webserver_root/public/themes";
712 $dh = opendir($themedir);
713 if ($dh) {
714 // Collect styles
715 $styleArray = array();
716 while (false !== ($tfname = readdir($dh))) {
717 // Only show files that contain tabs_style_ or style_ as options
718 if ($fldtype == 'tabs_css') {
719 $patternStyle = 'tabs_style_';
720 } else {
721 // $fldtype == 'css'
722 $patternStyle = 'style_';
724 if (
725 $tfname == 'style_blue.css' ||
726 $tfname == 'style_pdf.css' ||
727 !preg_match("/^" . $patternStyle . ".*\.css$/", $tfname)
729 continue;
732 if ($fldtype == 'tabs_css') {
733 // Drop the "tabs_style_" part and any replace any underscores with spaces
734 $styleDisplayName = str_replace("_", " ", substr($tfname, 11));
735 } else { // $fldtype == 'css'
736 // Drop the "style_" part and any replace any underscores with spaces
737 $styleDisplayName = str_replace("_", " ", substr($tfname, 6));
739 // Strip the ".css" and uppercase the first character
740 $styleDisplayName = ucfirst(str_replace(".css", "", $styleDisplayName));
742 $styleArray[$tfname] = $styleDisplayName;
744 // Alphabetize styles
745 asort($styleArray);
746 // Generate style selector
747 echo "<select class='form-control' name='form_$i' id='form_$i'>\n";
748 foreach ($styleArray as $styleKey => $styleValue) {
749 echo "<option value='" . attr($styleKey) . "'";
750 if ($styleKey == $fldvalue) {
751 echo " selected";
753 echo ">";
754 echo text($styleValue);
755 echo "</option>\n";
757 echo "</select>\n";
759 closedir($dh);
760 } elseif ($fldtype == 'hour') {
761 if ($userMode) {
762 $globalTitle = $globalValue;
765 echo " <select class='form-control' name='form_$i' id='form_$i'>\n";
766 for ($h = 0; $h < 24; ++$h) {
767 echo "<option value='$h'";
768 if ($h == $fldvalue) {
769 echo " selected";
772 echo ">";
773 if ($h == 0) {
774 echo "12 AM";
775 } elseif ($h < 12) {
776 echo "$h AM";
777 } elseif ($h == 12) {
778 echo "12 PM";
779 } else {
780 echo ($h - 12) . " PM";
783 echo "</option>\n";
786 echo " </select>\n";
789 if ($userMode) {
790 echo " </div>\n";
791 echo "<div class='col-sm-2 text-danger'>" . text($globalTitle) . "</div>\n";
792 echo "<div class='col-sm-2 '><input type='checkbox' value='YES' name='toggle_" . $i . "' id='toggle_" . $i . "' " . $settingDefault . "/></div>\n";
793 if ($fldtype == 'encrypted') {
794 echo "<input type='hidden' id='globaldefault_" . $i . "' value='" . attr($globalTitle) . "'>\n";
795 } else {
796 echo "<input type='hidden' id='globaldefault_" . $i . "' value='" . attr($globalValue) . "'>\n";
798 echo "</div>\n";
799 } else {
800 echo " </div></div>\n";
802 ++$i;
805 if (trim(strtolower($fldid)) == 'portal_offsite_address_patient_link' && !empty($GLOBALS['portal_offsite_enable']) && !empty($GLOBALS['portal_offsite_providerid'])) {
806 echo "<div class='row'>";
807 echo "<div class='col-sm-12'>";
808 echo "<input type='hidden' name='form_download' id='form_download'>";
809 echo "<button onclick=\"return validate_file()\" type='button'>" . xlt('Download Offsite Portal Connection Files') . "</button>";
810 echo "<div id='file_error_message' class='alert alert-error'></div>";
811 echo "</div>";
812 echo "</div>";
816 echo "<div class='btn-group oe-margin-b-10'>" .
817 "<button type='submit' class='btn btn-secondary btn-save oe-pull-toward' name='form_save'" .
818 "value='" . xla('Save') . "'>" . xlt('Save') . "</button></div>";
819 echo "<div class='oe-pull-away oe-margin-t-10' style=''>" . xlt($grpname) . " &nbsp;<a href='#' class='text-dark text-decoration-none fa fa-lg fa-arrow-circle-up oe-help-redirect scroll' aria-hidden='true'></a></div><div class='clearfix'></div></div>";
820 echo " </div>\n";
824 </div><!--End of tabContainer div-->
825 </div><!--End of globals-div div-->
826 </form>
827 </div>
828 </div>
829 </div><!--End of container div-->
830 <?php $oemr_ui->oeBelowContainerDiv();?>
831 </div>
832 <?php
833 $post_srch_desc = $_POST['srch_desc'];
834 if (!empty($post_srch_desc) && $srch_item == 0) {
835 echo "<script>alert(" . js_escape($post_srch_desc . " - " . xl('search term was not found, please try another search')) . ");</script>";
839 <script>
840 $(function () {
841 tabbify();
842 <?php // mdsupport - Highlight search results ?>
843 $('.srch div.control-label').wrapInner("<mark></mark>");
844 $('.tab .row.srch :first-child').closest('.tab').each(function() {
845 $('.tabNav li:nth-child(' + ($(this).index() + 1) + ') a').wrapInner("<mark></mark>");
847 // Use the counter ($i) to make the form user friendly for user-specific globals use
848 <?php
849 if ($userMode) {
850 for ($j = 0; $j <= $i; $j++) { ?>
851 $("#form_<?php echo $j ?>").change(function() {
852 $("#toggle_<?php echo $j ?>").prop('checked', false);
854 $("#toggle_<?php echo $j ?>").change(function() {
855 if ($('#toggle_<?php echo $j ?>').prop('checked')) {
856 var defaultGlobal = $("#globaldefault_<?php echo $j ?>").val();
857 $("#form_<?php echo $j ?>").val(defaultGlobal);
860 <?php
865 $('.scroll').click(function() {
866 if ($(window).scrollTop() == 0) {
867 alert(<?php echo xlj("Already at the top of the page"); ?>);
868 } else {
869 window.parent.scrollTo({
870 top: 0,
871 behavior: 'smooth',
873 window.scrollTo({
874 top: 0,
875 behavior: 'smooth',
878 return false;
880 </script>
881 </body>
882 </html>