6 * @link http://www.open-emr.org
7 * @author Jerry Padgett <sjpadgett@gmail.com>
8 * @copyright Copyright (c) 2016-2019 Jerry Padgett <sjpadgett@gmail.com>
9 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
11 require_once(dirname(__FILE__
) . '/../../interface/globals.php');
13 use OpenEMR\Common\Crypto\CryptoGen
;
14 use OpenEMR\Common\Logging\EventAuditLogger
;
16 class ApplicationTable
19 public function __construct()
25 * All DB Transactions take place
29 * @param array $params
32 * Logging True / False
33 * @param boolean $error
34 * Error Display True / False
37 public function zQuery($sql, $params = '', $log = false, $error = true)
43 $return = sqlStatement($sql, $params);
45 } catch (Exception
$e) {
47 $this->errorHandler($e, $sql, $params);
52 EventAuditLogger
::instance()->auditSQLEvent($sql, $result, $params);
58 public function getPortalAuditRec($recid)
63 $sql = "Select * From onsite_portal_activity Where id = ?";
64 $return = sqlStatementNoLog($sql, $recid);
66 } catch (Exception
$e) {
67 $this->errorHandler($e, $sql);
69 if ($result === true) {
70 return sqlFetchArray($return);
76 public function getPortalAudit($patientid, $action = 'review', $activity = 'profile', $status = 'waiting', $auditflg = 1, $rtn = 'last', $oelog = true, $error = true)
88 $sql = "Select * From onsite_portal_activity As pa Where pa.patient_id = ? And pa.activity = ? And pa.require_audit = ? ".
89 "And pa.status = ? And pa.pending_action = ? ORDER BY pa.date ASC LIMIT 1";
90 $return = sqlStatementNoLog($sql, $audit);
92 } catch (Exception
$e) {
94 $this->errorHandler($e, $sql, $audit);
99 EventAuditLogger
::instance()->auditSQLEvent($sql, $result, $audit);
102 if ($rtn == 'last') {
103 return sqlFetchArray($return);
109 * Function portalAudit
110 * All Portal audit Transactions log
111 * Hoping to work both ends, patient and user, from one or most two tables
114 * SQL Query Statment for actions will execute sql as normal for cases
115 * user auth is not required.
116 * @param array $params
117 * Parameters for actions
118 * @param array $auditvals
119 * Parameters of audit
120 * @param boolean $log
121 * openemr Logging True / False
122 * @param boolean $error
123 * Error Display True / False
124 * @param type audit array params for portal audits
126 * $audit['patient_id']="";
127 * $audit['activity']="";
128 * $audit['require_audit']="";
129 * $audit['pending_action']="";
130 * $audit['action_taken']="";
131 * $audit['status']="";
132 * $audit['narrative']="";
133 * $audit['table_action']=""; //auth user action sql to run after review
134 * $audit['table_args']=""; //auth user action data to run after review
135 * $audit['action_user']="";
136 * $audit['action_taken_time']="";
137 * $audit['checksum']="";
139 public function portalAudit($type = 'insert', $rec = '', array $auditvals, $oelog = true, $error = true)
144 if ($type != 'insert') {
145 $audit['date'] = $auditvals['date'] ?
$auditvals['date'] : date("Y-m-d H:i:s");
148 $audit['patient_id'] = $auditvals['patient_id'] ?
$auditvals['patient_id'] : $_SESSION['pid'];
149 $audit['activity'] = $auditvals['activity'] ?
$auditvals['activity'] : "";
150 $audit['require_audit'] = $auditvals['require_audit'] ?
$auditvals['require_audit'] : "";
151 $audit['pending_action'] = $auditvals['pending_action'] ?
$auditvals['pending_action'] : "";
152 $audit['action_taken'] = $auditvals['action_taken'] ?
$auditvals['action_taken'] : "";
153 $audit['status'] = $auditvals['status'] ?
$auditvals['status'] : "new";
154 $audit['narrative'] = $auditvals['narrative'] ?
$auditvals['narrative'] : "";
155 $audit['table_action'] = $auditvals['table_action'] ?
$auditvals['table_action'] : "";
156 if ($auditvals['activity'] == 'profile') {
157 $audit['table_args'] = serialize($auditvals['table_args']);
159 $audit['table_args'] = $auditvals['table_args'];
162 $audit['action_user'] = $auditvals['action_user'] ?
$auditvals['action_user'] : "";
163 $audit['action_taken_time'] = $auditvals['action_taken_time'] ?
$auditvals['action_taken_time'] : "";
164 $audit['checksum'] = $auditvals['checksum'] ?
$auditvals['checksum'] : "";
167 if ($type != 'update') {
168 $logsql = "INSERT INTO onsite_portal_activity".
169 "( date, patient_id, activity, require_audit, pending_action, action_taken, status, narrative,".
170 "table_action, table_args, action_user, action_taken_time, checksum) ".
171 "VALUES (NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
173 $logsql = "update onsite_portal_activity set date=?, patient_id=?, activity=?, require_audit=?,".
174 " pending_action=?, action_taken=?,status=?, narrative=?, table_action=?, table_args=?,".
175 "action_user=?, action_taken_time=?, checksum=? ";
176 $logsql .= "where id='" . add_escape_custom($rec) . "' And patient_id='" . add_escape_custom($audit['patient_id']) . "'";
179 $return = sqlStatementNoLog($logsql, $audit);
181 } catch (Exception
$e) {
183 $this->errorHandler($e, $logsql, $audit);
188 $this->portalLog('profile audit transaction', $audit['patient_id'], $logsql, $audit, $result, 'See portal audit activity');
189 //auditSQLEvent( $logsql, $result, $audit );
195 public function portalLog($event = '', $patient_id = null, $comments = "", $binds = '', $success = '1', $user_notes = '', $ccda_doc_id = 0)
197 $groupname = isset($GLOBALS['groupname']) ?
$GLOBALS['groupname'] : 'none';
198 $user = isset($_SESSION['portal_username']) ?
$_SESSION['portal_username'] : $_SESSION['authUser'];
199 $log_from = isset($_SESSION['portal_username']) ?
'onsite-portal' : 'portal-dashboard';
200 if (!isset($_SESSION['portal_username']) && !isset($_SESSION['authUser'])) {
201 $log_from = 'portal-login';
204 $user_notes .= isset($_SESSION['whereto']) ?
(' Module:' . $_SESSION['whereto']) : "";
206 $processed_binds = "";
207 if (is_array($binds)) {
209 foreach ($binds as $value_bind) {
211 $processed_binds .= "'" . add_escape_custom($value_bind) . "'";
214 $processed_binds .= ",'" . add_escape_custom($value_bind) . "'";
218 if (! empty($processed_binds)) {
219 $processed_binds = "(" . $processed_binds . ")";
220 $comments .= " " . $processed_binds;
224 $this->portalNewEvent($event, $user, $groupname, $success, $comments, $patient_id, $log_from, $user_notes, $ccda_doc_id);
227 * Function errorHandler
228 * All error display and log
229 * Display the Error, Line and File
230 * Same behavior of HelpfulDie fuction in OpenEMR
231 * Path /library/sql.inc
235 * @param array $binds
237 public function errorHandler($e, $sql, $binds = '')
239 $trace = $e->getTraceAsString();
240 $nLast = strpos($trace, '[internal function]');
241 $trace = substr($trace, 0, ( $nLast - 3 ));
244 $logMsg .= "\r Exception: " . self
::escapeHtml($e->getMessage());
245 } while ($e = $e->getPrevious());
249 $processedBinds = "";
250 if (is_array($binds)) {
252 foreach ($binds as $valueBind) {
254 $processedBinds .= "'" . $valueBind . "'";
257 $processedBinds .= ",'" . $valueBind . "'";
261 if (! empty($processedBinds)) {
262 $processedBinds = "(" . $processedBinds . ")";
266 echo '<pre><span style="color: red;">';
267 echo 'ERROR : ' . $logMsg;
269 echo 'SQL statement : ' . self
::escapeHtml($sql);
270 echo self
::escapeHtml($processedBinds);
271 echo '</span></pre>';
278 $logMsg .= "\n SQL statement : $sql" . $processedBinds;
279 $logMsg .= "\n $trace";
280 error_log("ERROR: " . htmlspecialchars($logMsg, ENT_QUOTES
), 0);
282 public function escapeHtml($string)
284 return htmlspecialchars($string, ENT_QUOTES
);
287 * Retrive the data format from GLOBALS
289 * @param Date format set in GLOBALS
290 * @return Date format in PHP
292 public function dateFormat($format)
294 if ($format == "0") {
295 $date_format = 'yyyy/mm/dd';
296 } else if ($format == 1) {
297 $date_format = 'mm/dd/yyyy';
298 } else if ($format == 2) {
299 $date_format = 'dd/mm/yyyy';
301 $date_format = $format;
307 * fixDate - Date Conversion Between Different Formats
309 * @param String $input_date
310 * Date to be converted
311 * @param String $date_format
314 public function fixDate($input_date, $output_format = null, $input_format = null)
320 $input_date = preg_replace('/T|Z/', ' ', $input_date);
322 $temp = explode(' ', $input_date); // split using space and consider the first portion, in case of date with time
323 $input_date = $temp[0];
325 $output_format = ApplicationTable
::dateFormat($output_format);
326 $input_format = ApplicationTable
::dateFormat($input_format);
328 preg_match("/[^ymd]/", $output_format, $date_seperator_output);
329 $seperator_output = $date_seperator_output[0];
330 $output_date_arr = explode($seperator_output, $output_format);
332 preg_match("/[^ymd]/", $input_format, $date_seperator_input);
333 $seperator_input = $date_seperator_input[0];
334 $input_date_array = explode($seperator_input, $input_format);
336 preg_match("/[^1234567890]/", $input_date, $date_seperator_input);
337 $seperator_input = $date_seperator_input[0];
338 $input_date_arr = explode($seperator_input, $input_date);
340 foreach ($output_date_arr as $key => $format) {
341 $index = array_search($format, $input_date_array);
342 $output_date_arr[$key] = $input_date_arr[$index];
345 $output_date = implode($seperator_output, $output_date_arr);
347 $output_date = $temp[1] ?
$output_date . " " . $temp[1] : $output_date; // append the time, if exists, with the new formatted date
352 * Using generate id function from OpenEMR sql.inc library file
353 * @param string $seqname table name containing sequence (default is adodbseq)
354 * @param integer $startID id to start with for a new sequence (default is 1)
355 * @return integer returns the sequence integer
357 public function generateSequenceID()
359 return generate_id();
361 public function portalNewEvent($event, $user, $groupname, $success, $comments = "", $patient_id = null, $log_from = '', $user_notes = "", $ccda_doc_id = 0)
363 $adodb = $GLOBALS['adodb']['db'];
364 $crt_user = isset($_SERVER['SSL_CLIENT_S_DN_CN']) ?
$_SERVER['SSL_CLIENT_S_DN_CN'] : null;
366 $encrypt_comment = 'No';
367 if (! empty($comments)) {
368 if ($GLOBALS["enable_auditlog_encryption"]) {
369 $cryptoGen = new CryptoGen();
370 $comments = $cryptoGen->encryptStandard($comments);
371 $encrypt_comment = 'Yes';
375 $sql = "insert into log ( date, event, user, groupname, success, comments, log_from, crt_user, patient_id, user_notes) " . "values ( NOW(), " . $adodb->qstr($event) . "," .
376 $adodb->qstr($user) . "," . $adodb->qstr($groupname) . "," . $adodb->qstr($success) . "," .
377 $adodb->qstr($comments) . "," . $adodb->qstr($log_from) . "," . $adodb->qstr($crt_user) . "," .
378 $adodb->qstr($patient_id) . "," . $adodb->qstr($user_notes) .")";
380 $ret = sqlInsertClean_audit($sql);
382 $last_log_id = $GLOBALS['adodb']['db']->Insert_ID();
383 $encryptLogQry = "INSERT INTO log_comment_encrypt (log_id, encrypt, checksum, version) " . " VALUES ( " . $adodb->qstr($last_log_id) . "," . $adodb->qstr($encrypt_comment) . "," . "'','3')";
384 sqlInsertClean_audit($encryptLogQry);
386 if (( $patient_id == "NULL" ) ||
( $patient_id == null )) {
390 EventAuditLogger
::instance()->send_atna_audit_msg($user, $groupname, $event, $patient_id, $success, $comments);