* @author Brady Miller * @author Ken Chapple * @author Tony McCormick * @copyright Copyright (c) 2016-2020 Jerry Padgett * @copyright Copyright (c) 2019 Brady Miller * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ // Will start the (patient) portal OpenEMR session/cookie. require_once(dirname(__FILE__) . "/../../src/Common/Session/SessionUtil.php"); OpenEMR\Common\Session\SessionUtil::portalSessionStart(); //landing page definition -- where to go if something goes wrong $landingpage = "../index.php?site=" . urlencode($_SESSION['site_id']); // // kick out if patient not authenticated if (isset($_SESSION['pid']) && isset($_SESSION['patient_portal_onsite_two'])) { $pid = $_SESSION['pid']; $user = $_SESSION['sessionUser']; } else { OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy(); header('Location: ' . $landingpage . '&w'); exit; } $ignoreAuth_onsite_portal = true; global $ignoreAuth_onsite_portal; require_once('../../interface/globals.php'); require_once("$srcdir/forms.inc"); require_once("$srcdir/pnotes.inc"); require_once("$srcdir/patient.inc"); require_once("$srcdir/options.inc.php"); require_once("$srcdir/lists.inc"); require_once("$srcdir/report.inc"); require_once("$srcdir/classes/Document.class.php"); require_once("$srcdir/classes/Note.class.php"); require_once(dirname(__file__) . "/../../custom/code_types.inc.php"); require_once $GLOBALS['srcdir'] . '/ESign/Api.php'; require_once($GLOBALS["include_root"] . "/orders/single_order_results.inc.php"); require_once($GLOBALS['fileroot'] . "/controllers/C_Document.class.php"); use ESign\Api; use Mpdf\Mpdf; $staged_docs = array(); $archive_name = ''; // For those who care that this is the patient report. $GLOBALS['PATIENT_REPORT_ACTIVE'] = true; $PDF_OUTPUT = empty($_POST['pdf']) ? 0 : intval($_POST['pdf']); if ($PDF_OUTPUT) { $config_mpdf = array( 'tempDir' => $GLOBALS['MPDF_WRITE_DIR'], 'mode' => $GLOBALS['pdf_language'], 'format' => $GLOBALS['pdf_size'], 'default_font_size' => '9', 'default_font' => 'dejavusans', 'margin_left' => $GLOBALS['pdf_left_margin'], 'margin_right' => $GLOBALS['pdf_right_margin'], 'margin_top' => $GLOBALS['pdf_top_margin'], 'margin_bottom' => $GLOBALS['pdf_bottom_margin'], 'margin_header' => '', 'margin_footer' => '', 'orientation' => $GLOBALS['pdf_layout'], 'shrink_tables_to_fit' => 1, 'use_kwt' => true, 'autoScriptToLang' => true, 'keep_table_proportions' => true ); $pdf = new mPDF($config_mpdf); if ($_SESSION['language_direction'] == 'rtl') { $pdf->SetDirectionality('rtl'); } ob_start(); } // get various authorization levels $auth_notes_a = true; //AclMain::aclCheckCore('encounters', 'notes_a'); $auth_notes = true; //AclMain::aclCheckCore('encounters', 'notes'); $auth_coding_a = true; //AclMain::aclCheckCore('encounters', 'coding_a'); $auth_coding = true; //AclMain::aclCheckCore('encounters', 'coding'); $auth_relaxed = true; //AclMain::aclCheckCore('encounters', 'relaxed'); $auth_med = true; //AclMain::aclCheckCore('patients' , 'med'); $auth_demo = true; //AclMain::aclCheckCore('patients' , 'demo'); $esignApi = new Api(); $printable = empty($_GET['printable']) ? false : true; if ($PDF_OUTPUT) { $printable = true; } unset($_GET['printable']); // Number of columns in tables for insurance and encounter forms. $N = $PDF_OUTPUT ? 4 : 6; $first_issue = 1; function getContent() { global $web_root, $webserver_root; $content = ob_get_clean(); // Fix a nasty html2pdf bug - it ignores document root! // TODO - now use mPDF, so should test if still need this fix $i = 0; $wrlen = strlen($web_root); $wsrlen = strlen($webserver_root); while (true) { $i = stripos($content, " src='/", $i + 1); if ($i === false) { break; } if ( substr($content, $i + 6, $wrlen) === $web_root && substr($content, $i + 6, $wsrlen) !== $webserver_root ) { $content = substr($content, 0, $i + 6) . $webserver_root . substr($content, $i + 6 + $wrlen); } } return $content; } function postToGet($arin) { $getstring = ""; foreach ($arin as $key => $val) { if (is_array($val)) { foreach ($val as $k => $v) { $getstring .= urlencode($key . "[]") . "=" . urlencode($v) . "&"; } } else { $getstring .= urlencode($key) . "=" . urlencode($val) . "&"; } } return $getstring; } function report_basename($pid) { $ptd = getPatientData($pid, "fname,lname"); // escape names for pesky periods hyphen etc. $esc = $ptd['fname'] . '_' . $ptd['lname']; $esc = str_replace(array('.', ',', ' '), '', $esc); $fn = basename_international(strtolower($esc . '_' . $pid . '_' . xl('report'))); return array('base' => $fn, 'fname' => $ptd['fname'], 'lname' => $ptd['lname']); } function zip_content($source, $destination, $content = '', $create = true) { if (!extension_loaded('zip')) { return false; } $zip = new ZipArchive(); if ($create) { if (!$zip->open($destination, ZipArchive::CREATE)) { return false; } } else { if (!$zip->open($destination, ZipArchive::OVERWRITE)) { return false; } } if (is_file($source) === true) { $zip->addFromString(basename($source), file_get_contents($source)); } elseif (!empty($content)) { $zip->addFromString(basename($source), $content); } return $zip->close(); } ?>
0) { $ar = $_GET; } else { $ar = $_POST; } if ($printable) { /******************************************************************* $titleres = getPatientData($pid, "fname,lname,providerID"); $sql = "SELECT * FROM facility ORDER BY billing_location DESC LIMIT 1"; *******************************************************************/ $titleres = getPatientData($pid, "fname,lname,providerID,DATE_FORMAT(DOB,'%m/%d/%Y') as DOB_TS"); if ($_SESSION['pc_facility']) { $sql = "select * from facility where id=" . add_escape_custom($_SESSION['pc_facility']); } else { $sql = "SELECT * FROM facility ORDER BY billing_location DESC LIMIT 1"; } /******************************************************************/ $db = $GLOBALS['adodb']['db']; $results = $db->Execute($sql); $facility = array(); if (!$results->EOF) { $facility = $results->fields; } // Setup Headers and Footers for mPDF only Download // in HTML view it's just one line at the top of page 1 echo ' ' . xlt("PATIENT") . ':' . text($titleres['lname']) . ', ' . text($titleres['fname']) . ' - ' . text($titleres['DOB_TS']) . ' '; echo '' . xlt('Generated on') . ' ' . text(oeFormatShortDate()) . ' - ' . text($facility['name']) . ' ' . text($facility['phone']) . ''; $practice_logo = ""; $plogo = glob("$OE_SITE_DIR/images/*");// let's give the user a little say in image format. $plogo = preg_grep('~practice_logo\.(gif|png|jpg|jpeg)$~i', $plogo); if (!empty($plogo)) { $k = current(array_keys($plogo)); $practice_logo = $plogo[$k]; } ?>


,


:


$val) { if ($key == 'pdf') { continue; } // These are the top checkboxes (demographics, allergies, etc.). // if (stristr($key, "include_")) { if ($val == "demographics") { echo "
"; echo "
\n"; print "

" . xlt('Patient Data') . ":

"; // printRecDataOne($patient_data_array, getRecPatientData ($pid), $N); $result1 = getPatientData($pid); $result2 = getEmployerData($pid); echo " \n"; display_layout_rows('DEM', $result1, $result2); echo "
\n"; echo "
\n"; } elseif ($val == "history") { echo "
"; echo "
\n"; //if (AclMain::aclCheckCore('patients', 'med')) { print "

" . xlt('History Data') . ":

"; // printRecDataOne($history_data_array, getRecHistoryData ($pid), $N); $result1 = getHistoryData($pid); echo " \n"; display_layout_rows('HIS', $result1); echo "
\n"; //} echo "
"; // } elseif ($val == "employer") { // print "
".xl('Employer Data').":
"; // printRecDataOne($employer_data_array, getRecEmployerData ($pid), $N); } elseif ($val == "insurance") { echo "
"; echo "
"; echo "

" . xlt('Insurance Data') . ":

"; print "
" . xlt('Primary Insurance Data') . ":
"; printRecDataOne($insurance_data_array, getRecInsuranceData($pid, "primary"), $N); print "" . xlt('Secondary Insurance Data') . ":
"; printRecDataOne($insurance_data_array, getRecInsuranceData($pid, "secondary"), $N); print "" . xlt('Tertiary Insurance Data') . ":
"; printRecDataOne($insurance_data_array, getRecInsuranceData($pid, "tertiary"), $N); echo "
"; } elseif ($val == "billing") { echo "
"; echo "
"; print "

" . xlt('Billing Information') . ":

"; if ((!empty($ar['newpatient'])) && (count($ar['newpatient']) > 0)) { $billings = array(); echo ""; echo "\n"; $total = 0.00; $copays = 0.00; foreach ($ar['newpatient'] as $be) { $ta = explode(":", $be); $billing = getPatientBillingEncounter($pid, $ta[1]); $billings[] = $billing; foreach ($billing as $b) { echo "\n"; echo "\n"; echo "\n"; echo "\n"; $total += $b['fee']; if ($b['code_type'] == "COPAY") { $copays += $b['fee']; } } } echo ""; echo ""; echo ""; echo ""; echo "
" . xlt('Code') . "" . xlt('Fee') . "
"; echo text($b['code_type']) . ":\t" . text($b['code']) . " " . text($b['modifier']) . "   " . text($b['code_text']) . "     "; echo ""; echo text(oeFormatMoney($b['fee'])); echo "
 
" . xlt('Sub-Total') . "" . text(oeFormatMoney($total + abs($copays))) . "
" . xlt('Paid') . "" . text(oeFormatMoney(abs($copays))) . "
" . xlt('Total') . "" . text(oeFormatMoney($total)) . "
"; echo "
";
                //print_r($billings);
                echo "
"; } else { printPatientBilling($pid); } echo "
\n"; // end of billing DIV /**** } elseif ($val == "allergies") { print "Patient Allergies:
"; printListData($pid, "allergy", "1"); } elseif ($val == "medications") { print "Patient Medications:
"; printListData($pid, "medication", "1"); } elseif ($val == "medical_problems") { print "Patient Medical Problems:
"; printListData($pid, "medical_problem", "1"); ****/ } elseif ($val == "immunizations") { //if (AclMain::aclCheckCore('patients', 'med')) { echo "
"; echo "
\n"; print "

" . xlt('Patient Immunization') . ":

"; $sql = "select i1.immunization_id, i1.administered_date, substring(i1.note,1,20) as immunization_note, c.code_text_short " . " from immunizations i1 " . " left join code_types ct on ct.ct_key = 'CVX' " . " left join codes c on c.code_type = ct.ct_id AND i1.cvx_code = c.code " . " where i1.patient_id = ? and i1.added_erroneously = 0 " . " order by administered_date desc"; $result = sqlStatement($sql, [$pid]); while ($row = sqlFetchArray($result)) { // Figure out which name to use (ie. from cvx list or from the custom list) if ($GLOBALS['use_custom_immun_list']) { $vaccine_display = generate_display_field(array('data_type' => '1','list_id' => 'immunizations'), $row['immunization_id']); } else { if (!empty($row['code_text_short'])) { $vaccine_display = xlt($row['code_text_short']); } else { $vaccine_display = generate_display_field(array('data_type' => '1','list_id' => 'immunizations'), $row['immunization_id']); } } echo text($row['administered_date']) . " - " . $vaccine_display; if ($row['immunization_note']) { echo " - " . text($row['immunization_note']); } echo "
\n"; } echo "
\n"; //} // communication report } elseif ($val == "batchcom") { echo "
"; echo "
\n"; print "

" . xlt('Patient Communication sent') . ":

"; $sql = "SELECT concat( 'Messsage Type: ', batchcom.msg_type, ', Message Subject: ', batchcom.msg_subject, ', Sent on:', batchcom.msg_date_sent ) AS batchcom_data, batchcom.msg_text, concat( users.fname, users.lname ) AS user_name FROM `batchcom` JOIN `users` ON users.id = batchcom.sent_by WHERE batchcom.patient_id=?"; // echo $sql; $result = sqlStatement($sql, [$pid]); while ($row = sqlFetchArray($result)) { echo text($row['batchcom_data']) . ", " . xlt('By') . ": " . text($row['user_name']) . "
" . xlt('Text') . ":
" . text($row['msg_txt']) . "
\n"; } echo "
\n"; } elseif ($val == "notes") { echo "
"; echo "
\n"; print "

" . xlt('Patient Notes') . ":

"; printPatientNotes($pid); echo "
"; } elseif ($val == "transactions") { echo "
"; echo "
\n"; print "

" . xlt('Patient Transactions') . ":

"; printPatientTransactions($pid); echo "
"; } } else { // Documents is an array of checkboxes whose values are document IDs. // if ($key == "documents") { echo "
"; echo "
"; foreach ($val as $valkey => $valvalue) { $document_id = $valvalue; if (!is_numeric($document_id)) { continue; } $d = new Document($document_id); $fname = basename($d->get_name()); $extension = substr($fname, strrpos($fname, ".")); if (strtolower($extension) == '.zip' || strtolower($extension) == '.dcm') { continue; } echo "

" . xlt('Document') . " '" . text($fname) . "-" . text($d->get_id()) . "'

"; $notes = $d->get_notes(); if (!empty($notes)) { echo ""; } foreach ($notes as $note) { echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; } if (!empty($notes)) { echo "
' . xlt('Note') . ' #' . text($note->get_id()) . '
' . xlt('Date') . ': ' . text(oeFormatShortDate($note->get_date())) . '
' . text($note->get_note()) . '

"; } if ($extension == ".png" || $extension == ".jpg" || $extension == ".jpeg" || $extension == ".gif") { if ($PDF_OUTPUT) { // OK to link to the image file because it will be accessed by the // mPDF parser and not the browser. $tempDocC = new C_Document(); $fileTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true); // tmp file in ../documents/temp since need to be available via webroot $from_file_tmp_web_name = tempnam($GLOBALS['OE_SITE_DIR'] . '/documents/temp', "oer"); file_put_contents($from_file_tmp_web_name, $fileTemp); echo " 750) { echo " class='bigimage'"; } $tmp_files_remove[] = $from_file_tmp_web_name; echo " />

"; } else { echo "

"; } } else { // Most clinic documents are expected to be PDFs, and in that happy case // we can avoid the lengthy image conversion process. if ($PDF_OUTPUT && $extension == ".pdf") { echo "
\n"; // HTML to PDF conversion will fail if there are open tags. $content = getContent(); $pdf->writeHTML($content); // catch up with buffer. $err = ''; try { $tempDocC = new C_Document(); $pdfTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true); // tmp file in temporary_files_dir $from_file_tmp_name = tempnam($GLOBALS['temporary_files_dir'], "oer"); file_put_contents($from_file_tmp_name, $pdfTemp); $pagecount = $pdf->setSourceFile($from_file_tmp_name); for ($i = 0; $i < $pagecount; ++$i) { $pdf->AddPage(); $itpl = $pdf->importPage($i + 1); $pdf->useTemplate($itpl); } } catch (Exception $e) { // chances are PDF is > v1.4 and compression level not supported. // regardless, we're here so lets dispose in different way. // unlink($from_file_tmp_name); $archive_name = ($GLOBALS['temporary_files_dir'] . '/' . report_basename($pid)['base'] . ".zip"); $rtn = zip_content(basename($d->url), $archive_name, $pdfTemp); $err = "" . xlt('PDF Document Parse Error and not included. Check if included in archive.') . " : " . text($fname) . ""; $pdf->writeHTML($err); $staged_docs[] = array('path' => $d->url, 'fname' => $fname); } finally { unlink($from_file_tmp_name); // Make sure whatever follows is on a new page. Maybe! // okay if not a series of pdfs so if so need @todo if (empty($err)) { $pdf->AddPage(); } // Resume output buffering and the above-closed tags. ob_start(); echo "
\n"; } } else { if ($PDF_OUTPUT) { // OK to link to the image file because it will be accessed by the mPDF parser and not the browser. $tempDocC = new C_Document(); $fileTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, false, true, true); // tmp file in ../documents/temp since need to be available via webroot $from_file_tmp_web_name = tempnam($GLOBALS['OE_SITE_DIR'] . '/documents/temp', "oer"); file_put_contents($from_file_tmp_web_name, $fileTemp); echo "

"; $tmp_files_remove[] = $from_file_tmp_web_name; } else { echo "

"; } } } // end if-else } // end Documents loop echo "
"; } elseif ($key == "procedures") { // Procedures is an array of checkboxes whose values are procedure order IDs. if ($auth_med) { echo "
"; echo "
"; foreach ($val as $valkey => $poid) { echo "

" . xlt('Procedure Order') . ":

"; echo "
\n"; // Need to move the inline styles from this function to the stylesheet, but until // then we do it just for PDFs to avoid breaking anything. generate_order_report($poid, false, !$PDF_OUTPUT); echo "
\n"; } echo "
"; } } elseif (strpos($key, "issue_") === 0) { // display patient Issues if ($first_issue) { $prevIssueType = 'asdf1234!@#$'; // random junk so as to not match anything $first_issue = 0; echo "
"; echo "

" . xlt("Issues") . "

"; } preg_match('/^(.*)_(\d+)$/', $key, $res); $rowid = $res[2]; $irow = sqlQuery("SELECT type, title, comments, diagnosis " . "FROM lists WHERE id = ?", [$rowid]); $diagnosis = $irow['diagnosis']; if ($prevIssueType != $irow['type']) { // output a header for each Issue Type we encounter $disptype = $ISSUE_TYPES[$irow['type']][0]; echo "
" . attr($disptype) . ":
\n"; $prevIssueType = $irow['type']; } echo "
"; echo "" . text($irow['title']) . ":"; echo " " . text($irow['comments']) . "\n"; // Show issue's chief diagnosis and its description: if ($diagnosis) { echo "
"; echo "[" . xlt('Diagnosis') . "]
"; $dcodes = explode(";", $diagnosis); foreach ($dcodes as $dcode) { echo "" . text($dcode) . ": "; echo lookup_code_descriptions($dcode) . "
\n"; } //echo $diagnosis." -- ".lookup_code_descriptions($diagnosis)."\n"; echo "
"; } // Supplemental data for GCAC or Contraception issues. if ($irow['type'] == 'ippf_gcac') { echo " \n"; display_layout_rows('GCA', sqlQuery("SELECT * FROM lists_ippf_gcac WHERE id = ?", [$rowid])); echo "
\n"; } elseif ($irow['type'] == 'contraceptive') { echo " \n"; display_layout_rows('CON', sqlQuery("SELECT * FROM lists_ippf_con WHERE id = ?", [$rowid])); echo "
\n"; } echo "
\n"; //end the issue DIV } else { // we have an "encounter form" form field whose name is like // dirname_formid, with a value which is the encounter ID. // // display encounter forms, encoded as a POST variable // in the format: = if (($auth_notes_a || $auth_notes || $auth_coding_a || $auth_coding || $auth_med || $auth_relaxed)) { $form_encounter = $val; preg_match('/^(.*)_(\d+)$/', $key, $res); $form_id = $res[2]; $formres = getFormNameByFormdirAndFormid($res[1], $form_id); $dateres = getEncounterDateByEncounter($form_encounter); $formId = getFormIdByFormdirAndFormid($res[1], $form_id); if ($res[1] == 'newpatient') { echo "
\n"; echo "

" . xlt($formres["form_name"]) . "

"; } else { echo "
"; echo "

" . text(xl_form_title($formres["form_name"])) . "

"; } // show the encounter's date echo "(" . text(oeFormatSDFT(strtotime($dateres["date"]))) . ") "; if ($res[1] == 'newpatient') { // display the provider info echo ' ' . xlt('Provider') . ': ' . text(getProviderName(getProviderIdOfEncounter($form_encounter))); } echo "
\n"; // call the report function for the form ?>
createFormESign($formId, $res[1], $form_encounter); if ($esign->isLogViewable("report")) { $esign->renderLog(); } ?>
 " . xlt('Procedure') . ": " . text($brow['code']) . " " . text($brow['code_text']) . "
\n"; } } print "
"; } // end auth-check for encounter forms } // end if('issue_')... else... } // end if('include_')... else... } // end $ar loop if ($printable) { echo "

" . xlt('Signature') . ": _______________________________
"; } ?>
SetTitle(ucfirst($ptd['fname']) . ' ' . $ptd['lname'] . ' ' . xl('Id') . ':' . $pid . ' ' . xl('Report')); $isit_utf8 = preg_match('//u', $content); // quick check for invalid encoding if (!$isit_utf8) { if (function_exists('iconv')) { // if we can lets save the report $content = iconv("UTF-8", "UTF-8//IGNORE", $content); } else { // no sense going on. $die_str = xlt("Failed UTF8 encoding check! Could not automatically fix."); die($die_str); } } try { $pdf->writeHTML($content); // convert html } catch (Exception $exception) { die(text($exception)); } if ($PDF_OUTPUT == 1) { try { if (!empty($archive_name) && sizeof($staged_docs) > 0) { $rtn = zip_content(basename($fn), $archive_name, $pdf->Output($fn, 'S')); header('Content-Description: File Transfer'); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header("Cache-control: private"); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header("Content-Type: application/zip; charset=utf-8"); header("Content-Length: " . filesize($archive_name)); header('Content-Disposition: attachment; filename="' . basename($archive_name) . '"'); ob_end_clean(); @readfile($archive_name) or error_log("Archive temp file not found: " . $archive_name); unlink($archive_name); } else { $pdf->Output($fn, $GLOBALS['pdf_output']); // D = Download, I = Inline } } catch (Exception $exception) { die(text($exception)); } } foreach ($tmp_files_remove as $tmp_file) { // Remove the tmp files that were created unlink($tmp_file); } } else { ?>