fixes: CDR engine fixes for duplicate use of actions across rules in addition to...
[openemr.git] / ccr / createCCR.php
blob7535008af733c3fa99d52a5e263a29a62357d739
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 // check if using the patient portal
16 //(if so, then use the portal authorization)
17 if (isset($_GET['portal_auth'])) {
18 $landingpage = "../portal/index.php";
20 // Will start the (patient) portal OpenEMR session/cookie.
21 require_once(dirname(__FILE__) . "/../src/Common/Session/SessionUtil.php");
22 OpenEMR\Common\Session\SessionUtil::portalSessionStart();
24 if (isset($_SESSION['pid']) && isset($_SESSION['patient_portal_onsite_two'])) {
25 $pid = $_SESSION['pid'];
26 $ignoreAuth = true;
27 global $ignoreAuth;
28 } else {
29 OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
30 header('Location: ' . $landingpage . '?w');
31 exit;
33 } else {
34 // Check authorization.
35 $thisauth = AclMain::aclCheckCore('patients', 'pat_rep');
36 if (!$thisauth) {
37 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Create CCR")]);
38 exit;
42 require_once(dirname(__FILE__) . "/../interface/globals.php");
43 require_once(dirname(__FILE__) . "/../library/sql-ccr.inc.php");
44 require_once(dirname(__FILE__) . "/uuid.php");
45 require_once(dirname(__FILE__) . "/transmitCCD.php");
46 require_once(dirname(__FILE__) . "/../custom/code_types.inc.php");
48 use PHPMailer\PHPMailer\PHPMailer;
50 function createCCR($action, $raw = "no", $requested_by = "")
53 $authorID = getUuid();
54 $patientID = getUuid();
55 $sourceID = getUuid();
56 $oemrID = getUuid();
58 $result = getActorData();
59 while ($res = sqlFetchArray($result[2])) {
60 ${"labID{$res['id']}"} = getUuid();
63 $ccr = new DOMDocument('1.0', 'UTF-8');
64 $e_styleSheet = $ccr->createProcessingInstruction('xml-stylesheet', 'type="text/xsl" href="stylesheet/ccr.xsl"');
65 $ccr->appendChild($e_styleSheet);
67 $e_ccr = $ccr->createElementNS('urn:astm-org:CCR', 'ContinuityOfCareRecord');
68 $ccr->appendChild($e_ccr);
70 /////////////// Header
72 require_once("createCCRHeader.php");
73 $e_Body = $ccr->createElement('Body');
74 $e_ccr->appendChild($e_Body);
76 /////////////// Problems
78 $e_Problems = $ccr->createElement('Problems');
79 require_once("createCCRProblem.php");
80 $e_Body->appendChild($e_Problems);
82 /////////////// Alerts
84 $e_Alerts = $ccr->createElement('Alerts');
85 require_once("createCCRAlerts.php");
86 $e_Body->appendChild($e_Alerts);
88 ////////////////// Medication
90 $e_Medications = $ccr->createElement('Medications');
91 require_once("createCCRMedication.php");
92 $e_Body->appendChild($e_Medications);
94 ///////////////// Immunization
96 $e_Immunizations = $ccr->createElement('Immunizations');
97 require_once("createCCRImmunization.php");
98 $e_Body->appendChild($e_Immunizations);
101 /////////////////// Results
103 $e_Results = $ccr->createElement('Results');
104 require_once("createCCRResult.php");
105 $e_Body->appendChild($e_Results);
108 /////////////////// Procedures
110 //$e_Procedures = $ccr->createElement('Procedures');
111 //require_once("createCCRProcedure.php");
112 //$e_Body->appendChild($e_Procedures);
114 //////////////////// Footer
116 // $e_VitalSigns = $ccr->createElement('VitalSigns');
117 // $e_Body->appendChild($e_VitalSigns);
119 /////////////// Actors
121 $e_Actors = $ccr->createElement('Actors');
122 require_once("createCCRActor.php");
123 $e_ccr->appendChild($e_Actors);
125 if ($action == "generate") {
126 gnrtCCR($ccr, $raw, $requested_by);
129 if ($action == "viewccd") {
130 viewCCD($ccr, $raw, $requested_by);
134 function gnrtCCR($ccr, $raw = "no", $requested_by = "")
136 global $pid;
138 $ccr->preserveWhiteSpace = false;
139 $ccr->formatOutput = true;
141 if ($raw == "yes") {
142 // simply send the xml to a textarea (nice debugging tool)
143 echo "<textarea rows='35' cols='500' style='width:95%' readonly>";
144 echo $ccr->saveXml();
145 echo "</textarea>";
146 return;
147 } elseif ($raw == "hybrid") {
148 // send a file that contains a hybrid file of the raw xml and the xsl stylesheet
149 createHybridXML($ccr);
150 } elseif ($raw == "pure") {
151 // send a zip file that contains a separate xml data file and xsl stylesheet
152 if (! (class_exists('ZipArchive'))) {
153 displayError(xl("ERROR: Missing ZipArchive PHP Module"));
154 return;
157 $tempDir = $GLOBALS['temporary_files_dir'];
158 $zipName = $tempDir . "/" . getReportFilename() . "-ccr.zip";
159 if (file_exists($zipName)) {
160 unlink($zipName);
163 $zip = new ZipArchive();
164 if (!($zip)) {
165 displayError(xl("ERROR: Unable to Create Zip Archive."));
166 return;
169 if ($zip->open($zipName, ZipArchive::CREATE)) {
170 $zip->addFile("stylesheet/ccr.xsl", "stylesheet/ccr.xsl");
171 $xmlName = $tempDir . "/" . getReportFilename() . "-ccr.xml";
172 if (file_exists($xmlName)) {
173 unlink($xmlName);
176 $ccr->save($xmlName);
177 $zip->addFile($xmlName, basename($xmlName));
178 $zip->close();
179 header("Pragma: public");
180 header("Expires: 0");
181 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
182 header("Content-Type: application/force-download");
183 header("Content-Length: " . filesize($zipName));
184 header("Content-Disposition: attachment; filename=" . basename($zipName) . ";");
185 header("Content-Description: File Transfer");
186 readfile($zipName);
187 unlink($zipName);
188 unlink($xmlName);
189 exit(0);
190 } else {
191 displayError(xl("ERROR: Unable to Create Zip Archive."));
192 return;
194 } elseif (substr($raw, 0, 4) == "send") {
195 $recipient = trim(stripslashes(substr($raw, 5)));
196 $ccd_out = $ccr->saveXml();
197 $result = transmitCCD($pid, $ccd_out, $recipient, $requested_by, "CCR");
198 echo htmlspecialchars($result, ENT_NOQUOTES);
199 return;
200 } else {
201 header("Content-type: application/xml");
202 echo $ccr->saveXml();
206 function viewCCD($ccr, $raw = "no", $requested_by = "")
208 global $pid;
210 $ccr->preserveWhiteSpace = false;
211 $ccr->formatOutput = true;
213 if (file_exists(dirname(__FILE__) . '/generatedXml')) {
214 $ccr->save(dirname(__FILE__) . '/generatedXml/ccrForCCD.xml');
217 $xmlDom = new DOMDocument();
218 $xmlDom->loadXML($ccr->saveXML());
220 $ccr_ccd = new DOMDocument();
221 $ccr_ccd->load(dirname(__FILE__) . '/ccd/ccr_ccd.xsl');
223 $xslt = new XSLTProcessor();
224 $xslt->importStylesheet($ccr_ccd);
226 $ccd = new DOMDocument();
227 $ccd->preserveWhiteSpace = false;
228 $ccd->formatOutput = true;
230 $ccd->loadXML($xslt->transformToXML($xmlDom));
232 if (file_exists(dirname(__FILE__) . '/generatedXml')) {
233 $ccd->save(dirname(__FILE__) . '/generatedXml/ccdDebug.xml');
236 if ($raw == "yes") {
237 // simply send the xml to a textarea (nice debugging tool)
238 echo "<textarea rows='35' cols='500' style='width:95%' readonly>";
239 echo $ccd->saveXml();
240 echo "</textarea>";
241 return;
244 if ($raw == "pure") {
245 // send a zip file that contains a separate xml data file and xsl stylesheet
246 if (! (class_exists('ZipArchive'))) {
247 displayError(xl("ERROR: Missing ZipArchive PHP Module"));
248 return;
251 $tempDir = $GLOBALS['temporary_files_dir'];
252 $zipName = $tempDir . "/" . getReportFilename() . "-ccd.zip";
253 if (file_exists($zipName)) {
254 unlink($zipName);
257 $zip = new ZipArchive();
258 if (!($zip)) {
259 displayError(xl("ERROR: Unable to Create Zip Archive."));
260 return;
263 if ($zip->open($zipName, ZipArchive::CREATE)) {
264 $zip->addFile("stylesheet/cda.xsl", "stylesheet/cda.xsl");
265 $xmlName = $tempDir . "/" . getReportFilename() . "-ccd.xml";
266 if (file_exists($xmlName)) {
267 unlink($xmlName);
270 $e_styleSheet = $ccd->createProcessingInstruction(
271 'xml-stylesheet',
272 'type="text/xsl" href="stylesheet/cda.xsl"'
274 $ccd->insertBefore($e_styleSheet, $ccd->firstChild);
275 $ccd->save($xmlName);
276 $zip->addFile($xmlName, basename($xmlName));
277 $zip->close();
278 header("Pragma: public");
279 header("Expires: 0");
280 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
281 header("Content-Type: application/force-download");
282 header("Content-Length: " . filesize($zipName));
283 header("Content-Disposition: attachment; filename=" . basename($zipName) . ";");
284 header("Content-Description: File Transfer");
285 readfile($zipName);
286 unlink($zipName);
287 unlink($xmlName);
288 exit(0);
289 } else {
290 displayError(xl("ERROR: Unable to Create Zip Archive."));
291 return;
295 if (substr($raw, 0, 4) == "send") {
296 $recipient = trim(stripslashes(substr($raw, 5)));
297 $ccd_out = $ccd->saveXml();
298 $result = transmitCCD($pid, $ccd_out, $recipient, $requested_by);
299 echo htmlspecialchars($result, ENT_NOQUOTES);
300 return;
303 $ss = new DOMDocument();
304 $ss->load(dirname(__FILE__) . "/stylesheet/cda.xsl");
306 $xslt->importStyleSheet($ss);
308 $html = $xslt->transformToXML($ccd);
310 echo $html;
314 function sourceType($ccr, $uuid)
317 $e_Source = $ccr->createElement('Source');
319 $e_Actor = $ccr->createElement('Actor');
320 $e_Source->appendChild($e_Actor);
322 $e_ActorID = $ccr->createElement('ActorID', $uuid);
323 $e_Actor->appendChild($e_ActorID);
325 return $e_Source;
329 function displayError($message)
331 echo '<script>alert("' . addslashes($message) . '");</script>';
335 function createHybridXML($ccr)
338 // save the raw xml
339 $main_xml = $ccr->saveXml();
341 // save the stylesheet
342 $main_stylesheet = file_get_contents('stylesheet/ccr.xsl');
344 // replace stylesheet link in raw xml file
345 $substitute_string = '<?xml-stylesheet type="text/xsl" href="#style1"?>
346 <!DOCTYPE ContinuityOfCareRecord [
347 <!ATTLIST xsl:stylesheet id ID #REQUIRED>
350 $replace_string = '<?xml-stylesheet type="text/xsl" href="stylesheet/ccr.xsl"?>';
351 $main_xml = str_replace($replace_string, $substitute_string, $main_xml);
353 // remove redundant xml declaration from stylesheet
354 $replace_string = '<?xml version="1.0" encoding="UTF-8"?>';
355 $main_stylesheet = str_replace($replace_string, '', $main_stylesheet);
357 // embed the stylesheet in the raw xml file
358 $replace_string = '<ContinuityOfCareRecord xmlns="urn:astm-org:CCR">';
359 $main_stylesheet = $replace_string . $main_stylesheet;
360 $main_xml = str_replace($replace_string, $main_stylesheet, $main_xml);
362 // insert style1 id into the stylesheet parameter
363 $substitute_string = 'xsl:stylesheet id="style1" exclude-result-prefixes';
364 $replace_string = 'xsl:stylesheet exclude-result-prefixes';
365 $main_xml = str_replace($replace_string, $substitute_string, $main_xml);
367 // prepare the filename to use
368 // LASTNAME-FIRSTNAME-PID-DATESTAMP-ccr.xml
369 $main_filename = getReportFilename() . "-ccr.xml";
371 // send the output as a file to the user
372 header("Content-type: text/xml");
373 header("Content-Disposition: attachment; filename=" . $main_filename . "");
374 echo $main_xml;
377 if ($_POST['ccrAction']) {
378 $raw = $_POST['raw'];
379 /* If transmit requested, fail fast if the recipient address fails basic validation */
380 if (substr($raw, 0, 4) == "send") {
381 $send_to = trim(stripslashes(substr($raw, 5)));
382 if (!PHPMailer::ValidateAddress($send_to)) {
383 echo(htmlspecialchars(xl('Invalid recipient address. Please try again.'), ENT_QUOTES));
384 return;
387 createCCR($_POST['ccrAction'], $raw, $_POST['requested_by']);
388 } else {
389 createCCR($_POST['ccrAction'], $raw);