Feat openemr fix 7480 7494 email prescription (#7495)
[openemr.git] / ccr / createCCR.php
blob0f399d307e61a47b108acd4fc579a2c560607c26
1 <?php
3 /**
4 * CCR Script.
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Garden State Health Systems <http://www.gshsys.com/>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @copyright Copyright (c) 2010 Garden State Health Systems <http://www.gshsys.com/>
11 * @copyright Copyright (c) 2018-2019 Brady Miller <brady.g.miller@gmail.com>
12 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
15 use OpenEMR\Common\Session\SessionUtil;
17 // check if using the patient portal
18 //(if so, then use the portal authorization)
19 $notPatientPortal = false;
20 if (isset($_GET['portal_auth'])) {
21 $landingpage = "../portal/index.php";
23 // Will start the (patient) portal OpenEMR session/cookie.
24 require_once(dirname(__FILE__) . "/../src/Common/Session/SessionUtil.php");
25 SessionUtil::portalSessionStart();
27 if (isset($_SESSION['pid']) && isset($_SESSION['patient_portal_onsite_two'])) {
28 $pid = $_SESSION['pid'];
29 $ignoreAuth = true;
30 global $ignoreAuth;
31 } else {
32 SessionUtil::portalSessionCookieDestroy();
33 header('Location: ' . $landingpage . '?w');
34 exit;
36 } else {
37 // Check authorization.
38 $notPatientPortal = true;
41 require_once(dirname(__FILE__) . "/../interface/globals.php");
42 require_once(dirname(__FILE__) . "/../library/sql-ccr.inc.php");
43 require_once(dirname(__FILE__) . "/uuid.php");
44 require_once(dirname(__FILE__) . "/transmitCCD.php");
45 require_once(dirname(__FILE__) . "/../custom/code_types.inc.php");
47 use OpenEMR\Common\Acl\AclMain;
48 use OpenEMR\Common\Twig\TwigContainer;
49 use PHPMailer\PHPMailer\PHPMailer;
51 if ($notPatientPortal) {
52 $thisauth = AclMain::aclCheckCore('patients', 'pat_rep');
53 if (!$thisauth) {
54 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Create CCR")]);
55 exit;
59 function createCCR($action, $raw = "no", $requested_by = "")
62 $authorID = getUuid();
63 $patientID = getUuid();
64 $sourceID = getUuid();
65 $oemrID = getUuid();
67 $result = getActorData();
68 while ($res = sqlFetchArray($result[2])) {
69 ${"labID{$res['id']}"} = getUuid();
72 $ccr = new DOMDocument('1.0', 'UTF-8');
73 $e_styleSheet = $ccr->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="stylesheet/ccr.xsl"');
74 $ccr->appendChild($e_styleSheet);
76 $e_ccr = $ccr->createElementNS('urn:astm-org:CCR', 'ContinuityOfCareRecord');
77 $ccr->appendChild($e_ccr);
79 /////////////// Header
81 require_once("createCCRHeader.php");
82 $e_Body = $ccr->createElement('Body');
83 $e_ccr->appendChild($e_Body);
85 /////////////// Problems
87 $e_Problems = $ccr->createElement('Problems');
88 require_once("createCCRProblem.php");
89 $e_Body->appendChild($e_Problems);
91 /////////////// Alerts
93 $e_Alerts = $ccr->createElement('Alerts');
94 require_once("createCCRAlerts.php");
95 $e_Body->appendChild($e_Alerts);
97 ////////////////// Medication
99 $e_Medications = $ccr->createElement('Medications');
100 require_once("createCCRMedication.php");
101 $e_Body->appendChild($e_Medications);
103 ///////////////// Immunization
105 $e_Immunizations = $ccr->createElement('Immunizations');
106 require_once("createCCRImmunization.php");
107 $e_Body->appendChild($e_Immunizations);
110 /////////////////// Results
112 $e_Results = $ccr->createElement('Results');
113 require_once("createCCRResult.php");
114 $e_Body->appendChild($e_Results);
117 /////////////////// Procedures
119 //$e_Procedures = $ccr->createElement('Procedures');
120 //require_once("createCCRProcedure.php");
121 //$e_Body->appendChild($e_Procedures);
123 //////////////////// Footer
125 // $e_VitalSigns = $ccr->createElement('VitalSigns');
126 // $e_Body->appendChild($e_VitalSigns);
128 /////////////// Actors
130 $e_Actors = $ccr->createElement('Actors');
131 require_once("createCCRActor.php");
132 $e_ccr->appendChild($e_Actors);
134 if ($action == "generate") {
135 gnrtCCR($ccr, $raw, $requested_by);
138 if ($action == "viewccd") {
139 viewCCD($ccr, $raw, $requested_by);
143 function gnrtCCR($ccr, $raw = "no", $requested_by = "")
145 global $pid;
147 $ccr->preserveWhiteSpace = false;
148 $ccr->formatOutput = true;
150 if ($raw == "yes") {
151 // simply send the xml to a textarea (nice debugging tool)
152 echo "<textarea rows='35' cols='500' style='width:95%' readonly>";
153 echo $ccr->saveXml();
154 echo "</textarea>";
155 return;
156 } elseif ($raw == "hybrid") {
157 // send a file that contains a hybrid file of the raw xml and the xsl stylesheet
158 createHybridXML($ccr);
159 } elseif ($raw == "pure") {
160 // send a zip file that contains a separate xml data file and xsl stylesheet
161 if (! (class_exists('ZipArchive'))) {
162 displayError(xl("ERROR: Missing ZipArchive PHP Module"));
163 return;
166 $tempDir = $GLOBALS['temporary_files_dir'];
167 $zipName = $tempDir . "/" . getReportFilename() . "-ccr.zip";
168 if (file_exists($zipName)) {
169 unlink($zipName);
172 $zip = new ZipArchive();
173 if (!($zip)) {
174 displayError(xl("ERROR: Unable to Create Zip Archive."));
175 return;
178 if ($zip->open($zipName, ZipArchive::CREATE)) {
179 $zip->addFile("stylesheet/ccr.xsl", "stylesheet/ccr.xsl");
180 $xmlName = $tempDir . "/" . getReportFilename() . "-ccr.xml";
181 if (file_exists($xmlName)) {
182 unlink($xmlName);
185 $ccr->save($xmlName);
186 $zip->addFile($xmlName, basename($xmlName));
187 $zip->close();
188 header("Pragma: public");
189 header("Expires: 0");
190 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
191 header("Content-Type: application/force-download");
192 header("Content-Length: " . filesize($zipName));
193 header("Content-Disposition: attachment; filename=" . basename($zipName) . ";");
194 header("Content-Description: File Transfer");
195 readfile($zipName);
196 unlink($zipName);
197 unlink($xmlName);
198 exit(0);
199 } else {
200 displayError(xl("ERROR: Unable to Create Zip Archive."));
201 return;
203 } elseif (substr($raw, 0, 4) == "send") {
204 $recipient = trim(stripslashes(substr($raw, 5)));
205 $ccd_out = $ccr->saveXml();
206 $result = transmitCCD($pid, $ccd_out, $recipient, $requested_by, "CCR");
207 echo htmlspecialchars($result, ENT_NOQUOTES);
208 return;
209 } else {
210 header("Content-type: application/xml");
211 echo $ccr->saveXml();
215 function viewCCD($ccr, $raw = "no", $requested_by = "")
217 global $pid;
219 $ccr->preserveWhiteSpace = false;
220 $ccr->formatOutput = true;
222 if (file_exists(dirname(__FILE__) . '/generatedXml')) {
223 $ccr->save(dirname(__FILE__) . '/generatedXml/ccrForCCD.xml');
226 $xmlDom = new DOMDocument();
227 $xmlDom->loadXML($ccr->saveXML());
229 $ccr_ccd = new DOMDocument();
230 $ccr_ccd->load(dirname(__FILE__) . '/ccd/ccr_ccd.xsl');
232 $xslt = new XSLTProcessor();
233 $xslt->importStylesheet($ccr_ccd);
235 $ccd = new DOMDocument();
236 $ccd->preserveWhiteSpace = false;
237 $ccd->formatOutput = true;
239 $ccd->loadXML($xslt->transformToXML($xmlDom));
241 if (file_exists(dirname(__FILE__) . '/generatedXml')) {
242 $ccd->save(dirname(__FILE__) . '/generatedXml/ccdDebug.xml');
245 if ($raw == "yes") {
246 // simply send the xml to a textarea (nice debugging tool)
247 echo "<textarea rows='35' cols='500' style='width:95%' readonly>";
248 echo $ccd->saveXml();
249 echo "</textarea>";
250 return;
253 if ($raw == "pure") {
254 // send a zip file that contains a separate xml data file and xsl stylesheet
255 if (! (class_exists('ZipArchive'))) {
256 displayError(xl("ERROR: Missing ZipArchive PHP Module"));
257 return;
260 $tempDir = $GLOBALS['temporary_files_dir'];
261 $zipName = $tempDir . "/" . getReportFilename() . "-ccd.zip";
262 if (file_exists($zipName)) {
263 unlink($zipName);
266 $zip = new ZipArchive();
267 if (!($zip)) {
268 displayError(xl("ERROR: Unable to Create Zip Archive."));
269 return;
272 if ($zip->open($zipName, ZipArchive::CREATE)) {
273 $zip->addFile("stylesheet/cda.xsl", "stylesheet/cda.xsl");
274 $xmlName = $tempDir . "/" . getReportFilename() . "-ccd.xml";
275 if (file_exists($xmlName)) {
276 unlink($xmlName);
279 $e_styleSheet = $ccd->createProcessingInstruction(
280 'xml-stylesheet',
281 'type="text/xsl" href="stylesheet/cda.xsl"'
283 $ccd->insertBefore($e_styleSheet, $ccd->firstChild);
284 $ccd->save($xmlName);
285 $zip->addFile($xmlName, basename($xmlName));
286 $zip->close();
287 header("Pragma: public");
288 header("Expires: 0");
289 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
290 header("Content-Type: application/force-download");
291 header("Content-Length: " . filesize($zipName));
292 header("Content-Disposition: attachment; filename=" . basename($zipName) . ";");
293 header("Content-Description: File Transfer");
294 readfile($zipName);
295 unlink($zipName);
296 unlink($xmlName);
297 exit(0);
298 } else {
299 displayError(xl("ERROR: Unable to Create Zip Archive."));
300 return;
304 if (substr($raw, 0, 4) == "send") {
305 $recipient = trim(stripslashes(substr($raw, 5)));
306 $ccd_out = $ccd->saveXml();
307 $result = transmitCCD($pid, $ccd_out, $recipient, $requested_by);
308 echo htmlspecialchars($result, ENT_NOQUOTES);
309 return;
312 $ss = new DOMDocument();
313 $ss->load(dirname(__FILE__) . "/stylesheet/cda.xsl");
315 $xslt->importStyleSheet($ss);
317 $html = $xslt->transformToXML($ccd);
319 echo $html;
323 function sourceType($ccr, $uuid)
326 $e_Source = $ccr->createElement('Source');
328 $e_Actor = $ccr->createElement('Actor');
329 $e_Source->appendChild($e_Actor);
331 $e_ActorID = $ccr->createElement('ActorID', $uuid);
332 $e_Actor->appendChild($e_ActorID);
334 return $e_Source;
338 function displayError($message)
340 echo '<script>alert("' . addslashes($message) . '");</script>';
344 function createHybridXML($ccr)
347 // save the raw xml
348 $main_xml = $ccr->saveXml();
350 // save the stylesheet
351 $main_stylesheet = file_get_contents('stylesheet/ccr.xsl');
353 // replace stylesheet link in raw xml file
354 $substitute_string = '<?xml-stylesheet type="text/xsl" href="#style1"?>
355 <!DOCTYPE ContinuityOfCareRecord [
356 <!ATTLIST xsl:stylesheet id ID #REQUIRED>
359 $replace_string = '<?xml-stylesheet type="text/xsl" href="stylesheet/ccr.xsl"?>';
360 $main_xml = str_replace($replace_string, $substitute_string, $main_xml);
362 // remove redundant xml declaration from stylesheet
363 $replace_string = '<?xml version="1.0" encoding="UTF-8"?>';
364 $main_stylesheet = str_replace($replace_string, '', $main_stylesheet);
366 // embed the stylesheet in the raw xml file
367 $replace_string = '<ContinuityOfCareRecord xmlns="urn:astm-org:CCR">';
368 $main_stylesheet = $replace_string . $main_stylesheet;
369 $main_xml = str_replace($replace_string, $main_stylesheet, $main_xml);
371 // insert style1 id into the stylesheet parameter
372 $substitute_string = 'xsl:stylesheet id="style1" exclude-result-prefixes';
373 $replace_string = 'xsl:stylesheet exclude-result-prefixes';
374 $main_xml = str_replace($replace_string, $substitute_string, $main_xml);
376 // prepare the filename to use
377 // LASTNAME-FIRSTNAME-PID-DATESTAMP-ccr.xml
378 $main_filename = getReportFilename() . "-ccr.xml";
380 // send the output as a file to the user
381 header("Content-type: text/xml");
382 header("Content-Disposition: attachment; filename=" . $main_filename . "");
383 echo $main_xml;
386 if ($_POST['ccrAction']) {
387 $raw = $_POST['raw'];
388 /* If transmit requested, fail fast if the recipient address fails basic validation */
389 if (substr($raw, 0, 4) == "send") {
390 $send_to = trim(stripslashes(substr($raw, 5)));
391 if (!PHPMailer::ValidateAddress($send_to)) {
392 echo(htmlspecialchars(xl('Invalid recipient address. Please try again.'), ENT_QUOTES));
393 return;
396 createCCR($_POST['ccrAction'], $raw, $_POST['requested_by']);
397 } else {
398 createCCR($_POST['ccrAction'], $raw);