You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
371 lines
13 KiB
371 lines
13 KiB
2 years ago
|
<?php
|
||
|
|
||
|
/**
|
||
|
* Patient Portal
|
||
|
*
|
||
|
* @package OpenEMR
|
||
|
* @link http://www.open-emr.org
|
||
|
* @author Jerry Padgett <sjpadgett@gmail.com>
|
||
|
* @copyright Copyright (c) 2016-2019 Jerry Padgett <sjpadgett@gmail.com>
|
||
|
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
|
||
|
*/
|
||
|
|
||
|
require_once(dirname(__FILE__) . '/../../interface/globals.php');
|
||
|
|
||
|
use OpenEMR\Common\Crypto\CryptoGen;
|
||
|
use OpenEMR\Common\Logging\EventAuditLogger;
|
||
|
|
||
|
class ApplicationTable
|
||
|
{
|
||
|
public function __construct()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Function zQuery
|
||
|
* All DB Transactions take place
|
||
|
*
|
||
|
* @param String $sql
|
||
|
* SQL Query Statment
|
||
|
* @param array $params
|
||
|
* SQL Parameters
|
||
|
* @param boolean $log
|
||
|
* Logging True / False
|
||
|
* @param boolean $error
|
||
|
* Error Display True / False
|
||
|
* @return type
|
||
|
*/
|
||
|
public function zQuery($sql, $params = '', $log = false, $error = true)
|
||
|
{
|
||
|
$return = false;
|
||
|
$result = false;
|
||
|
|
||
|
try {
|
||
|
$return = sqlStatement($sql, $params);
|
||
|
$result = true;
|
||
|
} catch (Exception $e) {
|
||
|
if ($error) {
|
||
|
$this->errorHandler($e, $sql, $params);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($log) {
|
||
|
EventAuditLogger::instance()->auditSQLEvent($sql, $result, $params);
|
||
|
}
|
||
|
|
||
|
return $return;
|
||
|
}
|
||
|
|
||
|
public function getPortalAuditRec($recid)
|
||
|
{
|
||
|
$return = false;
|
||
|
$result = false;
|
||
|
try {
|
||
|
$sql = "Select * From onsite_portal_activity Where id = ?";
|
||
|
$return = sqlStatementNoLog($sql, $recid);
|
||
|
$result = true;
|
||
|
} catch (Exception $e) {
|
||
|
$this->errorHandler($e, $sql);
|
||
|
}
|
||
|
if ($result === true) {
|
||
|
return sqlFetchArray($return);
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function getPortalAudit($patientid, $action = 'review', $activity = 'profile', $status = 'waiting', $auditflg = 1, $rtn = 'last', $oelog = true, $error = true)
|
||
|
{
|
||
|
$return = false;
|
||
|
$result = false;
|
||
|
$audit = array (
|
||
|
$patientid,
|
||
|
$activity,
|
||
|
$auditflg,
|
||
|
$status,
|
||
|
$action
|
||
|
);
|
||
|
try {
|
||
|
$sql = "Select * From onsite_portal_activity As pa Where pa.patient_id = ? And pa.activity = ? And pa.require_audit = ? " .
|
||
|
"And pa.status = ? And pa.pending_action = ? ORDER BY pa.date ASC LIMIT 1";
|
||
|
$return = sqlStatementNoLog($sql, $audit);
|
||
|
$result = true;
|
||
|
} catch (Exception $e) {
|
||
|
if ($error) {
|
||
|
$this->errorHandler($e, $sql, $audit);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($oelog) {
|
||
|
EventAuditLogger::instance()->auditSQLEvent($sql, $result, $audit);
|
||
|
}
|
||
|
|
||
|
if ($rtn == 'last') {
|
||
|
return sqlFetchArray($return);
|
||
|
} else {
|
||
|
return $return;
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Function portalAudit
|
||
|
* All Portal audit Transactions log
|
||
|
* Hoping to work both ends, patient and user, from one or most two tables
|
||
|
*
|
||
|
* @param String $sql
|
||
|
* SQL Query Statment for actions will execute sql as normal for cases
|
||
|
* user auth is not required.
|
||
|
* @param array $params
|
||
|
* Parameters for actions
|
||
|
* @param array $auditvals
|
||
|
* Parameters of audit
|
||
|
* @param boolean $log
|
||
|
* openemr Logging True / False
|
||
|
* @param boolean $error
|
||
|
* Error Display True / False
|
||
|
* @param type audit array params for portal audits
|
||
|
* $audit = Array();
|
||
|
* $audit['patient_id']="";
|
||
|
* $audit['activity']="";
|
||
|
* $audit['require_audit']="";
|
||
|
* $audit['pending_action']="";
|
||
|
* $audit['action_taken']="";
|
||
|
* $audit['status']="";
|
||
|
* $audit['narrative']="";
|
||
|
* $audit['table_action']=""; //auth user action sql to run after review
|
||
|
* $audit['table_args']=""; //auth user action data to run after review
|
||
|
* $audit['action_user']="";
|
||
|
* $audit['action_taken_time']="";
|
||
|
* $audit['checksum']="";
|
||
|
*/
|
||
|
public function portalAudit(string $type = null, string $rec = null, array $auditvals, $oelog = true, $error = true)
|
||
|
{
|
||
|
$return = false;
|
||
|
$result = false;
|
||
|
$audit = array ();
|
||
|
if (!$type) {
|
||
|
$type = 'insert';
|
||
|
}
|
||
|
if ($type != 'insert') {
|
||
|
$audit['date'] = $auditvals['date'] ? $auditvals['date'] : date("Y-m-d H:i:s");
|
||
|
}
|
||
|
|
||
|
$audit['patient_id'] = $auditvals['patient_id'] ? $auditvals['patient_id'] : $_SESSION['pid'];
|
||
|
$audit['activity'] = $auditvals['activity'] ? $auditvals['activity'] : "";
|
||
|
$audit['require_audit'] = $auditvals['require_audit'] ? $auditvals['require_audit'] : "";
|
||
|
$audit['pending_action'] = $auditvals['pending_action'] ? $auditvals['pending_action'] : "";
|
||
|
$audit['action_taken'] = $auditvals['action_taken'] ? $auditvals['action_taken'] : "";
|
||
|
$audit['status'] = $auditvals['status'] ? $auditvals['status'] : "new";
|
||
|
$audit['narrative'] = $auditvals['narrative'] ? $auditvals['narrative'] : "";
|
||
|
$audit['table_action'] = $auditvals['table_action'] ? $auditvals['table_action'] : "";
|
||
|
if ($auditvals['activity'] == 'profile') {
|
||
|
$audit['table_args'] = serialize($auditvals['table_args']);
|
||
|
} else {
|
||
|
$audit['table_args'] = $auditvals['table_args'];
|
||
|
}
|
||
|
|
||
|
$audit['action_user'] = $auditvals['action_user'] ? $auditvals['action_user'] : "";
|
||
|
$audit['action_taken_time'] = $auditvals['action_taken_time'] ? $auditvals['action_taken_time'] : "";
|
||
|
$audit['checksum'] = $auditvals['checksum'] ? $auditvals['checksum'] : "";
|
||
|
|
||
|
try {
|
||
|
if ($type != 'update') {
|
||
|
$logsql = "INSERT INTO onsite_portal_activity" .
|
||
|
"( date, patient_id, activity, require_audit, pending_action, action_taken, status, narrative," .
|
||
|
"table_action, table_args, action_user, action_taken_time, checksum) " .
|
||
|
"VALUES (NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||
|
} else {
|
||
|
$logsql = "update onsite_portal_activity set date=?, patient_id=?, activity=?, require_audit=?," .
|
||
|
" pending_action=?, action_taken=?,status=?, narrative=?, table_action=?, table_args=?," .
|
||
|
"action_user=?, action_taken_time=?, checksum=? ";
|
||
|
$logsql .= "where id='" . add_escape_custom($rec) . "' And patient_id='" . add_escape_custom($audit['patient_id']) . "'";
|
||
|
}
|
||
|
|
||
|
$return = sqlStatementNoLog($logsql, $audit);
|
||
|
$result = true;
|
||
|
} catch (Exception $e) {
|
||
|
if ($error) {
|
||
|
$this->errorHandler($e, $logsql, $audit);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($oelog) {
|
||
|
$this->portalLog('profile audit transaction', $audit['patient_id'], $logsql, $audit, $result, 'See portal audit activity');
|
||
|
//auditSQLEvent( $logsql, $result, $audit );
|
||
|
}
|
||
|
|
||
|
return $return;
|
||
|
}
|
||
|
|
||
|
public function portalLog($event = '', $patient_id = null, $comments = "", $binds = '', $success = '1', $user_notes = '', $ccda_doc_id = 0)
|
||
|
{
|
||
|
$groupname = isset($GLOBALS['groupname']) ? $GLOBALS['groupname'] : 'none';
|
||
|
$user = isset($_SESSION['portal_username']) ? $_SESSION['portal_username'] : $_SESSION['authUser'];
|
||
|
$log_from = isset($_SESSION['portal_username']) ? 'onsite-portal' : 'portal-dashboard';
|
||
|
if (!isset($_SESSION['portal_username']) && !isset($_SESSION['authUser'])) {
|
||
|
$log_from = 'portal-login';
|
||
|
}
|
||
|
|
||
|
$user_notes .= isset($_SESSION['whereto']) ? (' Module:' . $_SESSION['whereto']) : "";
|
||
|
|
||
|
$processed_binds = "";
|
||
|
if (is_array($binds)) {
|
||
|
$first_loop = true;
|
||
|
foreach ($binds as $value_bind) {
|
||
|
if ($first_loop) {
|
||
|
$processed_binds .= "'" . add_escape_custom($value_bind) . "'";
|
||
|
$first_loop = false;
|
||
|
} else {
|
||
|
$processed_binds .= ",'" . add_escape_custom($value_bind) . "'";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (! empty($processed_binds)) {
|
||
|
$processed_binds = "(" . $processed_binds . ")";
|
||
|
$comments .= " " . $processed_binds;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$this->portalNewEvent($event, $user, $groupname, $success, $comments, $patient_id, $log_from, $user_notes, $ccda_doc_id);
|
||
|
}
|
||
|
/**
|
||
|
* Function errorHandler
|
||
|
* All error display and log
|
||
|
* Display the Error, Line and File
|
||
|
* Same behavior of HelpfulDie fuction in OpenEMR
|
||
|
* Path /library/sql.inc
|
||
|
*
|
||
|
* @param type $e
|
||
|
* @param string $sql
|
||
|
* @param array $binds
|
||
|
*/
|
||
|
public function errorHandler($e, $sql, $binds = '')
|
||
|
{
|
||
|
$trace = $e->getTraceAsString();
|
||
|
$nLast = strpos($trace, '[internal function]');
|
||
|
$trace = substr($trace, 0, ( $nLast - 3 ));
|
||
|
$logMsg = '';
|
||
|
do {
|
||
|
$logMsg .= "\r Exception: " . self::escapeHtml($e->getMessage());
|
||
|
} while ($e = $e->getPrevious());
|
||
|
/**
|
||
|
* List all Params
|
||
|
*/
|
||
|
$processedBinds = "";
|
||
|
if (is_array($binds)) {
|
||
|
$firstLoop = true;
|
||
|
foreach ($binds as $valueBind) {
|
||
|
if ($firstLoop) {
|
||
|
$processedBinds .= "'" . $valueBind . "'";
|
||
|
$firstLoop = false;
|
||
|
} else {
|
||
|
$processedBinds .= ",'" . $valueBind . "'";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (! empty($processedBinds)) {
|
||
|
$processedBinds = "(" . $processedBinds . ")";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
echo '<pre><span style="color: red;">';
|
||
|
echo 'ERROR : ' . $logMsg;
|
||
|
echo "\r\n";
|
||
|
echo 'SQL statement : ' . self::escapeHtml($sql);
|
||
|
echo self::escapeHtml($processedBinds);
|
||
|
echo '</span></pre>';
|
||
|
echo '<pre>';
|
||
|
echo $trace;
|
||
|
echo '</pre>';
|
||
|
/**
|
||
|
* Error Logging
|
||
|
*/
|
||
|
$logMsg .= "\n SQL statement : $sql" . $processedBinds;
|
||
|
$logMsg .= "\n $trace";
|
||
|
error_log("ERROR: " . htmlspecialchars($logMsg, ENT_QUOTES), 0);
|
||
|
}
|
||
|
public function escapeHtml($string)
|
||
|
{
|
||
|
return htmlspecialchars($string, ENT_QUOTES);
|
||
|
}
|
||
|
/*
|
||
|
* Retrive the data format from GLOBALS
|
||
|
*
|
||
|
* @param Date format set in GLOBALS
|
||
|
* @return Date format in PHP
|
||
|
*/
|
||
|
public function dateFormat($format)
|
||
|
{
|
||
|
if ($format == "0") {
|
||
|
$date_format = 'yyyy/mm/dd';
|
||
|
} elseif ($format == 1) {
|
||
|
$date_format = 'mm/dd/yyyy';
|
||
|
} elseif ($format == 2) {
|
||
|
$date_format = 'dd/mm/yyyy';
|
||
|
} else {
|
||
|
$date_format = $format;
|
||
|
}
|
||
|
|
||
|
return $date_format;
|
||
|
}
|
||
|
/**
|
||
|
* fixDate - Date Conversion Between Different Formats
|
||
|
*
|
||
|
* @param String $input_date
|
||
|
* Date to be converted
|
||
|
* @param String $date_format
|
||
|
* Target Date Format
|
||
|
*/
|
||
|
public function fixDate($input_date, $output_format = null, $input_format = null)
|
||
|
{
|
||
|
if (! $input_date) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$input_date = preg_replace('/T|Z/', ' ', $input_date);
|
||
|
|
||
|
$temp = explode(' ', $input_date); // split using space and consider the first portion, in case of date with time
|
||
|
$input_date = $temp[0];
|
||
|
|
||
|
$output_format = ApplicationTable::dateFormat($output_format);
|
||
|
$input_format = ApplicationTable::dateFormat($input_format);
|
||
|
|
||
|
preg_match("/[^ymd]/", $output_format, $date_seperator_output);
|
||
|
$seperator_output = $date_seperator_output[0];
|
||
|
$output_date_arr = explode($seperator_output, $output_format);
|
||
|
|
||
|
preg_match("/[^ymd]/", $input_format, $date_seperator_input);
|
||
|
$seperator_input = $date_seperator_input[0];
|
||
|
$input_date_array = explode($seperator_input, $input_format);
|
||
|
|
||
|
preg_match("/[^1234567890]/", $input_date, $date_seperator_input);
|
||
|
$seperator_input = $date_seperator_input[0];
|
||
|
$input_date_arr = explode($seperator_input, $input_date);
|
||
|
|
||
|
foreach ($output_date_arr as $key => $format) {
|
||
|
$index = array_search($format, $input_date_array);
|
||
|
$output_date_arr[$key] = $input_date_arr[$index];
|
||
|
}
|
||
|
|
||
|
$output_date = implode($seperator_output, $output_date_arr);
|
||
|
|
||
|
$output_date = $temp[1] ? $output_date . " " . $temp[1] : $output_date; // append the time, if exists, with the new formatted date
|
||
|
return $output_date;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Using generate id function from OpenEMR sql.inc library file
|
||
|
* @param string $seqname table name containing sequence (default is adodbseq)
|
||
|
* @param integer $startID id to start with for a new sequence (default is 1)
|
||
|
* @return integer returns the sequence integer
|
||
|
*/
|
||
|
public function generateSequenceID()
|
||
|
{
|
||
|
return generate_id();
|
||
|
}
|
||
|
|
||
|
public function portalNewEvent($event, $user, $groupname, $success, $comments = "", $patient_id = null, $log_from = '', $user_notes = "", $ccda_doc_id = 0)
|
||
|
{
|
||
|
EventAuditLogger::instance()->recordLogItem($success, $event, $user, $groupname, $comments, $patient_id, null, $log_from, null, $ccda_doc_id, $user_notes);
|
||
|
}
|
||
|
}// app query class
|