drop support for php 7.4 (#5740)
[openemr.git] / contrib / util / ccda_import / import_ccda.php
bloba20e3e79527057100e7a3320da0523cac0467b99
1 <?php
3 /**
4 * Import CCDA script
6 * Prior to use:
7 * 1. Turn on Carecoordination modules in OpenEMR.
8 * 2. Place ccdas in a directory.
9 * 3. Uncomment exit at top of this script.
10 * 4. Consider turning off the audit log (turn off both the 'Enable Audit Logging' and
11 * 'Audit all Emergency User Queries' settings) in OpenEMR to improve performance (if audit log
12 * not needed).
14 * Use:
15 * 1. use: php import_ccda.php <ccda-directory> <site> <openemr-directory> <development-mode>
16 * 2. use example: php import_ccda.php /var/www/localhost/htdocs/openemr/synthea default /var/www/localhost/htdocs/openemr true
17 * 3. use example: php import_ccda.php /var/www/localhost/htdocs/openemr/synthea default /var/www/localhost/htdocs/openemr false
18 * 4. Note that development-mode will markedly improve performance by bypassing the import of
19 * the ccda document and bypassing the use of the audit_master and audit_details tables and
20 * will directly import the new patient data from the ccda. Note this should never be done
21 * on sites that already contain real data/use. This will also turn off the audit log during
22 * the import.
23 * 5. Note that a log.txt file is created with log/stats of the run.
25 * Description of what this script automates (for unlimited number of ccda documents):
26 * 1. import ccda document (bypassed in development-mode)
27 * 2. import to ccda table (bypassed in development-mode)
28 * 3. import as new patient
29 * 4. run function to populate all the uuids via the universal service function that already exists
32 * @package OpenEMR
33 * @link https://www.open-emr.org
34 * @author Brady Miller <brady.g.miller@gmail.com>
35 * @copyright Copyright (c) 2021 Brady Miller <brady.g.miller@gmail.com>
36 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
39 // comment this out when using this script (and then uncomment it again when done using script)
40 exit;
42 if (php_sapi_name() !== 'cli' || count($argv) != 5) {
43 echo "Only php cli can execute a command\n";
44 echo "use: php import_ccda.php <ccda-directory> <site> <openemr-directory> <development-mode>\n";
45 echo "example use: php import_ccda.php /var/www/localhost/htdocs/openemr/synthea default /var/www/localhost/htdocs/openemr true\n";
46 echo "example use: php import_ccda.php /var/www/localhost/htdocs/openemr/synthea default /var/www/localhost/htdocs/openemr false\n";
47 die;
50 function outputMessage($message)
52 echo $message;
53 file_put_contents("log.txt", $message, FILE_APPEND);
56 // collect parameters (need to do before globals)
57 $dir = $argv[1] . '/*';
58 $_GET['site'] = $argv[2];
59 $openemrPath = $argv[3];
60 $seriousOptimizeFlag = $argv[4];
61 if ($seriousOptimizeFlag == "true") {
62 $seriousOptimize = true;
63 } else {
64 $seriousOptimize = false;
67 $ignoreAuth = 1;
68 require_once($openemrPath . "/interface/globals.php");
70 use OpenEMR\Common\Uuid\UuidRegistry;
72 // show parameters (need to do after globals)
73 outputMessage("ccda directory: " . $argv[1] . "\n");
74 outputMessage("site: " . $_SESSION['site_id'] . "\n");
75 outputMessage("openemr path: " . $openemrPath . "\n");
77 if ($seriousOptimize) {
78 outputMessage("development mode is on\n");
79 // temporarily disable the audit log
80 $auditLogSetting = sqlQueryNoLog("SELECT `gl_value` FROM `globals` WHERE `gl_name` = 'enable_auditlog'")['gl_value'] ?? 0;
81 sqlStatementNoLog("UPDATE `globals` SET `gl_value` = 0 WHERE `gl_name` = 'enable_auditlog'");
82 $auditLogBreakglassSetting = sqlQueryNoLog("SELECT `gl_value` FROM `globals` WHERE `gl_name` = 'gbl_force_log_breakglass'")['gl_value'] ?? 0;
83 sqlStatementNoLog("UPDATE `globals` SET `gl_value` = 0 WHERE `gl_name` = 'gbl_force_log_breakglass'");
84 } else {
85 outputMessage("development mode is off\n");
88 outputMessage("Starting patients import\n");
89 $counter = 0;
90 $millisecondsStart = round(microtime(true) * 1000);
91 foreach (glob($dir) as $file) {
92 if ($seriousOptimize) {
93 // development-mode is on (note step 1 and step 2 are bypassed)
94 // 3. import as new patient (note need to escape ' characters in the filename)
95 $file = str_replace("'", "\'", $file);
96 exec("php " . $openemrPath . "/bin/console openemr:ccda-newpatient-import --site=" . $_SESSION['site_id'] . " --document=" . $file);
97 } else {
98 // development mode is off
99 // 1. import ccda document
100 $fileContents = file_get_contents($file);
101 $document = new Document();
102 // TODO: collect CCDA category id instead of hardcoding 13
103 $document->createDocument('00', 13, basename($file), 'text/xml', $fileContents);
104 $documentId = $document->get_id();
105 // 2. import to ccda table
106 exec("php " . $openemrPath . "/bin/console openemr:ccda-import --site=" . $_SESSION['site_id'] . " --document_id=" . $documentId);
107 $auditId = sqlQueryNoLog("SELECT max(`id`) as `maxid` FROM `audit_master`")['maxid'];
108 // 3. import as new patient
109 exec("php " . $openemrPath . "/bin/console openemr:ccda-newpatient --site=" . $_SESSION['site_id'] . " --am_id=" . $auditId . " --document_id=" . $documentId);
111 $counter++;
112 $incrementCounter = 50; // echo every 50 records imported
113 if (($counter % $incrementCounter) == 0) {
114 $timeSec = round(((round(microtime(true) * 1000)) - $millisecondsStart) / 1000);
115 outputMessage($counter . " patients imported (" . $timeSec . " total seconds) (" . ((isset($lasttimeSec) ? ($timeSec - $lasttimeSec) : $timeSec) / $incrementCounter) . " average seconds per patient for last " . $incrementCounter . " patients)\n");
116 $lasttimeSec = $timeSec;
119 $timeSec = round(((round(microtime(true) * 1000)) - $millisecondsStart) / 1000);
120 echo outputMessage("Completed patients import (" . $counter . " patients) (" . $timeSec . " total seconds) (" . (($timeSec) / $counter) . " average seconds per patient)\n");
121 // 4. run function to populate all the uuids via the universal service function that already exists
122 echo outputMessage("Started uuid creation\n");
123 UuidRegistry::populateAllMissingUuids(false);
124 $timeSec = round(((round(microtime(true) * 1000)) - $millisecondsStart) / 1000);
125 echo outputMessage("Completed uuid creation (" . $timeSec . " total seconds; " . $timeSec / 3600 . " total hours)\n");
127 if ($seriousOptimize) {
128 // reset the audit log to the original value
129 sqlStatementNoLog("UPDATE `globals` SET `gl_value` = ? WHERE `gl_name` = 'enable_auditlog'", [$auditLogSetting]);
130 sqlStatementNoLog("UPDATE `globals` SET `gl_value` = ? WHERE `gl_name` = 'gbl_force_log_breakglass'", [$auditLogBreakglassSetting]);