diff --git a/interface/patient_file/report/custom_report.php b/interface/patient_file/report/custom_report.php index 85ec7d7149b..26c8fa2432e 100644 --- a/interface/patient_file/report/custom_report.php +++ b/interface/patient_file/report/custom_report.php @@ -40,6 +40,10 @@ $GLOBALS['PATIENT_REPORT_ACTIVE'] = true; $PDF_OUTPUT = empty($_POST['pdf']) ? 0 : intval($_POST['pdf']); +$PDF_FAX = empty($_POST['fax']) ? 0 : intval($_POST['fax']); +if ($PDF_FAX) { + $PDF_OUTPUT = 1; +} if ($PDF_OUTPUT) { $config_mpdf = array( @@ -817,7 +821,10 @@ function postToGet($arin) if ($PDF_OUTPUT) { $content = getContent(); $ptd = getPatientData($pid, "fname,lname"); - $fn = strtolower($ptd['fname'] . '_' . $ptd['lname'] . '_' . $pid . '_' . xl('report') . '.pdf'); + // 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') . '.pdf')); $pdf->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) { @@ -837,7 +844,15 @@ function postToGet($arin) if ($PDF_OUTPUT == 1) { try { - $pdf->Output($fn, $GLOBALS['pdf_output']); // D = Download, I = Inline + if ($PDF_FAX === 1) { + $fax_pdf = $pdf->Output($fn, 'S'); + $tmp_file = $GLOBALS['temporary_files_dir'] . '/' . $fn; // is deleted in sendFax... + file_put_contents($tmp_file, $fax_pdf); + echo $tmp_file; + exit(); + } else { + $pdf->Output($fn, $GLOBALS['pdf_output']); // D = Download, I = Inline + } } catch (MpdfException $exception) { die(text($exception)); } diff --git a/interface/patient_file/report/patient_report.php b/interface/patient_file/report/patient_report.php index 18ac1322d70..21ca774257c 100644 --- a/interface/patient_file/report/patient_report.php +++ b/interface/patient_file/report/patient_report.php @@ -6,6 +6,10 @@ * @link http://www.open-emr.org * @author Brady Miller * @copyright Copyright (c) 2017-2018 Brady Miller + * @author Stephen Nielson + * @copyright Copyright (c) 2019 Stephen Nielson + * @author Jerry Padgett + * @copyright Copyright (c) 2019 Jerry Padgett * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ @@ -34,6 +38,7 @@ $auth_med = acl_check('patients', 'med'); $auth_demo = acl_check('patients', 'demo'); +$oefax = !empty($GLOBALS['oefax_enable']) ? $GLOBALS['oefax_enable'] : 0; /** * @var EventDispatcherInterface $eventDispatcher The event dispatcher / listener object */ @@ -268,7 +273,9 @@ function show_date_fun(){ dispatch(OpenEMR\Events\PatientReport::ACTIONS_RENDER_POST, new GenericEvent()); + if ($oefax) { + $eventDispatcher->dispatch(PatientReportEvent::ACTIONS_RENDER_POST, new GenericEvent()); + } ?>
@@ -751,7 +758,9 @@ function(data) { dispatch(PatientReportEvent::JAVASCRIPT_READY_POST, new GenericEvent()); + if ($oefax) { + $eventDispatcher->dispatch(PatientReportEvent::JAVASCRIPT_READY_POST, new GenericEvent()); + } ?> }); diff --git a/library/dialog.js b/library/dialog.js index 91105549dc6..2724888ff3c 100644 --- a/library/dialog.js +++ b/library/dialog.js @@ -65,7 +65,7 @@ function dlgOpenWindow(url, winname, width, height) { } top.modaldialog = cascwin(url, winname, width, height, "resizable=1,scrollbars=1,location=0,toolbar=0"); - grabfocus(top); + return false; } @@ -231,26 +231,26 @@ if (typeof alertMsg !== "function") { console.log(error.message) }); } + const persistUserOption = function (option, value) { + return $.ajax({ + url: top.webroot_url + "/library/ajax/user_settings.php", + type: 'post', + contentType: 'application/x-www-form-urlencoded', + data: { + csrf_token_form: top.csrf_token_js, + target: option, + setting: value + }, + beforeSend: function () { + top.restoreSession; + }, + error: function (jqxhr, status, errorThrown) { + console.log(errorThrown); + } + }); + }; } -const persistUserOption = function (option, value) { - return $.ajax({ - url: top.webroot_url + "/library/ajax/user_settings.php", - type: 'post', - contentType: 'application/x-www-form-urlencoded', - data: { - csrf_token_form: top.csrf_token_js, - target: option, - setting: value - }, - beforeSend: function () { - top.restoreSession; - }, - error: function (jqxhr, status, errorThrown) { - console.log(errorThrown); - } - }); -}; // Test if supporting dialog callbacks and close dependencies are in scope. diff --git a/library/globals.inc.php b/library/globals.inc.php index 56eaa1b7f27..9e76332a87e 100644 --- a/library/globals.inc.php +++ b/library/globals.inc.php @@ -2028,6 +2028,17 @@ function gblTimeZones() // 'Notifications' => array( + 'oefax_enable' => array( + xl('Enable Fax SMS Module'), + array( + 0 => xl('Disabled'), + 1 => xl('RingCentral'), + 2 => xl('Twilio'), + ), + '0', + xl('Enable Fax SMS Support. Remember to install fax module.') + ), + 'patient_reminder_sender_name' => array( xl('Patient Reminder Sender Name'), 'text', // data type @@ -2789,9 +2800,9 @@ function gblTimeZones() 'fhir_enable' => array( xl('Enable FHIR Provider Client Service'), array( - 0 => xl('Off: No Service.'), - 1 => xl('On: HAPI FHIR.'), - 2 => xl('On: Smart on FHIR.'), + 0 => xl('Disabled'), + 1 => xl('HAPI FHIR'), + 2 => xl('Smart on FHIR'), ), '0', xl('Enable FHIR Provider Client Service') diff --git a/library/smarty/plugins/function.dispatchPatientDocumentEvent.php b/library/smarty/plugins/function.dispatchPatientDocumentEvent.php new file mode 100644 index 00000000000..8204560f4f6 --- /dev/null +++ b/library/smarty/plugins/function.dispatchPatientDocumentEvent.php @@ -0,0 +1,55 @@ + + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + */ + +use OpenEMR\Events\PatientDocuments\PatientDocumentEvent; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\GenericEvent; + +/** + * Smarty {dispatchPatientDocumentEvent} function plugin + * + * Type: function
+ * Name: dispatchPatientDocumentEvent
+ * Purpose: Event listener for PatientDocumentEvent
+ * + * Examples: + * + * {dispatchPatientDocumentEvent event="javascript_ready_fax_dialog"} + * {dispatchPatientDocumentEvent event="actions_render_fax_anchor"} + * + * @param array + * @param Smarty + */ + + +function smarty_function_dispatchPatientDocumentEvent($params, &$smarty) +{ + if (empty($params['event'])) { + $smarty->trigger_error("dispatchPatientDocumentEvent: missing 'event' parameter"); + return; + } else { + $event = $params['event']; + } + + $eventDispatcher = $GLOBALS['kernel']->getEventDispatcher(); + if ($event == "javascript_ready_fax_dialog") { + $eventDispatcher->dispatch(PatientDocumentEvent::JAVASCRIPT_READY_FAX_DIALOG, new GenericEvent()); + } else if ($event == "actions_render_fax_anchor") { + $eventDispatcher->dispatch(PatientDocumentEvent::ACTIONS_RENDER_FAX_ANCHOR, new GenericEvent()); + } else { + $smarty->trigger_error("dispatchPatientDocumentEvent: invalid 'event' parameter"); + return; + } +} diff --git a/src/Core/ModulesApplication.php b/src/Core/ModulesApplication.php index 974c77961ae..98d12bc8571 100644 --- a/src/Core/ModulesApplication.php +++ b/src/Core/ModulesApplication.php @@ -1,7 +1,7 @@ get('ModuleManager')->loadModules(); // Prepare list of listeners to bootstrap - $listenersFromAppConfig = isset($configuration['listeners']) ? $configuration['listeners'] : []; - $config = $serviceManager->get('config'); + $listenersFromAppConfig = isset($configuration['listeners']) ? $configuration['listeners'] : []; + $config = $serviceManager->get('config'); $listenersFromConfigService = isset($config['listeners']) ? $config['listeners'] : []; $listeners = array_unique(array_merge($listenersFromConfigService, $listenersFromAppConfig)); @@ -75,7 +75,7 @@ private function bootstrapCustomModules($eventDispatcher, $customModulePath) $resultSet = sqlStatementNoLog($statement = "SELECT mod_name, mod_directory FROM modules WHERE mod_active = 1 AND type != 1 ORDER BY `mod_ui_order`, `date`"); $db_modules = []; while ($row = sqlFetchArray($resultSet)) { - $db_modules[] = ["name" => $row["mod_name"], "directory" => $row['mod_directory'], "path" => $customModulePath . $row['mod_directory'] ]; + $db_modules[] = ["name" => $row["mod_name"], "directory" => $row['mod_directory'], "path" => $customModulePath . $row['mod_directory']]; } foreach ($db_modules as $module) { $this->loadCustomModule($module, $eventDispatcher); @@ -85,17 +85,16 @@ private function bootstrapCustomModules($eventDispatcher, $customModulePath) private function loadCustomModule($module, $eventDispatcher) { - if (!is_readable($module['path'] . DIRECTORY_SEPARATOR . self::CUSTOM_MODULE_BOOSTRAP_NAME)) { - // TODO: stephen need to escape filename here. + if (!is_readable($module['path'] . '/' . attr(self::CUSTOM_MODULE_BOOSTRAP_NAME))) { error_log("Custom module file path " . errorLogEscape($module['path']) - . DIRECTORY_SEPARATOR . self::CUSTOM_MODULE_BOOSTRAP_NAME + . '/' . self::CUSTOM_MODULE_BOOSTRAP_NAME . " is not readable. Check directory permissions"); } try { // the only thing in scope here is $module and $eventDispatcher which is ok for our bootstrap piece. // do we really want to just include a file?? Should we go all zend and actually force a class instantiation // here and then inject the EventDispatcher or even possibly the Symfony Kernel here? - include $module['path'] . DIRECTORY_SEPARATOR . self::CUSTOM_MODULE_BOOSTRAP_NAME; + include $module['path'] . '/' . attr(self::CUSTOM_MODULE_BOOSTRAP_NAME); } catch (Exception $exception) { error_log(errorLogEscape($exception->getMessage())); } diff --git a/src/Events/PatientDocuments/PatientDocumentEvent.php b/src/Events/PatientDocuments/PatientDocumentEvent.php new file mode 100644 index 00000000000..064f1fe8a63 --- /dev/null +++ b/src/Events/PatientDocuments/PatientDocumentEvent.php @@ -0,0 +1,20 @@ + + * @copyright Copyright (c) 2019 Jerry Padgett + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +namespace OpenEMR\Events\PatientDocuments; + +use Symfony\Component\EventDispatcher\Event; + +class PatientDocumentEvent extends Event +{ + const ACTIONS_RENDER_FAX_ANCHOR = 'documents.actions.render.fax.anchor'; + const JAVASCRIPT_READY_FAX_DIALOG = 'documents.javascript.fax.dialog'; +} diff --git a/src/Events/PatientReport/PatientReportEvent.php b/src/Events/PatientReport/PatientReportEvent.php index 51e1ae4f00b..0c8db976605 100644 --- a/src/Events/PatientReport/PatientReportEvent.php +++ b/src/Events/PatientReport/PatientReportEvent.php @@ -1,11 +1,21 @@ + * @copyright Copyright (c) 2019 Stephen Nielson + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + namespace OpenEMR\Events\PatientReport; use Symfony\Component\EventDispatcher\Event; class PatientReportEvent extends Event { - /** * This event fires after the action buttons for the report have rendered. * It allows listeners to render additional content or buttons. diff --git a/templates/documents/general_view.html b/templates/documents/general_view.html index a151882a1e3..020fd120b8a 100644 --- a/templates/documents/general_view.html +++ b/templates/documents/general_view.html @@ -5,11 +5,15 @@ * @link http://www.open-emr.org * @author Brady Miller * @copyright Copyright (c) 2017-2019 Brady Miller + * @author Jerry Padgett + * @copyright Copyright (c) 2018-2019 Jerry Padgett * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 *} + {if $GLOBALS.oefax_enable} + {dispatchPatientDocumentEvent event="actions_render_fax_anchor"} + {/if} + {xlt t='Pop Out'} {xlt t='Download'} {xlt t='Show Notes'} {$delete_string}