.inc files migration to .inc.php (#5897)
[openemr.git] / interface / patient_file / report / custom_report.php
blob61554881f4393d169374807d924eeaab4bd66b7b
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\Services\FacilityService;
38 if (!AclMain::aclCheckCore('patients', 'pat_rep')) {
39 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Custom Report")]);
40 exit;
43 $facilityService = new FacilityService();
45 $staged_docs = array();
46 $archive_name = '';
48 // For those who care that this is the patient report.
49 $GLOBALS['PATIENT_REPORT_ACTIVE'] = true;
51 $PDF_OUTPUT = empty($_POST['pdf']) ? 0 : intval($_POST['pdf']);
52 $PDF_FAX = empty($_POST['fax']) ? 0 : intval($_POST['fax']);
53 if ($PDF_FAX) {
54 $PDF_OUTPUT = 1;
57 if ($PDF_OUTPUT) {
58 $config_mpdf = array(
59 'tempDir' => $GLOBALS['MPDF_WRITE_DIR'],
60 'mode' => $GLOBALS['pdf_language'],
61 'format' => $GLOBALS['pdf_size'],
62 'default_font_size' => '9',
63 'default_font' => 'dejavusans',
64 'margin_left' => $GLOBALS['pdf_left_margin'],
65 'margin_right' => $GLOBALS['pdf_right_margin'],
66 'margin_top' => $GLOBALS['pdf_top_margin'] * 1.5,
67 'margin_bottom' => $GLOBALS['pdf_bottom_margin'] * 1.5,
68 'margin_header' => $GLOBALS['pdf_top_margin'],
69 'margin_footer' => $GLOBALS['pdf_bottom_margin'],
70 'orientation' => $GLOBALS['pdf_layout'],
71 'shrink_tables_to_fit' => 1,
72 'use_kwt' => true,
73 'autoScriptToLang' => true,
74 'keep_table_proportions' => true
76 $pdf = new mPDF($config_mpdf);
77 if ($_SESSION['language_direction'] == 'rtl') {
78 $pdf->SetDirectionality('rtl');
80 ob_start();
81 } // end pdf conditional.
83 // get various authorization levels
84 $auth_notes_a = AclMain::aclCheckCore('encounters', 'notes_a');
85 $auth_notes = AclMain::aclCheckCore('encounters', 'notes');
86 $auth_coding_a = AclMain::aclCheckCore('encounters', 'coding_a');
87 $auth_coding = AclMain::aclCheckCore('encounters', 'coding');
88 $auth_relaxed = AclMain::aclCheckCore('encounters', 'relaxed');
89 $auth_med = AclMain::aclCheckCore('patients', 'med');
90 $auth_demo = AclMain::aclCheckCore('patients', 'demo');
92 $esignApi = new Api();
94 $printable = empty($_GET['printable']) ? false : true;
95 if ($PDF_OUTPUT) {
96 $printable = true;
99 unset($_GET['printable']);
101 // Number of columns in tables for insurance and encounter forms.
102 $N = $PDF_OUTPUT ? 4 : 6;
104 $first_issue = 1;
106 function getContent()
108 global $web_root, $webserver_root;
109 $content = ob_get_clean();
110 // Fix a nasty mPDF bug - it ignores document root!
111 $i = 0;
112 $wrlen = strlen($web_root);
113 $wsrlen = strlen($webserver_root);
114 while (true) {
115 $i = stripos($content, " src='/", $i + 1);
116 if ($i === false) {
117 break;
120 if (
121 substr($content, $i + 6, $wrlen) === $web_root &&
122 substr($content, $i + 6, $wsrlen) !== $webserver_root
124 $content = substr($content, 0, $i + 6) . $webserver_root . substr($content, $i + 6 + $wrlen);
128 return $content;
131 function postToGet($arin)
133 $getstring = "";
134 foreach ($arin as $key => $val) {
135 if (is_array($val)) {
136 foreach ($val as $k => $v) {
137 $getstring .= attr_url($key . "[]") . "=" . attr_url($v) . "&";
139 } else {
140 $getstring .= attr_url($key) . "=" . attr_url($val) . "&";
144 return $getstring;
147 function report_basename($pid)
149 $ptd = getPatientData($pid, "fname,lname");
150 // escape names for pesky periods hyphen etc.
151 $esc = $ptd['fname'] . '_' . $ptd['lname'];
152 $esc = str_replace(array('.', ',', ' '), '', $esc);
153 $fn = basename_international(strtolower($esc . '_' . $pid . '_' . xl('report')));
155 return array('base' => $fn, 'fname' => $ptd['fname'], 'lname' => $ptd['lname']);
158 function zip_content($source, $destination, $content = '', $create = true)
160 if (!extension_loaded('zip')) {
161 return false;
164 $zip = new ZipArchive();
165 if ($create) {
166 if (!$zip->open($destination, ZipArchive::CREATE)) {
167 return false;
169 } else {
170 if (!$zip->open($destination, ZipArchive::OVERWRITE)) {
171 return false;
175 if (is_file($source) === true) {
176 $zip->addFromString(basename($source), file_get_contents($source));
177 } elseif (!empty($content)) {
178 $zip->addFromString(basename($source), $content);
181 return $zip->close();
186 <?php if ($PDF_OUTPUT) { ?>
187 <?php Header::setupAssets(['pdf-style', 'esign-theme-only']); ?>
188 <?php } else { ?>
189 <html>
190 <head>
191 <?php Header::setupHeader(['esign-theme-only', 'search-highlight']); ?>
192 <?php } ?>
194 <?php // do not show stuff from report.php in forms that is encaspulated
195 // by div of navigateLink class. Specifically used for CAMOS, but
196 // can also be used by other forms that require output in the
197 // encounter listings output, but not in the custom report. ?>
199 <style>
200 div.navigateLink {
201 display: none;
204 .hilite2 {
205 background-color: transparent;
208 .hilite, mark, .next {
209 background-color: var(--yellow);
212 img {
213 max-width: 700px;
215 </style>
217 <?php if (!$PDF_OUTPUT) { ?>
218 <?php // if the track_anything form exists, then include the styling
219 if (file_exists(__DIR__ . "/../../forms/track_anything/style.css")) { ?>
220 <?php Header::setupAssets('track-anything'); ?>
221 <?php } ?>
223 </head>
224 <?php } ?>
226 <body>
227 <div class="container">
228 <div id="report_custom w-100"> <!-- large outer DIV -->
229 <?php
230 if (sizeof($_GET) > 0) {
231 $ar = $_GET;
232 } else {
233 $ar = $_POST;
236 if ($printable) {
237 /*******************************************************************
238 * $sql = "SELECT * FROM facility ORDER BY billing_location DESC LIMIT 1";
239 *******************************************************************/
240 $facility = null;
241 if ($_SESSION['pc_facility']) {
242 $facility = $facilityService->getById($_SESSION['pc_facility']);
243 } else {
244 $facility = $facilityService->getPrimaryBillingLocation();
247 /******************************************************************/
248 // Setup Headers and Footers for mPDF only Download
249 if ($PDF_OUTPUT) {
250 echo genPatientHeaderFooter($pid);
253 // Use logo if it exists as 'practice_logo.gif' in the site dir
254 // old code used the global custom dir which is no longer a valid
255 $practice_logo = "";
256 $plogo = glob("$OE_SITE_DIR/images/*");// let's give the user a little say in image format.
257 $plogo = preg_grep('~practice_logo\.(gif|png|jpg|jpeg)$~i', $plogo);
258 if (!empty($plogo)) {
259 $k = current(array_keys($plogo));
260 $practice_logo = $plogo[$k];
263 $logo = "";
264 if (file_exists($practice_logo)) {
265 $logo = $GLOBALS['OE_SITE_WEBROOT'] . "/images/" . basename($practice_logo);
268 echo genFacilityTitle(getPatientName($pid), $_SESSION['pc_facility'], $logo);?>
270 <?php } else { // not printable
272 <div class="border-bottom fixed-top px-5 pt-4 report_search_bar">
273 <div class="row">
274 <div class="col-md">
275 <input type="text" class="form-control" onkeyup="clear_last_visit();remove_mark_all();find_all();" name="search_element" id="search_element" />
276 </div>
277 <div class="col-md">
278 <div class="btn-group">
279 <button type="button" class="btn btn-primary btn-search" onClick="clear_last_visit();remove_mark_all();find_all();"><?php echo xlt('Find'); ?></button>
280 <button type="button" class="btn btn-primary" onClick="next_prev('prev');"><?php echo xlt('Prev'); ?></button>
281 <button type="button" class="btn btn-primary" onClick="next_prev('next');"><?php echo xlt('Next'); ?></button>
282 </div>
283 </div>
284 <div class="col-md">
285 <span><?php echo xlt('Match case'); ?></span>
286 <input type="checkbox" onClick="clear_last_visit();remove_mark_all();find_all();" name="search_case" id="search_case" />
287 </div>
288 <div class="col-md mb-2">
289 <span class="text font-weight-bold"><?php echo xlt('Search In'); ?>:</span>
290 <br />
291 <?php
292 $form_id_arr = array();
293 $form_dir_arr = array();
294 $last_key = '';
295 //ksort($ar);
296 foreach ($ar as $key_search => $val_search) {
297 if ($key_search == 'pdf' || $key_search == '') {
298 continue;
301 if (($auth_notes_a || $auth_notes || $auth_coding_a || $auth_coding || $auth_med || $auth_relaxed)) {
302 preg_match('/^(.*)_(\d+)$/', $key_search, $res_search);
303 $form_id_arr[] = add_escape_custom($res_search[2] ?? '');
304 $form_dir_arr[] = add_escape_custom($res_search[1] ?? '');
308 //echo json_encode(json_encode($array_key_id));
309 if (sizeof($form_id_arr) > 0) {
310 $query = "SELECT DISTINCT(form_name),formdir FROM forms WHERE form_id IN ( '" . implode("','", $form_id_arr) . "') AND formdir IN ( '" . implode("','", $form_dir_arr) . "')";
311 $arr = sqlStatement($query);
312 echo "<select multiple size='4' class='form-control' id='forms_to_search' onchange='clear_last_visit();remove_mark_all();find_all();' >";
313 while ($res_forms_ids = sqlFetchArray($arr)) {
314 echo "<option value='" . attr($res_forms_ids['formdir']) . "' selected>" . text($res_forms_ids['form_name']) . "</option>";
316 echo "</select>";
319 </div>
320 <div class="col-md">
321 <span id='alert_msg' class='text-danger'></span>
322 </div>
323 </div>
324 </div>
325 <div id="backLink">
326 <a href="patient_report.php" onclick='top.restoreSession()'>
327 <span class='title'><?php echo xlt('Patient Report'); ?></span>
328 <span class='back'><?php echo text($tback); ?></span>
329 </a>
330 </div>
331 <br />
332 <br />
333 <a href="custom_report.php?printable=1&<?php print postToGet($ar); ?>" class='link_submit' target='new' onclick='top.restoreSession()'>
334 [<?php echo xlt('Printable Version'); ?>]
335 </a>
336 <?php } // end not printable ?>
338 <?php
340 // include ALL form's report.php files
341 $inclookupres = sqlStatement("select distinct formdir from forms where pid = ? AND deleted=0", array($pid));
342 while ($result = sqlFetchArray($inclookupres)) {
343 // include_once("{$GLOBALS['incdir']}/forms/" . $result["formdir"] . "/report.php");
344 $formdir = $result['formdir'];
345 if (substr($formdir, 0, 3) == 'LBF') {
346 include_once($GLOBALS['incdir'] . "/forms/LBF/report.php");
347 } else {
348 include_once($GLOBALS['incdir'] . "/forms/$formdir/report.php");
352 if ($PDF_OUTPUT) {
353 $tmp_files_remove = array();
356 // For each form field from patient_report.php...
358 foreach ($ar as $key => $val) {
359 if ($key == 'pdf') {
360 continue;
363 // These are the top checkboxes (demographics, allergies, etc.).
365 if (stristr($key, "include_")) {
366 if ($val == "recurring_days") {
367 /// label/header for recurring days
368 echo "<hr />";
369 echo "<div class='text' id='appointments'>\n";
370 print "<h4>" . xlt('Recurrent Appointments') . ":</h4>";
372 //fetch the data of the recurring days
373 $recurrences = fetchRecurrences($pid);
375 //print the recurring days to screen
376 if (empty($recurrences)) { //if there are no recurrent appointments:
377 echo "<div class='text' >";
378 echo "<span>" . xlt('None{{Appointment}}') . "</span>";
379 echo "</div>";
380 echo "<br />";
381 } else {
382 foreach ($recurrences as $row) {
383 //checks if there are recurrences and if they are current (git didn't end yet)
384 if (!recurrence_is_current($row['pc_endDate'])) {
385 continue;
388 echo "<div class='text' >";
389 echo "<span>" . xlt('Appointment Category') . ': ' . xlt($row['pc_catname']) . "</span>";
390 echo "<br />";
391 echo "<span>" . xlt('Recurrence') . ': ' . text($row['pc_recurrspec']) . "</span>";
392 echo "<br />";
394 if (ends_in_a_week($row['pc_endDate'])) {
395 echo "<span class='text-danger'>" . xlt('End Date') . ': ' . text($row['pc_endDate']) . "</span>";
396 } else {
397 echo "<span>" . xlt('End Date') . ': ' . text($row['pc_endDate']) . "</span>";
400 echo "</div>";
401 echo "<br />";
405 echo "</div><br />";
406 } elseif ($val == "demographics") {
407 echo "<hr />";
408 echo "<div class='text demographics' id='DEM'>\n";
409 print "<h4>" . xlt('Patient Data') . ":</h4>";
410 // printRecDataOne($patient_data_array, getRecPatientData ($pid), $N);
411 $result1 = getPatientData($pid);
412 $result2 = getEmployerData($pid);
413 echo " <div class='table-responsive'><table class='table'>\n";
414 display_layout_rows('DEM', $result1, $result2);
415 echo " </table></div>\n";
416 echo "</div>\n";
417 } elseif ($val == "history") {
418 echo "<hr />";
419 echo "<div class='text history' id='HIS'>\n";
420 if (AclMain::aclCheckCore('patients', 'med')) {
421 print "<h4>" . xlt('History Data') . ":</h4>";
422 // printRecDataOne($history_data_array, getRecHistoryData ($pid), $N);
423 $result1 = getHistoryData($pid);
424 echo " <table>\n";
425 display_layout_rows('HIS', $result1);
426 echo " </table>\n";
429 echo "</div>";
431 // } elseif ($val == "employer") {
432 // print "<br /><span class='bold'>".xl('Employer Data').":</span><br />";
433 // printRecDataOne($employer_data_array, getRecEmployerData ($pid), $N);
434 } elseif ($val == "insurance") {
435 echo "<hr />";
436 echo "<div class='text insurance'>";
437 echo "<h4>" . xlt('Insurance Data') . ":</h4>";
438 print "<br /><span class='font-weight-bold'>" . xlt('Primary Insurance Data') . ":</span><br />";
439 printRecDataOne($insurance_data_array, getRecInsuranceData($pid, "primary"), $N);
440 print "<span class='font-weight-bold'>" . xlt('Secondary Insurance Data') . ":</span><br />";
441 printRecDataOne($insurance_data_array, getRecInsuranceData($pid, "secondary"), $N);
442 print "<span class='font-weight-bold'>" . xlt('Tertiary Insurance Data') . ":</span><br />";
443 printRecDataOne($insurance_data_array, getRecInsuranceData($pid, "tertiary"), $N);
444 echo "</div>";
445 } elseif ($val == "billing") {
446 echo "<hr />";
447 echo "<div class='text billing'>";
448 print "<h4>" . xlt('Billing Information') . ":</h4>";
449 if (!empty($ar['newpatient']) && count($ar['newpatient']) > 0) {
450 $billings = array();
451 echo "<div class='table-responsive'><table class='table'>";
452 echo "<tr><td class='font-weight-bold'>" . xlt('Code') . "</td><td class='font-weight-bold'>" . xlt('Fee') . "</td></tr>\n";
453 $total = 0.00;
454 $copays = 0.00;
455 foreach ($ar['newpatient'] as $be) {
456 $ta = explode(":", $be);
457 $billing = getPatientBillingEncounter($pid, $ta[1]);
458 $billings[] = $billing;
459 foreach ($billing as $b) {
460 echo "<tr>\n";
461 echo "<td class='text'>";
462 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;";
463 echo "</td>\n";
464 echo "<td class='text'>";
465 echo text(oeFormatMoney($b['fee']));
466 echo "</td>\n";
467 echo "</tr>\n";
468 $total += $b['fee'];
469 if ($b['code_type'] == "COPAY") {
470 $copays += $b['fee'];
475 echo "<tr><td>&nbsp;</td></tr>";
476 echo "<tr><td class='font-weight-bold'>" . xlt('Sub-Total') . "</td><td class='text'>" . text(oeFormatMoney($total + abs($copays))) . "</td></tr>";
477 echo "<tr><td class='font-weight-bold'>" . xlt('Paid') . "</td><td class='text'>" . text(oeFormatMoney(abs($copays))) . "</td></tr>";
478 echo "<tr><td class='font-weight-bold'>" . xlt('Total') . "</td><td class='text'>" . text(oeFormatMoney($total)) . "</td></tr>";
479 echo "</table></div>";
480 echo "<pre>";
481 //print_r($billings);
482 echo "</pre>";
483 } else {
484 printPatientBilling($pid);
487 echo "</div>\n"; // end of billing DIV
488 } elseif ($val == "immunizations") {
489 if (AclMain::aclCheckCore('patients', 'med')) {
490 echo "<hr />";
491 echo "<div class='text immunizations'>\n";
492 print "<h4>" . xlt('Patient Immunization') . ":</h4>";
493 $sql = "select i1.immunization_id, i1.administered_date, substring(i1.note,1,20) as immunization_note, c.code_text_short " .
494 " from immunizations i1 " .
495 " left join code_types ct on ct.ct_key = 'CVX' " .
496 " left join codes c on c.code_type = ct.ct_id AND i1.cvx_code = c.code " .
497 " where i1.patient_id = ? and i1.added_erroneously = 0 " .
498 " order by administered_date desc";
499 $result = sqlStatement($sql, array($pid));
500 while ($row = sqlFetchArray($result)) {
501 // Figure out which name to use (ie. from cvx list or from the custom list)
502 if ($GLOBALS['use_custom_immun_list']) {
503 $vaccine_display = generate_display_field(array('data_type' => '1', 'list_id' => 'immunizations'), $row['immunization_id']);
504 } else {
505 if (!empty($row['code_text_short'])) {
506 $vaccine_display = xlt($row['code_text_short']);
507 } else {
508 $vaccine_display = generate_display_field(array('data_type' => '1', 'list_id' => 'immunizations'), $row['immunization_id']);
512 echo text($row['administered_date']) . " - " . $vaccine_display;
513 if ($row['immunization_note']) {
514 echo " - " . text($row['immunization_note']);
517 echo "<br />\n";
520 echo "</div>\n";
523 // communication report
524 } elseif ($val == "batchcom") {
525 echo "<hr />";
526 echo "<div class='text transactions'>\n";
527 print "<h4>" . xlt('Patient Communication sent') . ":</h4>";
528 $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=?";
529 // echo $sql;
530 $result = sqlStatement($sql, array($pid));
531 while ($row = sqlFetchArray($result)) {
532 echo text($row['batchcom_data']) . ", By: " . text($row['user_name']) . "<br />Text:<br /> " . text($row['msg_txt']) . "<br />\n";
535 echo "</div>\n";
536 } elseif ($val == "notes") {
537 echo "<hr />";
538 echo "<div class='text notes'>\n";
539 print "<h4>" . xlt('Patient Notes') . ":</h4>";
540 printPatientNotes($pid);
541 echo "</div>";
542 } elseif ($val == "transactions") {
543 echo "<hr />";
544 echo "<div class='text transactions'>\n";
545 print "<h4>" . xlt('Patient Transactions') . ":</h4>";
546 printPatientTransactions($pid);
547 echo "</div>";
549 } else {
550 // Documents is an array of checkboxes whose values are document IDs.
552 if ($key == "documents") {
553 echo "<hr />";
554 echo "<div class='text documents'>";
555 foreach ($val as $valkey => $valvalue) {
556 $document_id = $valvalue;
557 if (!is_numeric($document_id)) {
558 continue;
561 $d = new Document($document_id);
562 $fname = basename($d->get_name());
563 // Extract the extension by the mime/type and not the file name extension
564 // -There is an exception. Need to manually see if it a pdf since
565 // the image_type_to_extension() is not working to identify pdf.
566 $extension = strtolower(substr($fname, strrpos($fname, ".")));
567 if ($extension != '.pdf') { // Will print pdf header within pdf import
568 echo "<h5>" . xlt('Document') . " '" . text($fname) . "-" . text($d->get_id()) . "'</h5>";
571 $notes = $d->get_notes();
572 if (!empty($notes)) {
573 echo "<div class='table-responsive'><table class='table'>";
576 foreach ($notes as $note) {
577 echo '<tr>';
578 echo '<td>' . xlt('Note') . ' #' . text($note->get_id()) . '</td>';
579 echo '</tr>';
580 echo '<tr>';
581 echo '<td>' . xlt('Date') . ': ' . text(oeFormatShortDate($note->get_date())) . '</td>';
582 echo '</tr>';
583 echo '<tr>';
584 echo '<td>' . text($note->get_note()) . '<br /><br /></td>';
585 echo '</tr>';
588 if (!empty($notes)) {
589 echo "</table></div>";
592 // adding support for .txt MDM-TXA interface/orders/receive_hl7_results.inc.php
593 if ($extension != (".pdf" || ".txt")) {
594 $tempCDoc = new C_Document();
595 $tempFile = $tempCDoc->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true);
596 // tmp file in temporary_files_dir
597 $tempFileName = tempnam($GLOBALS['temporary_files_dir'], "oer");
598 file_put_contents($tempFileName, $tempFile);
599 $image_data = getimagesize($tempFileName);
600 $extension = image_type_to_extension($image_data[2]);
601 unlink($tempFileName);
604 if ($extension == ".png" || $extension == ".jpg" || $extension == ".jpeg" || $extension == ".gif") {
605 if ($PDF_OUTPUT) {
606 // OK to link to the image file because it will be accessed by the
607 // mPDF parser and not the browser.
608 $tempDocC = new C_Document();
609 $fileTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true);
610 // tmp file in ../documents/temp since need to be available via webroot
611 $from_file_tmp_web_name = tempnam($GLOBALS['OE_SITE_DIR'] . '/documents/temp', "oer");
612 file_put_contents($from_file_tmp_web_name, $fileTemp);
613 echo "<img src='$from_file_tmp_web_name'";
614 // Flag images with excessive width for possible stylesheet action.
615 $asize = getimagesize($from_file_tmp_web_name);
616 if ($asize[0] > 750) {
617 echo " class='bigimage'";
619 $tmp_files_remove[] = $from_file_tmp_web_name;
620 echo " /><br /><br />";
621 } else {
622 echo "<img src='" . $GLOBALS['webroot'] .
623 "/controller.php?document&retrieve&patient_id=&document_id=" .
624 attr_url($document_id) . "&as_file=false&original_file=true&disable_exit=false&show_original=true'><br /><br />";
626 } else {
627 // Most clinic documents are expected to be PDFs, and in that happy case
628 // we can avoid the lengthy image conversion process.
629 if ($PDF_OUTPUT && $extension == ".pdf") {
630 echo "</div></div>\n"; // HTML to PDF conversion will fail if there are open tags.
631 $content = getContent();
632 $pdf->writeHTML($content); // catch up with buffer.
633 $err = '';
634 try {
635 // below header isn't being used. missed maybe!
636 $pg_header = "<span>" . xlt('Document') . " " . text($fname) . "-" . text($d->get_id()) . "</span>";
637 $tempDocC = new C_Document();
638 $pdfTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true);
639 // tmp file in temporary_files_dir
640 $from_file_tmp_name = tempnam($GLOBALS['temporary_files_dir'], "oer");
641 file_put_contents($from_file_tmp_name, $pdfTemp);
643 $pagecount = $pdf->setSourceFile($from_file_tmp_name);
644 for ($i = 0; $i < $pagecount; ++$i) {
645 $pdf->AddPage();
646 $itpl = $pdf->importPage($i + 1);
647 $pdf->useTemplate($itpl);
649 } catch (Exception $e) {
650 // chances are PDF is > v1.4 and compression level not supported.
651 // regardless, we're here so lets dispose in different way.
653 unlink($from_file_tmp_name);
654 $archive_name = ($GLOBALS['temporary_files_dir'] . '/' . report_basename($pid)['base'] . ".zip");
655 $rtn = zip_content(basename($d->url), $archive_name, $pdfTemp);
656 $err = "<span>" . xlt('PDF Document Parse Error and not included. Check if included in archive.') . " : " . text($fname) . "</span>";
657 $pdf->writeHTML($err);
658 $staged_docs[] = array('path' => $d->url, 'fname' => $fname);
659 } finally {
660 unlink($from_file_tmp_name);
661 // Make sure whatever follows is on a new page. Maybe!
662 // okay if not a series of pdfs so if so need @todo
663 if (empty($err)) {
664 $pdf->AddPage();
666 // Resume output buffering and the above-closed tags.
667 ob_start();
668 echo "<div><div class='text documents'>\n";
670 } elseif ($extension == ".txt") {
671 echo "<pre>";
672 $tempDocC = new C_Document();
673 $textTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, true, true, true);
674 echo text($textTemp);
675 echo "</pre>";
676 } else {
677 if ($PDF_OUTPUT) {
678 // OK to link to the image file because it will be accessed by the mPDF parser and not the browser.
679 $tempDocC = new C_Document();
680 $fileTemp = $tempDocC->retrieve_action($d->get_foreign_id(), $document_id, false, false, true, true);
681 // tmp file in ../documents/temp since need to be available via webroot
682 $from_file_tmp_web_name = tempnam($GLOBALS['OE_SITE_DIR'] . '/documents/temp', "oer");
683 file_put_contents($from_file_tmp_web_name, $fileTemp);
684 echo "<img src='$from_file_tmp_web_name'><br /><br />";
685 $tmp_files_remove[] = $from_file_tmp_web_name;
686 } else {
687 if ($extension === '.pdf' || $extension === '.zip') {
688 echo "<strong>" . xlt('Available Document') . ":</strong><em> " . text($fname) . "</em><br />";
689 } else {
690 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 />";
694 } // end if-else
695 } // end Documents loop
696 echo "</div>";
697 } elseif ($key == "procedures") { // Procedures is an array of checkboxes whose values are procedure order IDs.
698 if ($auth_med) {
699 echo "<hr />";
700 echo "<div class='text documents'>";
701 foreach ($val as $valkey => $poid) {
702 if (empty($GLOBALS['esign_report_show_only_signed'])) {
703 echo '<h4>' . xlt('Procedure Order') . ':</h4>';
704 echo "<br />\n";
705 generate_order_report($poid, false, !$PDF_OUTPUT);
706 echo "<br />\n";
709 echo "</div>";
711 } elseif (strpos($key, "issue_") === 0) {
712 // display patient Issues
713 if ($first_issue) {
714 $prevIssueType = 'asdf1234!@#$'; // random junk so as to not match anything
715 $first_issue = 0;
716 echo "<hr />";
717 echo "<h4>" . xlt("Issues") . "</h4>";
720 preg_match('/^(.*)_(\d+)$/', $key, $res);
721 $rowid = $res[2];
722 $irow = sqlQuery("SELECT lists.type, lists.title, lists.comments, lists.diagnosis, " .
723 "lists.udi_data, medications.drug_dosage_instructions FROM lists LEFT JOIN " .
724 "( SELECT id AS lists_medication_id, list_id, drug_dosage_instructions " .
725 "FROM lists_medication ) medications ON medications.list_id = id " .
726 "WHERE id = ?", array($rowid));
727 $diagnosis = $irow['diagnosis'];
728 if ($prevIssueType != $irow['type']) {
729 // output a header for each Issue Type we encounter
730 $disptype = $ISSUE_TYPES[$irow['type']][0];
731 echo "<div class='issue_type font-weight-bold'><h5>" . text($disptype) . ":</h5></div>\n";
732 $prevIssueType = $irow['type'];
735 echo "<div class='text issue'>";
736 if ($prevIssueType == "medical_device") {
737 echo "<span class='issue_title'><span class='font-weight-bold'>" . xlt('Title') . ": </span>" . text($irow['title']) . "</span><br>";
738 echo "<span class='issue_title'>" . (new MedicalDevice($irow['udi_data']))->fullOutputHtml() . "</span>";
739 echo "<span class='issue_comments'> " . text($irow['comments']) . "</span><br><br>\n";
740 } else {
741 echo "<span class='issue_title font-weight-bold'>" . text($irow['title']) . ":</span>";
742 echo "<span class='issue_comments'> " . text($irow['comments']) . "</span>\n";
743 if ($prevIssueType == "medication") {
744 echo "<span class='issue_dosage_instructions'> " . text($irow['drug_dosage_instructions']) . "</span>\n";
748 // Show issue's chief diagnosis and its description:
749 if ($diagnosis) {
750 echo "<div class='text issue_diag'>";
751 echo "[" . xlt('Diagnosis') . "]<br />";
752 $dcodes = explode(";", $diagnosis);
753 foreach ($dcodes as $dcode) {
754 echo "<span class='italic'>" . text($dcode) . "</span>: ";
755 echo text(lookup_code_descriptions($dcode)) . "<br />\n";
758 //echo $diagnosis." -- ".lookup_code_descriptions($diagnosis)."\n";
759 echo "</div>";
762 // Supplemental data for GCAC or Contraception issues.
763 if ($irow['type'] == 'ippf_gcac') {
764 echo " <div class='table-responsive'><table class='table'>\n";
765 display_layout_rows('GCA', sqlQuery("SELECT * FROM lists_ippf_gcac WHERE id = ?", array($rowid)));
766 echo " </table></div>\n";
767 } elseif ($irow['type'] == 'contraceptive') {
768 echo " <div class='table-responsive'><table class='table'>\n";
769 display_layout_rows('CON', sqlQuery("SELECT * FROM lists_ippf_con WHERE id = ?", array($rowid)));
770 echo " </table></div>\n";
773 echo "</div>\n"; //end the issue DIV
774 } else {
775 // we have an "encounter form" form field whose name is like
776 // dirname_formid, with a value which is the encounter ID.
778 // display encounter forms, encoded as a POST variable
779 // in the format: <formdirname_formid>=<encounterID>
781 if (($auth_notes_a || $auth_notes || $auth_coding_a || $auth_coding || $auth_med || $auth_relaxed)) {
782 $form_encounter = $val;
783 preg_match('/^(.*)_(\d+)$/', $key, $res);
784 $form_id = $res[2];
785 $formres = getFormNameByFormdirAndFormid($res[1], $form_id);
786 $dateres = getEncounterDateByEncounter($form_encounter);
787 $formId = getFormIdByFormdirAndFormid($res[1], $form_id);
789 if ($res[1] == 'newpatient') {
790 echo "<div class='text encounter'>\n";
791 echo "<h4>" . xlt($formres["form_name"]) . "</h4>";
792 } else {
793 echo "<div class='text encounter_form'>";
794 echo "<h4>" . text(xl_form_title($formres["form_name"])) . "</h4>";
797 // show the encounter's date
798 echo "(" . text(oeFormatSDFT(strtotime($dateres["date"]))) . ") ";
799 if ($res[1] == 'newpatient') {
800 // display the provider info
801 echo ' ' . xlt('Provider') . ': ' . text(getProviderName(getProviderIdOfEncounter($form_encounter)));
804 echo "<br />\n";
806 // call the report function for the form
808 <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]); ?>">
809 <?php
810 $esign = $esignApi->createFormESign($formId, $res[1], $form_encounter);
811 if ($esign->isSigned('report') && !empty($GLOBALS['esign_report_show_only_signed'])) {
812 if (substr($res[1], 0, 3) == 'LBF') {
813 call_user_func("lbf_report", $pid, $form_encounter, $N, $form_id, $res[1]);
814 } else {
815 call_user_func($res[1] . "_report", $pid, $form_encounter, $N, $form_id);
817 } elseif (empty($GLOBALS['esign_report_show_only_signed'])) {
818 if (substr($res[1], 0, 3) == 'LBF') {
819 call_user_func('lbf_report', $pid, $form_encounter, $N, $form_id, $res[1]);
820 } else {
821 call_user_func($res[1] . '_report', $pid, $form_encounter, $N, $form_id);
823 } else {
824 echo "<h6>" . xlt("Not signed.") . "</h6>";
826 if ($esign->isLogViewable("report")) {
827 $esign->renderLog();
831 </div>
832 <?php
834 if ($res[1] == 'newpatient') {
835 // display billing info
836 $bres = sqlStatement(
837 "SELECT b.date, b.code, b.code_text, b.modifier " .
838 "FROM billing AS b, code_types AS ct WHERE " .
839 "b.pid = ? AND " .
840 "b.encounter = ? AND " .
841 "b.activity = 1 AND " .
842 "b.code_type = ct.ct_key AND " .
843 "ct.ct_diag = 0 " .
844 "ORDER BY b.date",
845 array($pid, $form_encounter)
847 while ($brow = sqlFetchArray($bres)) {
848 echo "<div class='font-weight-bold d-inline-block'>&nbsp;" . xlt('Procedure') . ": </div><div class='text d-inline-block'>" .
849 text($brow['code']) . ":" . text($brow['modifier']) . " " . text($brow['code_text']) . "</div><br />\n";
853 print "</div>";
854 } // end auth-check for encounter forms
855 } // end if('issue_')... else...
856 } // end if('include_')... else...
857 } // end $ar loop
859 if ($printable && !$PDF_OUTPUT) {// Patched out of pdf 04/20/2017 sjpadgett
860 echo "<br /><br />" . xlt('Signature') . ": _______________________________<br />";
864 </div> <!-- end of report_custom DIV -->
865 </div>
867 <?php
868 if ($PDF_OUTPUT) {
869 $content = getContent();
870 $ptd = report_basename($pid);
871 $fn = $ptd['base'] . ".pdf";
872 $pdf->SetTitle(ucfirst($ptd['fname']) . ' ' . $ptd['lname'] . ' ' . xl('Id') . ':' . $pid . ' ' . xl('Report'));
873 $isit_utf8 = preg_match('//u', $content); // quick check for invalid encoding
874 if (!$isit_utf8) {
875 if (function_exists('iconv')) { // if we can lets save the report
876 $content = iconv("UTF-8", "UTF-8//IGNORE", $content);
877 } else { // no sense going on.
878 $die_str = xlt("Failed UTF8 encoding check! Could not automatically fix.");
879 die($die_str);
883 try {
884 $pdf->writeHTML($content); // convert html
885 } catch (MpdfException $exception) {
886 die(text($exception));
889 if ($PDF_OUTPUT == 1) {
890 try {
891 if ($PDF_FAX === 1) {
892 $fax_pdf = $pdf->Output($fn, 'S');
893 $tmp_file = $GLOBALS['temporary_files_dir'] . '/' . $fn; // is deleted in sendFax...
894 file_put_contents($tmp_file, $fax_pdf);
895 echo $tmp_file;
896 exit();
897 } else {
898 if (!empty($archive_name) && sizeof($staged_docs) > 0) {
899 $rtn = zip_content(basename($fn), $archive_name, $pdf->Output($fn, 'S'));
900 header('Content-Description: File Transfer');
901 header('Content-Transfer-Encoding: binary');
902 header('Expires: 0');
903 header("Cache-control: private");
904 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
905 header("Content-Type: application/zip; charset=utf-8");
906 header("Content-Length: " . filesize($archive_name));
907 header('Content-Disposition: attachment; filename="' . basename($archive_name) . '"');
909 ob_end_clean();
910 @readfile($archive_name) or error_log("Archive temp file not found: " . $archive_name);
912 unlink($archive_name);
913 } else {
914 $pdf->Output($fn, $GLOBALS['pdf_output']); // D = Download, I = Inline
917 } catch (MpdfException $exception) {
918 die(text($exception));
920 } else {
921 // This is the case of writing the PDF as a message to the CMS portal.
922 $ptdata = getPatientData($pid, 'cmsportal_login');
923 $contents = $pdf->Output('', true);
924 echo "<html><head>\n";
925 Header::setupHeader();
926 echo "</head><body>\n";
927 $result = cms_portal_call(array(
928 'action' => 'putmessage',
929 'user' => $ptdata['cmsportal_login'],
930 'title' => xl('Your Clinical Report'),
931 'message' => xl('Please see the attached PDF.'),
932 'filename' => 'report.pdf',
933 'mimetype' => 'application/pdf',
934 'contents' => base64_encode($contents)
936 if ($result['errmsg']) {
937 die(text($result['errmsg']));
940 echo "<p class='mt-3'>" . xlt('Report has been sent to the patient.') . "</p>\n";
941 echo "</body></html>\n";
943 foreach ($tmp_files_remove as $tmp_file) {
944 // Remove the tmp files that were created
945 unlink($tmp_file);
947 } else {
949 <?php if (!$printable) { ?>
950 <script src="<?php echo $GLOBALS['web_root'] ?>/interface/patient_file/report/custom_report.js?v=<?php echo $v_js_includes; ?>"></script>
951 <script>
952 const searchBarHeight = document.querySelectorAll('.report_search_bar')[0].clientHeight;
953 document.getElementById('backLink').style.marginTop = `${searchBarHeight}px`;
954 </script>
955 <?php } ?>
957 </body>
958 </html>
959 <?php } ?>