fix: ccda zip import and php warnings and deprecations (#7416)
[openemr.git] / interface / patient_file / report / custom_report.php
blob193496032b8a5bde73c409f55c12d6be4e836512
1 <?php
3 /**
4 * Patient custom report.
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Brady Miller <brady.g.miller@gmail.com>
9 * @author Ken Chapple <ken@mi-squared.com>
10 * @author Tony McCormick <tony@mi-squared.com>
11 * @author Jerry Padgett <sjpadgett@gmail.com>
12 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
13 * @copyright Copyright (c) 2017-2020 Jerry Padgett <sjpadgett@gmail.com>
14 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
17 require_once("../../globals.php");
18 require_once("$srcdir/forms.inc.php");
19 require_once("$srcdir/pnotes.inc.php");
20 require_once("$srcdir/patient.inc.php");
21 require_once("$srcdir/options.inc.php");
22 require_once("$srcdir/lists.inc.php");
23 require_once("$srcdir/report.inc.php");
24 require_once(dirname(__file__) . "/../../../custom/code_types.inc.php");
25 require_once $GLOBALS['srcdir'] . '/ESign/Api.php';
26 require_once($GLOBALS["include_root"] . "/orders/single_order_results.inc.php");
27 require_once("$srcdir/appointments.inc.php");
28 require_once($GLOBALS['fileroot'] . "/controllers/C_Document.class.php");
30 use ESign\Api;
31 use Mpdf\Mpdf;
32 use OpenEMR\Common\Acl\AclMain;
33 use OpenEMR\Common\Twig\TwigContainer;
34 use OpenEMR\Core\Header;
35 use OpenEMR\MedicalDevice\MedicalDevice;
36 use OpenEMR\Pdf\Config_Mpdf;
37 use OpenEMR\Services\FacilityService;
39 if (!AclMain::aclCheckCore('patients', 'pat_rep')) {
40 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Custom Report")]);
41 exit;
44 $facilityService = new FacilityService();
46 $staged_docs = array();
47 $archive_name = '';
49 // For those who care that this is the patient report.
50 $GLOBALS['PATIENT_REPORT_ACTIVE'] = true;
52 $PDF_OUTPUT = empty($_POST['pdf']) ? 0 : intval($_POST['pdf']);
53 $PDF_FAX = empty($_POST['fax']) ? 0 : intval($_POST['fax']);
54 if ($PDF_FAX) {
55 $PDF_OUTPUT = 1;
58 if ($PDF_OUTPUT) {
59 $config_mpdf = Config_Mpdf::getConfigMpdf();
60 // special settings for patient custom report that are necessary for mpdf
61 $config_mpdf['margin_top'] = $config_mpdf['margin_top'] * 1.5;
62 $config_mpdf['margin_bottom'] = $config_mpdf['margin_bottom'] * 1.5;
63 $config_mpdf['margin_header'] = $GLOBALS['pdf_top_margin'];
64 $config_mpdf['margin_footer'] = $GLOBALS['pdf_bottom_margin'];
65 $pdf = new mPDF($config_mpdf);
66 if ($_SESSION['language_direction'] == 'rtl') {
67 $pdf->SetDirectionality('rtl');
69 ob_start();
70 } // end pdf conditional.
72 // get various authorization levels
73 $auth_notes_a = AclMain::aclCheckCore('encounters', 'notes_a');
74 $auth_notes = AclMain::aclCheckCore('encounters', 'notes');
75 $auth_coding_a = AclMain::aclCheckCore('encounters', 'coding_a');
76 $auth_coding = AclMain::aclCheckCore('encounters', 'coding');
77 $auth_relaxed = AclMain::aclCheckCore('encounters', 'relaxed');
78 $auth_med = AclMain::aclCheckCore('patients', 'med');
79 $auth_demo = AclMain::aclCheckCore('patients', 'demo');
81 $esignApi = new Api();
83 $printable = empty($_GET['printable']) ? false : true;
84 if ($PDF_OUTPUT) {
85 $printable = true;
88 unset($_GET['printable']);
90 // Number of columns in tables for insurance and encounter forms.
91 $N = $PDF_OUTPUT ? 4 : 6;
93 $first_issue = 1;
95 function getContent()
97 global $web_root, $webserver_root;
98 $content = ob_get_clean();
99 // Fix a nasty mPDF bug - it ignores document root!
100 $i = 0;
101 $wrlen = strlen($web_root);
102 $wsrlen = strlen($webserver_root);
103 while (true) {
104 $i = stripos($content, " src='/", $i + 1);
105 if ($i === false) {
106 break;
109 if (
110 substr($content, $i + 6, $wrlen) === $web_root &&
111 substr($content, $i + 6, $wsrlen) !== $webserver_root
113 $content = substr($content, 0, $i + 6) . $webserver_root . substr($content, $i + 6 + $wrlen);
117 return $content;
120 function postToGet($arin)
122 $getstring = "";
123 foreach ($arin as $key => $val) {
124 if (is_array($val)) {
125 foreach ($val as $k => $v) {
126 $getstring .= attr_url($key . "[]") . "=" . attr_url($v) . "&";
128 } else {
129 $getstring .= attr_url($key) . "=" . attr_url($val) . "&";
133 return $getstring;
136 function report_basename($pid)
138 $ptd = getPatientData($pid, "fname,lname");
139 // escape names for pesky periods hyphen etc.
140 $esc = $ptd['fname'] . '_' . $ptd['lname'];
141 $esc = str_replace(array('.', ',', ' '), '', $esc);
142 $fn = basename_international(strtolower($esc . '_' . $pid . '_' . xl('report')));
144 return array('base' => $fn, 'fname' => $ptd['fname'], 'lname' => $ptd['lname']);
147 function zip_content($source, $destination, $content = '', $create = true)
149 if (!extension_loaded('zip')) {
150 return false;
153 $zip = new ZipArchive();
154 if ($create) {
155 if (!$zip->open($destination, ZipArchive::CREATE)) {
156 return false;
158 } else {
159 if (!$zip->open($destination, ZipArchive::OVERWRITE)) {
160 return false;
164 if (is_file($source) === true) {
165 $zip->addFromString(basename($source), file_get_contents($source));
166 } elseif (!empty($content)) {
167 $zip->addFromString(basename($source), $content);
170 return $zip->close();
175 <?php if ($PDF_OUTPUT) { ?>
176 <?php Header::setupAssets(['pdf-style', 'esign-theme-only']); ?>
177 <?php } else { ?>
178 <html>
179 <head>
180 <?php Header::setupHeader(['esign-theme-only', 'search-highlight']); ?>
181 <?php } ?>
183 <?php // do not show stuff from report.php in forms that is encaspulated
184 // by div of navigateLink class. Specifically used for CAMOS, but
185 // can also be used by other forms that require output in the
186 // encounter listings output, but not in the custom report. ?>
188 <style>
189 div.navigateLink {
190 display: none;
193 .hilite2 {
194 background-color: transparent;
197 .hilite, mark, .next {
198 background-color: var(--yellow);
201 img {
202 max-width: 700px;
204 </style>
206 <?php if (!$PDF_OUTPUT) { ?>
207 <?php // if the track_anything form exists, then include the styling
208 if (file_exists(__DIR__ . "/../../forms/track_anything/style.css")) { ?>
209 <?php Header::setupAssets('track-anything'); ?>
210 <?php } ?>
212 </head>
213 <?php } ?>
215 <body>
216 <div class="container">
217 <div id="report_custom w-100"> <!-- large outer DIV -->
218 <?php
219 if (sizeof($_GET) > 0) {
220 $ar = $_GET;
221 } else {
222 $ar = $_POST;
225 if ($printable) {
226 /*******************************************************************
227 * $sql = "SELECT * FROM facility ORDER BY billing_location DESC LIMIT 1";
228 *******************************************************************/
229 $facility = null;
230 if ($_SESSION['pc_facility']) {
231 $facility = $facilityService->getById($_SESSION['pc_facility']);
232 } else {
233 $facility = $facilityService->getPrimaryBillingLocation();
236 /******************************************************************/
237 // Setup Headers and Footers for mPDF only Download
238 if ($PDF_OUTPUT) {
239 echo genPatientHeaderFooter($pid);
242 // Use logo if it exists as 'practice_logo.gif' in the site dir
243 // old code used the global custom dir which is no longer a valid
244 $practice_logo = "";
245 $plogo = glob("$OE_SITE_DIR/images/*");// let's give the user a little say in image format.
246 $plogo = preg_grep('~practice_logo\.(gif|png|jpg|jpeg)$~i', $plogo);
247 if (!empty($plogo)) {
248 $k = current(array_keys($plogo));
249 $practice_logo = $plogo[$k];
252 $logo = "";
253 if (file_exists($practice_logo)) {
254 $logo = $GLOBALS['OE_SITE_WEBROOT'] . "/images/" . basename($practice_logo);
257 echo genFacilityTitle(getPatientName($pid), $_SESSION['pc_facility'], $logo); ?>
259 <?php } else { // not printable
261 <div class="border-bottom fixed-top px-5 pt-4 report_search_bar">
262 <div class="row">
263 <div class="col-md">
264 <input type="text" class="form-control" onkeyup="clear_last_visit();remove_mark_all();find_all();" name="search_element" id="search_element" />
265 </div>
266 <div class="col-md">
267 <div class="btn-group">
268 <button type="button" class="btn btn-primary btn-search" onClick="clear_last_visit();remove_mark_all();find_all();"><?php echo xlt('Find'); ?></button>
269 <button type="button" class="btn btn-primary" onClick="next_prev('prev');"><?php echo xlt('Prev'); ?></button>
270 <button type="button" class="btn btn-primary" onClick="next_prev('next');"><?php echo xlt('Next'); ?></button>
271 </div>
272 </div>
273 <div class="col-md">
274 <span><?php echo xlt('Match case'); ?></span>
275 <input type="checkbox" onClick="clear_last_visit();remove_mark_all();find_all();" name="search_case" id="search_case" />
276 </div>
277 <div class="col-md mb-2">
278 <span class="text font-weight-bold"><?php echo xlt('Search In'); ?>:</span>
279 <br />
280 <?php
281 $form_id_arr = array();
282 $form_dir_arr = array();
283 $last_key = '';
284 //ksort($ar);
285 foreach ($ar as $key_search => $val_search) {
286 if ($key_search == 'pdf' || $key_search == '') {
287 continue;
290 if (($auth_notes_a || $auth_notes || $auth_coding_a || $auth_coding || $auth_med || $auth_relaxed)) {
291 preg_match('/^(.*)_(\d+)$/', $key_search, $res_search);
292 $form_id_arr[] = add_escape_custom($res_search[2] ?? '');
293 $form_dir_arr[] = add_escape_custom($res_search[1] ?? '');
297 //echo json_encode(json_encode($array_key_id));
298 if (sizeof($form_id_arr) > 0) {
299 $query = "SELECT DISTINCT(form_name),formdir FROM forms WHERE form_id IN ( '" . implode("','", $form_id_arr) . "') AND formdir IN ( '" . implode("','", $form_dir_arr) . "')";
300 $arr = sqlStatement($query);
301 echo "<select multiple size='4' class='form-control' id='forms_to_search' onchange='clear_last_visit();remove_mark_all();find_all();' >";
302 while ($res_forms_ids = sqlFetchArray($arr)) {
303 echo "<option value='" . attr($res_forms_ids['formdir']) . "' selected>" . text($res_forms_ids['form_name']) . "</option>";
305 echo "</select>";
308 </div>
309 <div class="col-md">
310 <span id='alert_msg' class='text-danger'></span>
311 </div>
312 </div>
313 </div>
314 <div id="backLink">
315 <a href="patient_report.php" onclick='top.restoreSession()'>
316 <span class='title'><?php echo xlt('Patient Report'); ?></span>
317 <span class='back'><?php echo text($tback); ?></span>
318 </a>
319 </div>
320 <br />
321 <br />
322 <a href="custom_report.php?printable=1&<?php print postToGet($ar); ?>" class='link_submit' target='new' onclick='top.restoreSession()'>
323 [<?php echo xlt('Printable Version'); ?>]
324 </a>
325 <?php } // end not printable ?>
327 <?php
329 // include ALL form's report.php files
330 $inclookupres = sqlStatement("select distinct formdir from forms where pid = ? AND deleted=0", array($pid));
331 while ($result = sqlFetchArray($inclookupres)) {
332 // include_once("{$GLOBALS['incdir']}/forms/" . $result["formdir"] . "/report.php");
333 $formdir = $result['formdir'];
334 if (substr($formdir, 0, 3) == 'LBF') {
335 include_once($GLOBALS['incdir'] . "/forms/LBF/report.php");
336 } else {
337 include_once($GLOBALS['incdir'] . "/forms/$formdir/report.php");
341 if ($PDF_OUTPUT) {
342 $tmp_files_remove = array();
345 // For each form field from patient_report.php...
347 foreach ($ar as $key => $val) {
348 if ($key == 'pdf') {
349 continue;
352 // These are the top checkboxes (demographics, allergies, etc.).
354 if (stristr($key, "include_")) {
355 if ($val == "recurring_days") {
356 /// label/header for recurring days
357 echo "<hr />";
358 echo "<div class='text' id='appointments'>\n";
359 print "<h4>" . xlt('Recurrent Appointments') . ":</h4>";
361 //fetch the data of the recurring days
362 $recurrences = fetchRecurrences($pid);
364 //print the recurring days to screen
365 if (empty($recurrences)) { //if there are no recurrent appointments:
366 echo "<div class='text' >";
367 echo "<span>" . xlt('None{{Appointment}}') . "</span>";
368 echo "</div>";
369 echo "<br />";
370 } else {
371 foreach ($recurrences as $row) {
372 //checks if there are recurrences and if they are current (git didn't end yet)
373 if (!recurrence_is_current($row['pc_endDate'])) {
374 continue;
377 echo "<div class='text' >";
378 echo "<span>" . xlt('Appointment Category') . ': ' . xlt($row['pc_catname']) . "</span>";
379 echo "<br />";
380 echo "<span>" . xlt('Recurrence') . ': ' . text($row['pc_recurrspec']) . "</span>";
381 echo "<br />";
383 if (ends_in_a_week($row['pc_endDate'])) {
384 echo "<span class='text-danger'>" . xlt('End Date') . ': ' . text($row['pc_endDate']) . "</span>";
385 } else {
386 echo "<span>" . xlt('End Date') . ': ' . text($row['pc_endDate']) . "</span>";
389 echo "</div>";
390 echo "<br />";
394 echo "</div><br />";
395 } elseif ($val == "demographics") {
396 echo "<hr />";
397 echo "<div class='text demographics' id='DEM'>\n";
398 print "<h4>" . xlt('Patient Data') . ":</h4>";
399 // printRecDataOne($patient_data_array, getRecPatientData ($pid), $N);
400 $result1 = getPatientData($pid);
401 $result2 = getEmployerData($pid);
402 echo " <div class='table-responsive'><table class='table'>\n";
403 display_layout_rows('DEM', $result1, $result2);
404 echo " </table></div>\n";
405 echo "</div>\n";
406 } elseif ($val == "history") {
407 echo "<hr />";
408 echo "<div class='text history' id='HIS'>\n";
409 if (AclMain::aclCheckCore('patients', 'med')) {
410 print "<h4>" . xlt('History Data') . ":</h4>";
411 // printRecDataOne($history_data_array, getRecHistoryData ($pid), $N);
412 $result1 = getHistoryData($pid);
413 echo " <table>\n";
414 display_layout_rows('HIS', $result1);
415 echo " </table>\n";
418 echo "</div>";
420 // } elseif ($val == "employer") {
421 // print "<br /><span class='bold'>".xl('Employer Data').":</span><br />";
422 // printRecDataOne($employer_data_array, getRecEmployerData ($pid), $N);
423 } elseif ($val == "insurance") {
424 echo "<hr />";
425 echo "<div class='text insurance'>";
426 echo "<h4>" . xlt('Insurance Data') . ":</h4>";
427 print "<br /><span class='font-weight-bold'>" . xlt('Primary Insurance Data') . ":</span><br />";
428 printRecDataOne($insurance_data_array, getRecInsuranceData($pid, "primary"), $N);
429 print "<span class='font-weight-bold'>" . xlt('Secondary Insurance Data') . ":</span><br />";
430 printRecDataOne($insurance_data_array, getRecInsuranceData($pid, "secondary"), $N);
431 print "<span class='font-weight-bold'>" . xlt('Tertiary Insurance Data') . ":</span><br />";
432 printRecDataOne($insurance_data_array, getRecInsuranceData($pid, "tertiary"), $N);
433 echo "</div>";
434 } elseif ($val == "billing") {
435 echo "<hr />";
436 echo "<div class='text billing'>";
437 print "<h4>" . xlt('Billing Information') . ":</h4>";
438 if (!empty($ar['newpatient']) && count($ar['newpatient']) > 0) {
439 $billings = array();
440 echo "<div class='table-responsive'><table class='table'>";
441 echo "<tr><td class='font-weight-bold'>" . xlt('Code') . "</td><td class='font-weight-bold'>" . xlt('Fee') . "</td></tr>\n";
442 $total = 0.00;
443 $copays = 0.00;
444 foreach ($ar['newpatient'] as $be) {
445 $ta = explode(":", $be);
446 $billing = getPatientBillingEncounter($pid, $ta[1]);
447 $billings[] = $billing;
448 foreach ($billing as $b) {
449 echo "<tr>\n";
450 echo "<td class='text'>";
451 echo text($b['code_type']) . ":\t" . text($b['code']) . "&nbsp;" . text($b['modifier']) . "&nbsp;&nbsp;&nbsp;" . text($b['code_text']) . "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
452 echo "</td>\n";
453 echo "<td class='text'>";
454 echo text(oeFormatMoney($b['fee']));
455 echo "</td>\n";
456 echo "</tr>\n";
457 $total += $b['fee'];
458 if ($b['code_type'] == "COPAY") {
459 $copays += $b['fee'];
464 echo "<tr><td>&nbsp;</td></tr>";
465 echo "<tr><td class='font-weight-bold'>" . xlt('Sub-Total') . "</td><td class='text'>" . text(oeFormatMoney($total + abs($copays))) . "</td></tr>";
466 echo "<tr><td class='font-weight-bold'>" . xlt('Paid') . "</td><td class='text'>" . text(oeFormatMoney(abs($copays))) . "</td></tr>";
467 echo "<tr><td class='font-weight-bold'>" . xlt('Total') . "</td><td class='text'>" . text(oeFormatMoney($total)) . "</td></tr>";
468 echo "</table></div>";
469 echo "<pre>";
470 //print_r($billings);
471 echo "</pre>";
472 } else {
473 printPatientBilling($pid);
476 echo "</div>\n"; // end of billing DIV
477 } elseif ($val == "immunizations") {
478 if (AclMain::aclCheckCore('patients', 'med')) {
479 echo "<hr />";
480 echo "<div class='text immunizations'>\n";
481 print "<h4>" . xlt('Patient Immunization') . ":</h4>";
482 $sql = "select i1.immunization_id, i1.administered_date, substring(i1.note,1,20) as immunization_note, c.code_text_short " .
483 " from immunizations i1 " .
484 " left join code_types ct on ct.ct_key = 'CVX' " .
485 " left join codes c on c.code_type = ct.ct_id AND i1.cvx_code = c.code " .
486 " where i1.patient_id = ? and i1.added_erroneously = 0 " .
487 " order by administered_date desc";
488 $result = sqlStatement($sql, array($pid));
489 while ($row = sqlFetchArray($result)) {
490 // Figure out which name to use (ie. from cvx list or from the custom list)
491 if ($GLOBALS['use_custom_immun_list']) {
492 $vaccine_display = generate_display_field(array('data_type' => '1', 'list_id' => 'immunizations'), $row['immunization_id']);
493 } else {
494 if (!empty($row['code_text_short'])) {
495 $vaccine_display = xlt($row['code_text_short']);
496 } else {
497 $vaccine_display = generate_display_field(array('data_type' => '1', 'list_id' => 'immunizations'), $row['immunization_id']);
501 echo text($row['administered_date']) . " - " . $vaccine_display;
502 if ($row['immunization_note']) {
503 echo " - " . text($row['immunization_note']);
506 echo "<br />\n";
509 echo "</div>\n";
512 // communication report
513 } elseif ($val == "batchcom") {
514 echo "<hr />";
515 echo "<div class='text transactions'>\n";
516 print "<h4>" . xlt('Patient Communication sent') . ":</h4>";
517 $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=?";
518 // echo $sql;
519 $result = sqlStatement($sql, array($pid));
520 while ($row = sqlFetchArray($result)) {
521 echo text($row['batchcom_data']) . ", By: " . text($row['user_name']) . "<br />Text:<br /> " . text($row['msg_txt']) . "<br />\n";
524 echo "</div>\n";
525 } elseif ($val == "notes") {
526 echo "<hr />";
527 echo "<div class='text notes'>\n";
528 print "<h4>" . xlt('Patient Notes') . ":</h4>";
529 printPatientNotes($pid);
530 echo "</div>";
531 } elseif ($val == "transactions") {
532 echo "<hr />";
533 echo "<div class='text transactions'>\n";
534 print "<h4>" . xlt('Patient Transactions') . ":</h4>";
535 printPatientTransactions($pid);
536 echo "</div>";
538 } else {
539 // Documents is an array of checkboxes whose values are document IDs.
541 if ($key == "documents") {
542 echo "<hr />";
543 echo "<div class='text documents'>";
544 foreach ($val as $valkey => $valvalue) {
545 $document_id = $valvalue;
546 if (!is_numeric($document_id)) {
547 continue;
550 $d = new Document($document_id);
551 $fname = basename($d->get_name());
552 // Extract the extension by the mime/type and not the file name extension
553 // -There is an exception. Need to manually see if it a pdf since
554 // the image_type_to_extension() is not working to identify pdf.
555 $extension = strtolower(substr($fname, strrpos($fname, ".")));
556 if ($extension != '.pdf') { // Will print pdf header within pdf import
557 echo "<h5>" . xlt('Document') . " '" . text($fname) . "-" . text($d->get_id()) . "'</h5>";
560 $notes = $d->get_notes();
561 if (!empty($notes)) {
562 echo "<div class='table-responsive'><table class='table'>";
565 foreach ($notes as $note) {
566 echo '<tr>';
567 echo '<td>' . xlt('Note') . ' #' . text($note->get_id()) . '</td>';
568 echo '</tr>';
569 echo '<tr>';
570 echo '<td>' . xlt('Date') . ': ' . text(oeFormatShortDate($note->get_date())) . '</td>';
571 echo '</tr>';
572 echo '<tr>';
573 echo '<td>' . text($note->get_note()) . '<br /><br /></td>';
574 echo '</tr>';
577 if (!empty($notes)) {
578 echo "</table></div>";
581 // adding support for .txt MDM-TXA interface/orders/receive_hl7_results.inc.php
582 if ($extension != (".pdf" || ".txt")) {
583 $tempCDoc = new C_Document();
584 $tempFile = $tempCDoc->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true);
585 // tmp file in temporary_files_dir
586 $tempFileName = tempnam($GLOBALS['temporary_files_dir'], "oer");
587 file_put_contents($tempFileName, $tempFile);
588 $image_data = getimagesize($tempFileName);
589 $extension = image_type_to_extension($image_data[2]);
590 unlink($tempFileName);
593 if ($extension == ".png" || $extension == ".jpg" || $extension == ".jpeg" || $extension == ".gif") {
594 if ($PDF_OUTPUT) {
595 // OK to link to the image file because it will be accessed by the
596 // mPDF parser and not the browser.
597 $tempDocC = new C_Document();
598 $fileTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true);
599 // tmp file in ../documents/temp since need to be available via webroot
600 $from_file_tmp_web_name = tempnam($GLOBALS['OE_SITE_DIR'] . '/documents/temp', "oer");
601 file_put_contents($from_file_tmp_web_name, $fileTemp);
602 echo "<img src='$from_file_tmp_web_name'";
603 // Flag images with excessive width for possible stylesheet action.
604 $asize = getimagesize($from_file_tmp_web_name);
605 if ($asize[0] > 750) {
606 echo " class='bigimage'";
608 $tmp_files_remove[] = $from_file_tmp_web_name;
609 echo " /><br /><br />";
610 } else {
611 echo "<img src='" . $GLOBALS['webroot'] .
612 "/controller.php?document&retrieve&patient_id=&document_id=" .
613 attr_url($document_id) . "&as_file=false&original_file=true&disable_exit=false&show_original=true'><br /><br />";
615 } else {
616 // Most clinic documents are expected to be PDFs, and in that happy case
617 // we can avoid the lengthy image conversion process.
618 if ($PDF_OUTPUT && $extension == ".pdf") {
619 echo "</div></div>\n"; // HTML to PDF conversion will fail if there are open tags.
620 $content = getContent();
621 $pdf->writeHTML($content); // catch up with buffer.
622 $err = '';
623 try {
624 // below header isn't being used. missed maybe!
625 $pg_header = "<span>" . xlt('Document') . " " . text($fname) . "-" . text($d->get_id()) . "</span>";
626 $tempDocC = new C_Document();
627 $pdfTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true);
628 // tmp file in temporary_files_dir
629 $from_file_tmp_name = tempnam($GLOBALS['temporary_files_dir'], "oer");
630 file_put_contents($from_file_tmp_name, $pdfTemp);
632 $pagecount = $pdf->setSourceFile($from_file_tmp_name);
633 for ($i = 0; $i < $pagecount; ++$i) {
634 $pdf->AddPage();
635 $itpl = $pdf->importPage($i + 1);
636 $pdf->useTemplate($itpl);
638 } catch (Exception $e) {
639 // chances are PDF is > v1.4 and compression level not supported.
640 // regardless, we're here so lets dispose in different way.
642 unlink($from_file_tmp_name);
643 $archive_name = ($GLOBALS['temporary_files_dir'] . '/' . report_basename($pid)['base'] . ".zip");
644 $rtn = zip_content(basename($d->url), $archive_name, $pdfTemp);
645 $err = "<span>" . xlt('PDF Document Parse Error and not included. Check if included in archive.') . " : " . text($fname) . "</span>";
646 $pdf->writeHTML($err);
647 $staged_docs[] = array('path' => $d->url, 'fname' => $fname);
648 } finally {
649 unlink($from_file_tmp_name);
650 // Make sure whatever follows is on a new page. Maybe!
651 // okay if not a series of pdfs so if so need @todo
652 if (empty($err)) {
653 $pdf->AddPage();
655 // Resume output buffering and the above-closed tags.
656 ob_start();
657 echo "<div><div class='text documents'>\n";
659 } elseif ($extension == ".txt") {
660 echo "<pre>";
661 $tempDocC = new C_Document();
662 $textTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true);
663 echo text($textTemp);
664 echo "</pre>";
665 } else {
666 if ($PDF_OUTPUT) {
667 // OK to link to the image file because it will be accessed by the mPDF parser and not the browser.
668 $tempDocC = new C_Document();
669 $fileTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, false, true, true);
670 // tmp file in ../documents/temp since need to be available via webroot
671 $from_file_tmp_web_name = tempnam($GLOBALS['OE_SITE_DIR'] . '/documents/temp', "oer");
672 file_put_contents($from_file_tmp_web_name, $fileTemp);
673 echo "<img src='$from_file_tmp_web_name'><br /><br />";
674 $tmp_files_remove[] = $from_file_tmp_web_name;
675 } else {
676 if ($extension === '.pdf' || $extension === '.zip') {
677 echo "<strong>" . xlt('Available Document') . ":</strong><em> " . text($fname) . "</em><br />";
678 } else {
679 echo "<img src='" . $GLOBALS['webroot'] . "/controller.php?document&retrieve&patient_id=&document_id=" . attr_url($document_id) . "&as_file=false&original_file=false'><br /><br />";
683 } // end if-else
684 } // end Documents loop
685 echo "</div>";
686 } elseif ($key == "procedures") { // Procedures is an array of checkboxes whose values are procedure order IDs.
687 if ($auth_med) {
688 echo "<hr />";
689 echo "<div class='text documents'>";
690 foreach ($val as $valkey => $poid) {
691 if (empty($GLOBALS['esign_report_show_only_signed'])) {
692 echo '<h4>' . xlt('Procedure Order') . ':</h4>';
693 echo "<br />\n";
694 generate_order_report($poid, false, !$PDF_OUTPUT);
695 echo "<br />\n";
698 echo "</div>";
700 } elseif (strpos($key, "issue_") === 0) {
701 // display patient Issues
702 if ($first_issue) {
703 $prevIssueType = 'asdf1234!@#$'; // random junk so as to not match anything
704 $first_issue = 0;
705 echo "<hr />";
706 echo "<h4>" . xlt("Issues") . "</h4>";
709 preg_match('/^(.*)_(\d+)$/', $key, $res);
710 $rowid = $res[2];
711 $irow = sqlQuery("SELECT lists.type, lists.title, lists.comments, lists.diagnosis, " .
712 "lists.udi_data, medications.drug_dosage_instructions FROM lists LEFT JOIN " .
713 "( SELECT id AS lists_medication_id, list_id, drug_dosage_instructions " .
714 "FROM lists_medication ) medications ON medications.list_id = id " .
715 "WHERE id = ?", array($rowid));
716 $diagnosis = $irow['diagnosis'];
717 if ($prevIssueType != $irow['type']) {
718 // output a header for each Issue Type we encounter
719 $disptype = $ISSUE_TYPES[$irow['type']][0];
720 echo "<div class='issue_type font-weight-bold'><h5>" . text($disptype) . ":</h5></div>\n";
721 $prevIssueType = $irow['type'];
724 echo "<div class='text issue'>";
725 if ($prevIssueType == "medical_device") {
726 echo "<span class='issue_title'><span class='font-weight-bold'>" . xlt('Title') . ": </span>" . text($irow['title']) . "</span><br>";
727 echo "<span class='issue_title'>" . (new MedicalDevice($irow['udi_data']))->fullOutputHtml() . "</span>";
728 echo "<span class='issue_comments'> " . text($irow['comments']) . "</span><br><br>\n";
729 } else {
730 echo "<span class='issue_title font-weight-bold'>" . text($irow['title']) . ":</span>";
731 echo "<span class='issue_comments'> " . text($irow['comments']) . "</span>\n";
732 if ($prevIssueType == "medication") {
733 echo "<span class='issue_dosage_instructions'> " . text($irow['drug_dosage_instructions']) . "</span>\n";
737 // Show issue's chief diagnosis and its description:
738 if ($diagnosis) {
739 echo "<div class='text issue_diag'>";
740 echo "[" . xlt('Diagnosis') . "]<br />";
741 $dcodes = explode(";", $diagnosis);
742 foreach ($dcodes as $dcode) {
743 echo "<span class='italic'>" . text($dcode) . "</span>: ";
744 echo text(lookup_code_descriptions($dcode)) . "<br />\n";
747 //echo $diagnosis." -- ".lookup_code_descriptions($diagnosis)."\n";
748 echo "</div>";
751 // Supplemental data for GCAC or Contraception issues.
752 if ($irow['type'] == 'ippf_gcac') {
753 echo " <div class='table-responsive'><table class='table'>\n";
754 display_layout_rows('GCA', sqlQuery("SELECT * FROM lists_ippf_gcac WHERE id = ?", array($rowid)));
755 echo " </table></div>\n";
756 } elseif ($irow['type'] == 'contraceptive') {
757 echo " <div class='table-responsive'><table class='table'>\n";
758 display_layout_rows('CON', sqlQuery("SELECT * FROM lists_ippf_con WHERE id = ?", array($rowid)));
759 echo " </table></div>\n";
762 echo "</div>\n"; //end the issue DIV
763 } else {
764 // we have an "encounter form" form field whose name is like
765 // dirname_formid, with a value which is the encounter ID.
767 // display encounter forms, encoded as a POST variable
768 // in the format: <formdirname_formid>=<encounterID>
770 if (($auth_notes_a || $auth_notes || $auth_coding_a || $auth_coding || $auth_med || $auth_relaxed)) {
771 $form_encounter = $val;
772 preg_match('/^(.*)_(\d+)$/', $key, $res);
773 $form_id = $res[2];
774 $formres = getFormNameByFormdirAndFormid($res[1], $form_id);
775 $dateres = getEncounterDateByEncounter($form_encounter);
776 $formId = getFormIdByFormdirAndFormid($res[1], $form_id);
778 if ($res[1] == 'newpatient') {
779 echo "<div class='text encounter'>\n";
780 echo "<h4>" . xlt($formres["form_name"]) . "</h4>";
781 } else {
782 echo "<div class='text encounter_form'>";
783 echo "<h4>" . text(xl_form_title($formres["form_name"])) . "</h4>";
786 // show the encounter's date
787 echo "(" . text(oeFormatSDFT(strtotime($dateres["date"]))) . ") ";
788 if ($res[1] == 'newpatient') {
789 // display the provider info
790 echo ' ' . xlt('Provider') . ': ' . text(getProviderName(getProviderIdOfEncounter($form_encounter)));
793 echo "<br />\n";
795 // call the report function for the form
797 <div name="search_div" id="search_div_<?php echo attr($form_id) ?>_<?php echo attr($res[1]) ?>" class="report_search_div class_<?php echo attr($res[1]); ?>">
798 <?php
799 if (!empty($res[1])) {
800 $esign = $esignApi->createFormESign($formId, $res[1], $form_encounter);
801 if ($esign->isSigned('report') && !empty($GLOBALS['esign_report_show_only_signed'])) {
802 if (substr($res[1], 0, 3) == 'LBF') {
803 call_user_func("lbf_report", $pid, $form_encounter, $N, $form_id, $res[1]);
804 } else {
805 call_user_func($res[1] . "_report", $pid, $form_encounter, $N, $form_id);
807 } elseif (empty($GLOBALS['esign_report_show_only_signed'])) {
808 if (substr($res[1], 0, 3) == 'LBF') {
809 call_user_func('lbf_report', $pid, $form_encounter, $N, $form_id, $res[1]);
810 } else {
811 call_user_func($res[1] . '_report', $pid, $form_encounter, $N, $form_id);
813 } else {
814 echo "<h6>" . xlt("Not signed.") . "</h6>";
816 if ($esign->isLogViewable("report")) {
817 $esign->renderLog();
822 </div>
823 <?php
825 if ($res[1] == 'newpatient') {
826 // display billing info
827 $bres = sqlStatement(
828 "SELECT b.date, b.code, b.code_text, b.modifier " .
829 "FROM billing AS b, code_types AS ct WHERE " .
830 "b.pid = ? AND " .
831 "b.encounter = ? AND " .
832 "b.activity = 1 AND " .
833 "b.code_type = ct.ct_key AND " .
834 "ct.ct_diag = 0 " .
835 "ORDER BY b.date",
836 array($pid, $form_encounter)
838 while ($brow = sqlFetchArray($bres)) {
839 echo "<div class='font-weight-bold d-inline-block'>&nbsp;" . xlt('Procedure') . ": </div><div class='text d-inline-block'>" .
840 text($brow['code']) . ":" . text($brow['modifier']) . " " . text($brow['code_text']) . "</div><br />\n";
844 print "</div>";
845 } // end auth-check for encounter forms
846 } // end if('issue_')... else...
847 } // end if('include_')... else...
848 } // end $ar loop
850 if ($printable && !$PDF_OUTPUT) {// Patched out of pdf 04/20/2017 sjpadgett
851 echo "<br /><br />" . xlt('Signature') . ": _______________________________<br />";
855 </div> <!-- end of report_custom DIV -->
856 </div>
858 <?php
859 if ($PDF_OUTPUT) {
860 $content = getContent();
861 $ptd = report_basename($pid);
862 $fn = $ptd['base'] . ".pdf";
863 $pdf->SetTitle(ucfirst($ptd['fname']) . ' ' . $ptd['lname'] . ' ' . xl('Id') . ':' . $pid . ' ' . xl('Report'));
864 $isit_utf8 = preg_match('//u', $content); // quick check for invalid encoding
865 if (!$isit_utf8) {
866 if (function_exists('iconv')) { // if we can lets save the report
867 $content = iconv("UTF-8", "UTF-8//IGNORE", $content);
868 } else { // no sense going on.
869 $die_str = xlt("Failed UTF8 encoding check! Could not automatically fix.");
870 die($die_str);
874 try {
875 $pdf->writeHTML($content); // convert html
876 } catch (MpdfException $exception) {
877 die(text($exception));
880 if ($PDF_OUTPUT == 1) {
881 try {
882 if ($PDF_FAX === 1) {
883 $fax_pdf = $pdf->Output($fn, 'S');
884 $tmp_file = $GLOBALS['temporary_files_dir'] . '/' . $fn; // is deleted in sendFax...
885 file_put_contents($tmp_file, $fax_pdf);
886 echo $tmp_file;
887 exit();
888 } else {
889 if (!empty($archive_name) && sizeof($staged_docs) > 0) {
890 $rtn = zip_content(basename($fn), $archive_name, $pdf->Output($fn, 'S'));
891 header('Content-Description: File Transfer');
892 header('Content-Transfer-Encoding: binary');
893 header('Expires: 0');
894 header("Cache-control: private");
895 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
896 header("Content-Type: application/zip; charset=utf-8");
897 header("Content-Length: " . filesize($archive_name));
898 header('Content-Disposition: attachment; filename="' . basename($archive_name) . '"');
900 ob_end_clean();
901 @readfile($archive_name) or error_log("Archive temp file not found: " . $archive_name);
903 unlink($archive_name);
904 } else {
905 $pdf->Output($fn, $GLOBALS['pdf_output']); // D = Download, I = Inline
908 } catch (MpdfException $exception) {
909 die(text($exception));
911 } else {
912 // This is the case of writing the PDF as a message to the CMS portal.
913 $ptdata = getPatientData($pid, 'cmsportal_login');
914 $contents = $pdf->Output('', true);
915 echo "<html><head>\n";
916 Header::setupHeader();
917 echo "</head><body>\n";
918 $result = cms_portal_call(array(
919 'action' => 'putmessage',
920 'user' => $ptdata['cmsportal_login'],
921 'title' => xl('Your Clinical Report'),
922 'message' => xl('Please see the attached PDF.'),
923 'filename' => 'report.pdf',
924 'mimetype' => 'application/pdf',
925 'contents' => base64_encode($contents)
927 if ($result['errmsg']) {
928 die(text($result['errmsg']));
931 echo "<p class='mt-3'>" . xlt('Report has been sent to the patient.') . "</p>\n";
932 echo "</body></html>\n";
934 foreach ($tmp_files_remove as $tmp_file) {
935 // Remove the tmp files that were created
936 unlink($tmp_file);
938 } else {
940 <?php if (!$printable) { ?>
941 <script src="<?php echo $GLOBALS['web_root'] ?>/interface/patient_file/report/custom_report.js?v=<?php echo $v_js_includes; ?>"></script>
942 <script>
943 const searchBarHeight = document.querySelectorAll('.report_search_bar')[0].clientHeight;
944 document.getElementById('backLink').style.marginTop = `${searchBarHeight}px`;
945 </script>
946 <?php } ?>
948 </body>
949 </html>
950 <?php } ?>