php8 fixes part 1 (#3927)
[openemr.git] / interface / main / tabs / main.php
blob39e2894bba34e03649a0a6a9f2b1e01297864ac1
1 <?php
3 /**
4 * main.php
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Kevin Yeh <kevin.y@integralemr.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) 2016 Kevin Yeh <kevin.y@integralemr.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 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
18 $sessionAllowWrite = true;
19 require_once(__DIR__ . '/../../globals.php');
20 require_once $GLOBALS['srcdir'] . '/ESign/Api.php';
22 use Esign\Api;
23 use OpenEMR\Common\Acl\AclMain;
24 use OpenEMR\Common\Csrf\CsrfUtils;
25 use OpenEMR\Core\Header;
27 // Ensure token_main matches so this script can not be run by itself
28 // If do not match, then destroy the session and go back to login screen
29 if (
30 (empty($_SESSION['token_main_php'])) ||
31 (empty($_GET['token_main'])) ||
32 ($_GET['token_main'] != $_SESSION['token_main_php'])
33 ) {
34 // Below functions are from auth.inc, which is included in globals.php
35 authCloseSession();
36 authLoginScreen(false);
38 // this will not allow copy/paste of the link to this main.php page or a refresh of this main.php page
39 // (default behavior, however, this behavior can be turned off in the prevent_browser_refresh global)
40 if ($GLOBALS['prevent_browser_refresh'] > 1) {
41 unset($_SESSION['token_main_php']);
44 $esignApi = new Api();
46 <!DOCTYPE html>
47 <html>
48 <head>
49 <title><?php echo text($openemr_name); ?></title>
51 <script>
52 // This is to prevent users from losing data by refreshing or backing out of OpenEMR.
53 // (default behavior, however, this behavior can be turned off in the prevent_browser_refresh global)
54 <?php if ($GLOBALS['prevent_browser_refresh'] > 0) { ?>
55 window.addEventListener('beforeunload', (event) => {
56 if (!timed_out) {
57 event.returnValue = <?php echo xlj('Recommend not leaving or refreshing or you may lose data.'); ?>;
59 });
60 <?php } ?>
62 <?php require($GLOBALS['srcdir'] . "/restoreSession.php"); ?>
64 // Since this should be the parent window, this is to prevent calls to the
65 // window that opened this window. For example when a new window is opened
66 // from the Patient Flow Board or the Patient Finder.
67 window.opener = null;
68 window.name = "main";
70 // This flag indicates if another window or frame is trying to reload the login
71 // page to this top-level window. It is set by javascript returned by auth.inc
72 // and is checked by handlers of beforeunload events.
73 var timed_out = false;
74 // some globals to access using top.variable
75 // note that 'let' or 'const' does not allow global scope here.
76 // only use var
77 var isPortalEnabled = "<?php echo $GLOBALS['portal_onsite_two_enable'] ?>";
78 // Set the csrf_token_js token that is used in the below js/tabs_view_model.js script
79 var csrf_token_js = <?php echo js_escape(CsrfUtils::collectCsrfToken()); ?>;
80 var userDebug = <?php echo js_escape($GLOBALS['user_debug']); ?>;
81 var webroot_url = <?php echo js_escape($web_root); ?>;
82 var jsLanguageDirection = <?php echo js_escape($_SESSION['language_direction']); ?>;
83 var jsGlobals = {};
85 function goRepeaterServices() {
86 // Ensure send the skip_timeout_reset parameter to not count this as a manual entry in the
87 // timing out mechanism in OpenEMR.
89 // Send the skip_timeout_reset parameter to not count this as a manual entry in the
90 // timing out mechanism in OpenEMR. Notify App for various portal and reminder alerts.
91 // Combined portal and reminders ajax to fetch sjp 06-07-2020.
92 restoreSession();
93 let request = new FormData;
94 request.append("skip_timeout_reset", "1");
95 request.append("isPortal", isPortalEnabled);
96 request.append("csrf_token_form", csrf_token_js);
97 fetch(webroot_url + "/library/ajax/dated_reminders_counter.php", {
98 method: 'POST',
99 credentials: 'same-origin',
100 body: request
101 }).then((response) => {
102 if (response.status !== 200) {
103 console.log('Reminders start failed. Status Code: ' + response.status);
104 return;
106 return response.json();
107 }).then((data) => {
108 if (isPortalEnabled) {
109 let mail = data.mailCnt;
110 let chats = data.chatCnt;
111 let audits = data.auditCnt;
112 let payments = data.paymentCnt;
113 let total = data.total;
114 let enable = ((1 * mail) + (1 * audits)); // payments are among audits.
115 // Send portal counts to notification button model
116 // Will turn off button display if no notification!
117 app_view_model.application_data.user().portal(enable);
118 if (enable > 0) {
119 app_view_model.application_data.user().portalAlerts(total);
120 app_view_model.application_data.user().portalAudits(audits);
121 app_view_model.application_data.user().portalMail(mail);
122 app_view_model.application_data.user().portalChats(chats);
123 app_view_model.application_data.user().portalPayments(payments);
126 // Always send reminder count text to model
127 app_view_model.application_data.user().messages(data.reminderText);
128 }).catch(function(error) {
129 console.log('Request failed', error);
132 // run background-services
133 restoreSession();
134 request = new FormData;
135 request.append("skip_timeout_reset", "1");
136 request.append("ajax", "1");
137 request.append("csrf_token_form", csrf_token_js);
138 fetch(webroot_url + "/library/ajax/execute_background_services.php", {
139 method: 'POST',
140 credentials: 'same-origin',
141 body: request
142 }).then((response) => {
143 if (response.status !== 200) {
144 console.log('Background Service start failed. Status Code: ' + response.status);
146 }).catch(function(error) {
147 console.log('HTML Background Service start Request failed: ', error);
150 // auto run this function every 60 seconds
151 var repeater = setTimeout("goRepeaterServices()", 60000);
154 function isEncounterLocked(encounterId) {
155 <?php if ($esignApi->lockEncounters()) { ?>
156 // If encounter locking is enabled, make a syncronous call (async=false) to check the
157 // DB to see if the encounter is locked.
158 // Call restore session, just in case
159 // @TODO next clean up pass, turn into await promise then modify tabs_view_model.js L-309
160 restoreSession();
161 let url = webroot_url + "/interface/esign/index.php?module=encounter&method=esign_is_encounter_locked";
162 $.ajax({
163 type: 'POST',
164 url: url,
165 data: {encounterId: encounterId},
166 success: function (data) {
167 encounter_locked = data;
169 dataType: 'json',
170 async: false
172 return encounter_locked;
173 <?php } else { ?>
174 // If encounter locking isn't enabled then always return false
175 return false;
176 <?php } ?>
178 </script>
180 <?php Header::setupHeader(['knockout', 'tabs-theme', 'i18next']); ?>
181 <script>
182 // set up global translations for js
183 function setupI18n(lang_id) {
184 restoreSession();
185 return fetch(<?php echo js_escape($GLOBALS['webroot'])?> +"/library/ajax/i18n_generator.php?lang_id=" + encodeURIComponent(lang_id) + "&csrf_token_form=" + encodeURIComponent(csrf_token_js), {
186 credentials: 'same-origin',
187 method: 'GET'
188 }).then(response => response.json())
190 setupI18n(<?php echo js_escape($_SESSION['language_choice']); ?>).then(translationsJson => {
191 i18next.init({
192 lng: 'selected',
193 debug: false,
194 nsSeparator: false,
195 keySeparator: false,
196 resources: {
197 selected: {
198 translation: translationsJson
202 }).catch(error => {
203 console.log(error.message);
205 </script>
207 <script src="js/custom_bindings.js?v=<?php echo $v_js_includes; ?>"></script>
208 <script src="js/user_data_view_model.js?v=<?php echo $v_js_includes; ?>"></script>
209 <script src="js/patient_data_view_model.js?v=<?php echo $v_js_includes; ?>"></script>
210 <script src="js/therapy_group_data_view_model.js?v=<?php echo $v_js_includes; ?>"></script>
211 <script src="js/tabs_view_model.js?v=<?php echo $v_js_includes; ?>"></script>
212 <script src="js/application_view_model.js?v=<?php echo $v_js_includes; ?>"></script>
213 <script src="js/frame_proxies.js?v=<?php echo $v_js_includes; ?>"></script>
214 <script src="js/dialog_utils.js?v=<?php echo $v_js_includes; ?>"></script>
216 <?php
217 // Below code block is to prepare certain elements for deciding what links to show on the menu
219 // prepare newcrop globals that are used in creating the menu
220 if ($GLOBALS['erx_enable']) {
221 $newcrop_user_role_sql = sqlQuery("SELECT `newcrop_user_role` FROM `users` WHERE `username` = ?", array($_SESSION['authUser']));
222 $GLOBALS['newcrop_user_role'] = $newcrop_user_role_sql['newcrop_user_role'];
223 if ($GLOBALS['newcrop_user_role'] === 'erxadmin') {
224 $GLOBALS['newcrop_user_role_erxadmin'] = 1;
228 // prepare track anything to be used in creating the menu
229 $track_anything_sql = sqlQuery("SELECT `state` FROM `registry` WHERE `directory` = 'track_anything'");
230 $GLOBALS['track_anything_state'] = ($track_anything_sql['state'] ?? 0);
231 // prepare Issues popup link global that is used in creating the menu
232 $GLOBALS['allow_issue_menu_link'] = ((AclMain::aclCheckCore('encounters', 'notes', '', 'write') || AclMain::aclCheckCore('encounters', 'notes_a', '', 'write')) &&
233 AclMain::aclCheckCore('patients', 'med', '', 'write'));
236 <?php require_once("templates/tabs_template.php"); ?>
237 <?php require_once("templates/menu_template.php"); ?>
238 <?php require_once("templates/patient_data_template.php"); ?>
239 <?php require_once("templates/therapy_group_template.php"); ?>
240 <?php require_once("templates/user_data_template.php"); ?>
241 <?php require_once("menu/menu_json.php"); ?>
242 <?php $userQuery = sqlQuery("select * from users where username = ?", array($_SESSION['authUser'])); ?>
244 <script>
245 <?php if (!empty($_SESSION['frame1url']) && !empty($_SESSION['frame1target'])) { ?>
246 // Use session variables and tabStatus object to set up initial/default first tab
247 app_view_model.application_data.tabs.tabsList.push(new tabStatus(<?php echo xlj("Loading"); ?> +"...",<?php echo json_encode("../" . $_SESSION['frame1url']); ?>,<?php echo json_encode($_SESSION['frame1target']); ?>,<?php echo xlj("Loading"); ?> +" " + <?php echo json_encode($_SESSION['frame1label']); ?>, true, true, false));
248 <?php } ?>
250 <?php if (!empty($_SESSION['frame2url']) && !empty($_SESSION['frame2target'])) { ?>
251 // Use session variables and tabStatus object to set up initial/default second tab, if none is set in globals, this tab will not be displayed initially
252 app_view_model.application_data.tabs.tabsList.push(new tabStatus(<?php echo xlj("Loading"); ?> +"...",<?php echo json_encode("../" . $_SESSION['frame2url']); ?>,<?php echo json_encode($_SESSION['frame2target']); ?>,<?php echo xlj("Loading"); ?> +" " + <?php echo json_encode($_SESSION['frame2label']); ?>, true, false, false));
253 <?php } ?>
255 app_view_model.application_data.user(new user_data_view_model(<?php echo json_encode($_SESSION["authUser"])
256 . ',' . json_encode($userQuery['fname'])
257 . ',' . json_encode($userQuery['lname'])
258 . ',' . json_encode($_SESSION['authProvider']); ?>));
260 </script>
261 <style>
262 html, body {
263 width: max-content;
264 min-height: 100% !important;
265 height: 100% !important;
267 </style>
268 </head>
269 <body class="min-vw-100">
270 <!-- Below iframe is to support auto logout when timeout is reached -->
271 <iframe name="timeout" style="visibility:hidden; position:absolute; left:0; top:0; height:0; width:0; border:none;" src="timeout_iframe.php"></iframe>
272 <!-- Below iframe is to support logout, which needs to be run in an inner iframe to work as intended -->
273 <iframe name="logoutinnerframe" id="logoutinnerframe" style="visibility:hidden; position:absolute; left:0; top:0; height:0; width:0; border:none;" src="about:blank"></iframe>
274 <?php // mdsupport - app settings
275 $disp_mainBox = '';
276 if (isset($_SESSION['app1'])) {
277 $rs = sqlquery(
278 "SELECT title app_url FROM list_options WHERE activity=1 AND list_id=? AND option_id=?",
279 array('apps', $_SESSION['app1'])
281 if ($rs['app_url'] != "main/main_screen.php") {
282 echo '<iframe name="app1" src="../../' . attr($rs['app_url']) . '"
283 style="position: absolute; left: 0; top: 0; height: 100%; width: 100%; border: none;" />';
284 $disp_mainBox = 'style="display: none;"';
288 <div id="mainBox" <?php echo $disp_mainBox ?> >
289 <nav class="navbar navbar-expand-xl navbar-light bg-light py-0">
290 <a class="navbar-brand mt-2 mt-xl-0 mr-3 mr-xl-2" href="https://www.open-emr.org" title="OpenEMR <?php echo xla("Website"); ?>" rel="noopener" target="_blank">
291 <?php echo file_get_contents($GLOBALS['images_static_absolute'] . "/menu-logo.svg"); ?>
292 </a>
293 <button class="navbar-toggler mr-auto" type="button" data-toggle="collapse" data-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation">
294 <span class="navbar-toggler-icon"></span>
295 </button>
296 <div class="collapse navbar-collapse" id="mainMenu" data-bind="template: {name: 'menu-template', data: application_data}"></div>
297 <span id="userData" data-bind="template: {name: 'user-data-template', data: application_data}"></span>
298 </nav>
299 <div id="attendantData" class="body_title acck" data-bind="template: {name: app_view_model.attendant_template_type, data: application_data}">
300 </div>
302 <div class="body_title" id="tabs_div" data-bind="template: {name: 'tabs-controls', data: application_data}"></div>
304 <div class="mainFrames d-flex flex-row" id="mainFrames_div">
305 <div id="framesDisplay" data-bind="template: {name: 'tabs-frames', data: application_data}"></div>
306 </div>
307 </div>
308 <script>
309 ko.applyBindings(app_view_model);
311 $(function () {
312 $('.dropdown-toggle').dropdown();
313 goRepeaterServices();
314 $('#patient_caret').click(function () {
315 $('#attendantData').slideToggle();
316 $('#patient_caret').toggleClass('fa-caret-down').toggleClass('fa-caret-up');
318 if($('body').css('direction') == "rtl") {
319 $('.dropdown-menu-right').each(function() {
320 $(this).removeClass('dropdown-menu-right');
325 $(function () {
326 $('#logo_menu').focus();
328 $('#anySearchBox').keypress(function (event) {
329 if (event.which === 13 || event.keyCode === 13) {
330 event.preventDefault();
331 $('#search_globals').mousedown();
334 document.addEventListener('touchstart', {}); //specifically added for iOS devices, especially in iframes
335 </script>
336 </body>
337 </html>