Fix for exporting a large number of lists.
[openemr.git] / library / standard_tables_capture.inc
blob3e11663a3a6f5aac304fa50a2ec1f0bebc40cea0
1 <?php
3 /**
4  * This library contains functions that implement the database load processing
5  * of external database files into openEMR
6  *
7  * @package   OpenEMR
8  * @link      https://www.open-emr.org
9  * @author    Rohit Kumar <pandit.rohit@netsity.com>
10  * @author    (Mac) Kevin McAloon <mcaloon@patienthealthcareanalytics.com>
11  * @author    Brady Miller <brady.g.miller@gmail.com>
12  * @author    Roberto Vasquez <robertogagliotta@gmail.com>
13  * @author    Stephen Waite <stephen.waite@cmsvt.com>
14  * @copyright Copyright (c) 2011 Phyaura, LLC <info@phyaura.com>
15  * @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com>
16  * @copyright Copyright (c) 2019 Stephen Waite <stephen.waite@cmsvt.com>
17  * @license   https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
18  */
20 // Function to copy a package to temp
21 // $type (RXNORM, SNOMED etc.)
22 function temp_copy($filename, $type)
25     if (!file_exists($filename)) {
26         return false;
27     }
29     if (!file_exists($GLOBALS['temporary_files_dir'] . "/" . $type)) {
30         if (!mkdir($GLOBALS['temporary_files_dir'] . "/" . $type, 0777, true)) {
31                 return false;
32         }
33     }
35     if (copy($filename, $GLOBALS['temporary_files_dir'] . "/" . $type . "/" . basename($filename))) {
36         return true;
37     } else {
38         return false;
39     }
42 // Function to unarchive a package
43 // $type (RXNORM, SNOMED etc.)
44 function temp_unarchive($filename, $type)
46     $filename = $GLOBALS['temporary_files_dir'] . "/" . $type . "/" . basename($filename);
47     if (!file_exists($filename)) {
48         return false;
49     } elseif ($type == "ICD10") {
50         // copy zip file contents to /tmp/ICD10 due to CMS zip file
51         $zip = new ZipArchive();
52         $path = $GLOBALS['temporary_files_dir'] . "/" . $type;
53         if ($zip->open($filename) === true) {
54             for ($i = 0; $i < $zip->numFiles; $i++) {
55                 $sub_dir_filename = $zip->getNameIndex($i);
56                 $fileinfo = pathinfo($sub_dir_filename);
57                 if (!(copy("zip://" . $filename . "#" . $sub_dir_filename, "$path/" . $fileinfo['basename']))) {
58                     return false;
59                 }
60             }
61             $zip->close();
62             return true;
63         } else {
64             return false;
65         }
66     } else {
67         // unzip the file
68         $zip = new ZipArchive();
69         if ($zip->open($filename) === true) {
70             if (!($zip->extractTo($GLOBALS['temporary_files_dir'] . "/" . $type))) {
71                 return false;
72             }
73             $zip->close();
74             return true;
75         }
76     }
79 // Function to import the RXNORM tables
80 // $is_windows_flag - pass the IS_WINDOWS constant
81 function rxnorm_import($is_windows_flag)
84     // set paths
85     $dirScripts = $GLOBALS['temporary_files_dir'] . "/RXNORM/scripts/mysql";
86     $dir = $GLOBALS['temporary_files_dir'] . "/RXNORM/rrf";
87     $dir = str_replace('\\', '/', $dir);
89     $rx_info = array();
90     $rx_info['rxnatomarchive'] = array('title' => "Archive Data", 'dir' => "$dir", 'origin' => "RXNATOMARCHIVE.RRF", 'filename' => "RXNATOMARCHIVE.RRF", 'table' => "rxnatomarchive", 'required' => 0);
91     $rx_info['rxnconso'] = array('title' => "Concept Names and Sources", 'dir' => "$dir", 'origin' => "RXNCONSO.RRF", 'filename' => "RXNCONSO.RRF", 'table' => "rxnconso",  'required' => 1);
92     $rx_info['rxncui'] = array('title' => "Retired RXCUI Data", 'dir' => "$dir", 'origin' => "RXNCUI.RRF", 'filename' => "RXNCUI.RRF", 'table' => "rxncui", 'required' => 1);
93     $rx_info['rxncuichanges'] = array('title' => "Concept Changes", 'dir' => "$dir", 'origin' => "RXNCUICHANGES.RRF", 'filename' => "RXNCUICHANGES.RRF", 'table' => "rxncuichanges", 'required' => 1);
94     $rx_info['rxndoc'] = array('title' => "Documentation for Abbreviated Values", 'dir' => "$dir", 'origin' => "RXNDOC.RRF", 'filename' => "RXNDOC.RRF", 'table' => "rxndoc", 'required' => 1);
95     $rx_info['rxnrel'] = array('title' => "Relationships", 'dir' => "$dir", 'origin' => "RXNREL.RRF", 'filename' => "RXNREL.RRF", 'table' => "rxnrel", 'required' => 1);
96     $rx_info['rxnsab'] = array('title' => "Source Information", 'dir' => "$dir", 'origin' => "RXNSAB.RRF", 'filename' => "RXNSAB.RRF", 'table' => "rxnsab", 'required' => 0);
97     $rx_info['rxnsat'] = array('title' => "Simple Concept and Atom Attributes", 'dir' => "$dir", 'origin' => "RXNSAT.RRF", 'filename' => "RXNSAT.RRF", 'table' => "rxnsat", 'required' => 0);
98     $rx_info['rxnsty'] = array('title' => "Semantic Types ", 'dir' => "$dir", 'origin' => "RXNSTY.RRF", 'filename' => "RXNSTY.RRF", 'table' => "rxnsty", 'required' => 1);
100     // load scripts
101     $file_load = file_get_contents($dirScripts . '/Table_scripts_mysql_rxn.sql', true);
102     if ($is_windows_flag) {
103         $data_load = file_get_contents($dirScripts . '/Load_scripts_mysql_rxn_win.sql', true);
104     } else {
105         $data_load = file_get_contents($dirScripts . '/Load_scripts_mysql_rxn_unix.sql', true);
106     }
108     $indexes_load = file_get_contents($dirScripts . '/Indexes_mysql_rxn.sql', true);
110     //
111     // Creating the structure for table and applying indexes
112     //
114     $file_array = explode(";", $file_load);
115     foreach ($file_array as $val) {
116         if (trim($val) != '') {
117             sqlStatementNoLog($val);
118         }
119     }
121     $indexes_array = explode(";", $indexes_load);
123     foreach ($indexes_array as $val1) {
124         if (trim($val1) != '') {
125             sqlStatementNoLog($val1);
126         }
127     }
130     // Settings to drastically speed up import with InnoDB
131     sqlStatementNoLog("SET autocommit=0");
132     sqlStatementNoLog("START TRANSACTION");
133     $data = explode(";", $data_load);
134     foreach ($data as $val) {
135         foreach ($rx_info as $key => $value) {
136             $file_name = $value['origin'];
137             $replacement = $dir . "/" . $file_name;
139             $pattern = '/' . $file_name . '/';
140             if (strpos($val, $file_name) !== false) {
141                 $val1 = str_replace($file_name, $replacement, $val);
142                 if (trim($val1) != '') {
143                     sqlStatementNoLog($val1);
144                 }
145             }
146         }
147     }
149     // Settings to drastically speed up import with InnoDB
150     sqlStatementNoLog("COMMIT");
151     sqlStatementNoLog("SET autocommit=1");
153     return true;
156 // Function to import SNOMED tables
157 function snomed_import($us_extension = false)
160     // set up array
161     $table_array_for_snomed = array(
162         "sct_concepts_drop" => "DROP TABLE IF EXISTS `sct_concepts`",
163         "sct_concepts_structure" => "CREATE TABLE IF NOT EXISTS `sct_concepts` (
164             `ConceptId` bigint(20) NOT NULL,
165             `ConceptStatus` int(11) NOT NULL,
166             `FullySpecifiedName` varchar(255) NOT NULL,
167             `CTV3ID` varchar(5) NOT NULL,
168             `SNOMEDID` varchar(8) NOT NULL,
169             `IsPrimitive` tinyint(1) NOT NULL,
170             PRIMARY KEY (`ConceptId`)
171             ) ENGINE=InnoDB",
172         "sct_descriptions_drop" => "DROP TABLE IF EXISTS `sct_descriptions`",
173         "sct_descriptions_structure" => "CREATE TABLE IF NOT EXISTS `sct_descriptions` (
174             `DescriptionId` bigint(20) NOT NULL,
175             `DescriptionStatus` int(11) NOT NULL,
176             `ConceptId` bigint(20) NOT NULL,
177             `Term` varchar(255) NOT NULL,
178             `InitialCapitalStatus` tinyint(1) NOT NULL,
179             `DescriptionType` int(11) NOT NULL,
180             `LanguageCode` varchar(8) NOT NULL,
181             PRIMARY KEY (`DescriptionId`),
182             KEY `idx_concept_id` (`ConceptId`)
183             ) ENGINE=InnoDB",
184         "sct_relationships_drop" => "DROP TABLE IF EXISTS `sct_relationships`",
185         "sct_relationships_structure" => "CREATE TABLE IF NOT EXISTS `sct_relationships` (
186             `RelationshipId` bigint(20) NOT NULL,
187             `ConceptId1` bigint(20) NOT NULL,
188             `RelationshipType` bigint(20) NOT NULL,
189             `ConceptId2` bigint(20) NOT NULL,
190             `CharacteristicType` int(11) NOT NULL,
191             `Refinability` int(11) NOT NULL,
192             `RelationshipGroup` int(11) NOT NULL,
193             PRIMARY KEY (`RelationshipId`)
194             ) ENGINE=InnoDB"
195     );
197     // set up paths
198     $dir_snomed = $GLOBALS['temporary_files_dir'] . "/SNOMED/";
199     $sub_path = "Terminology/Content/";
200     $dir = $dir_snomed;
201     $dir = str_replace('\\', '/', $dir);
203     // executing the create statement for tables, these are defined in snomed_capture.inc file
204     // this is skipped if the US extension is being added
205     if (!$us_extension) {
206         foreach ($table_array_for_snomed as $val) {
207             if (trim($val) != '') {
208                 sqlStatement($val);
209             }
210         }
211     }
213     // reading the SNOMED directory and identifying the files to import and replacing the variables by originals values.
214     if (is_dir($dir) && $handle = opendir($dir)) {
215         while (false !== ($filename = readdir($handle))) {
216             if ($filename != "." && $filename != ".." && !strpos($filename, "zip")) {
217                 $path = $dir . "" . $filename . "/" . $sub_path;
218                 if (!(is_dir($path))) {
219                     $path = $dir . "" . $filename . "/RF1Release/" . $sub_path;
220                 }
222                 if (is_dir($path) && $handle1 = opendir($path)) {
223                     while (false !== ($filename1 = readdir($handle1))) {
224                         $load_script = "Load data local infile '#FILENAME#' into table #TABLE# fields terminated by '\\t' ESCAPED BY '' lines terminated by '\\n' ignore 1 lines   ";
225                         $array_replace = array("#FILENAME#","#TABLE#");
226                         if ($filename1 != "." && $filename1 != "..") {
227                             $file_replace = $path . $filename1;
228                             if (strpos($filename1, "Concepts") !== false) {
229                                 $new_str = str_replace($array_replace, array($file_replace,"sct_concepts"), $load_script);
230                             }
232                             if (strpos($filename1, "Descriptions") !== false) {
233                                 $new_str = str_replace($array_replace, array($file_replace,"sct_descriptions"), $load_script);
234                             }
236                             if (strpos($filename1, "Relationships") !== false) {
237                                 $new_str = str_replace($array_replace, array($file_replace,"sct_relationships"), $load_script);
238                             }
240                             if ($new_str != '') {
241                                 sqlStatement($new_str);
242                             }
243                         }
244                     }
245                 }
247                 closedir($handle1);
248             }
249         }
251         closedir($handle);
252     }
254     return true;
257 function drop_old_sct()
259     $array_to_truncate = array(
260         "sct_concepts_drop" => "DROP TABLE IF EXISTS `sct_concepts`",
261         "sct_descriptions_drop" => "DROP TABLE IF EXISTS `sct_descriptions`",
262         "sct_relationships_drop" => "DROP TABLE IF EXISTS `sct_relationships`"
263     );
264     foreach ($array_to_truncate as $val) {
265         if (trim($val) != '') {
266             sqlStatement($val);
267         }
268     }
271 function drop_old_sct2()
273     $array_to_truncate = array(
274         "sct2_concept_drop" => "DROP TABLE IF EXISTS `sct2_concept`",
275         "sct2_description_drop" => "DROP TABLE IF EXISTS `sct2_description`",
276         "sct2_identifier_drop" => "DROP TABLE IF EXISTS `sct2_identifier`",
277         "sct2_relationship_drop" => "DROP TABLE IF EXISTS `sct2_relationship`",
278         "sct2_statedrelationship_drop" => "DROP TABLE IF EXISTS `sct2_statedrelationship`",
279         "sct2_textdefinition_drop" => "DROP TABLE IF EXISTS `sct2_textdefinition`"
280     );
281     foreach ($array_to_truncate as $val) {
282         if (trim($val) != '') {
283             sqlStatement($val);
284         }
285     }
288 function chg_ct_external_torf1()
290     sqlStatement("UPDATE code_types SET ct_external = 2 WHERE ct_key = 'SNOMED'");
291     sqlStatement("UPDATE code_types SET ct_external = 7 WHERE ct_key = 'SNOMED-CT'");
292     sqlStatement("UPDATE code_types SET ct_external = 9 WHERE ct_key = 'SNOMED-PR'");
295 function chg_ct_external_torf2()
297     sqlStatement("UPDATE code_types SET ct_external = 10 WHERE ct_key = 'SNOMED'");
298     sqlStatement("UPDATE code_types SET ct_external = 11 WHERE ct_key = 'SNOMED-CT'");
299     sqlStatement("UPDATE code_types SET ct_external = 12 WHERE ct_key = 'SNOMED-PR'");
302 function snomedRF2_import()
305     // set up array
306     $table_array_for_snomed = array(
307         "sct2_concept_drop" => "DROP TABLE IF EXISTS `sct2_concept`",
308         "sct2_concept_structure" => "CREATE TABLE IF NOT EXISTS `sct2_concept` (
309             `id` bigint(20) NOT NULL,
310             `effectiveTime` date NOT NULL,
311             `active` int(11) NOT NULL,
312             `moduleId` bigint(20) NOT NULL,
313             `definitionStatusId` bigint(25) NOT NULL,
314              PRIMARY KEY (`id`)
315             ) ENGINE=InnoDB",
316         "sct2_description_drop" => "DROP TABLE IF EXISTS `sct2_description`",
317         "sct2_description_structure" => "CREATE TABLE IF NOT EXISTS `sct2_description` (
318             `id` bigint(20) NOT NULL,
319             `effectiveTime` date NOT NULL,
320             `active` bigint(11) NOT NULL,
321             `moduleId` bigint(25) NOT NULL,
322             `conceptId` bigint(20) NOT NULL,
323             `languageCode` varchar(8) NOT NULL,
324             `typeId` bigint(25) NOT NULL,
325             `term` varchar(255) NOT NULL,
326             `caseSignificanceId` bigint(25) NOT NULL,
327              PRIMARY KEY (`id`, `active`, `conceptId`),
328              KEY `idx_concept_id` (`conceptId`)
329             ) ENGINE=InnoDB",
330         "sct2_identifier_drop" => "DROP TABLE IF EXISTS `sct2_identifier`",
331         "sct2_identifier_structure" => "CREATE TABLE IF NOT EXISTS `sct2_identifier` (
332             `identifierSchemeId` bigint(25) NOT NULL,
333             `alternateIdentifier` bigint(25) NOT NULL,
334             `effectiveTime` date NOT NULL,
335             `active` int(11) NOT NULL,
336             `moduleId` bigint(25) NOT NULL,
337             `referencedComponentId` bigint(25) NOT NULL,
338              PRIMARY KEY (`identifierSchemeId`)
339             ) ENGINE=InnoDB",
340         "sct2_relationship_drop" => "DROP TABLE IF EXISTS `sct2_relationship`",
341         "sct2_relationship_structure" => "CREATE TABLE IF NOT EXISTS `sct2_relationship` (
342             `id` bigint(20) NOT NULL,
343             `effectiveTime` date NOT NULL,
344             `active` int(11) NOT NULL,
345             `moduleId` bigint(25) NOT NULL,
346             `sourceId` bigint(20) NOT NULL,
347             `destinationId` bigint(20) NOT NULL,
348             `typeId` bigint(25) NOT NULL,
349             `characteristicTypeId` bigint(25) NOT NULL,
350             `modifierId` bigint(25) NOT NULL,
351              PRIMARY KEY (`id`)
352             ) ENGINE=InnoDB",
353         "sct2_statedrelationship_drop" => "DROP TABLE IF EXISTS `sct2_statedrelationship`",
354         "sct2_statedrelationship_structure" => "CREATE TABLE IF NOT EXISTS `sct2_statedrelationship` (
355             `id` bigint(20) NOT NULL,
356             `effectiveTime` date NOT NULL,
357             `active` int(11) NOT NULL,
358             `moduleId` bigint(25) NOT NULL,
359             `sourceId` bigint(20) NOT NULL,
360             `destinationId` bigint(20) NOT NULL,
361             `relationshipGroup` int(11) NOT NULL,
362             `typeId` bigint(25) NOT NULL,
363              PRIMARY KEY (`id`)
364             ) ENGINE=InnoDB",
365         "sct2_textdefinition_drop" => "DROP TABLE IF EXISTS `sct2_textdefinition`",
366         "sct2_textdefinition_structure" => "CREATE TABLE IF NOT EXISTS `sct2_textdefinition` (
367             `id` bigint(20) NOT NULL,
368             `effectiveTime` date NOT NULL,
369             `active` int(11) NOT NULL,
370             `moduleId` bigint(25) NOT NULL,
371             `conceptId` bigint(20) NOT NULL,
372             `languageCode` varchar(8) NOT NULL,
373             `typeId` bigint(25) NOT NULL,
374             `term` varchar(655) NOT NULL,
375              PRIMARY KEY (`id`)
376             ) ENGINE=InnoDB"
377     );
379     // set up paths
380     $dir_snomed = $GLOBALS['temporary_files_dir'] . "/SNOMED/";
381     // $sub_path="Terminology/Content/";
382     $sub_path = "Full/Terminology/";
383     $dir = $dir_snomed;
384     $dir = str_replace('\\', '/', $dir);
386     // executing the create statement for tables, these are defined in snomed_capture.inc file
387     // this is skipped if the US extension is being added
388     //if (!$us_extension) {
389         //var_dump($us_extension);
390     foreach ($table_array_for_snomed as $val) {
391         if (trim($val) != '') {
392             sqlStatement($val);
393         }
394     }
395     //}
397     // reading the SNOMED directory and identifying the files to import and replacing the variables by originals values.
398     if (is_dir($dir) && $handle = opendir($dir)) {
399         while (false !== ($filename = readdir($handle))) {
400             if ($filename != "." && $filename != ".." && !strpos($filename, "zip")) {
401                 $path = $dir . "" . $filename . "/" . $sub_path;
402                 if (!(is_dir($path))) {
403                     $path = $dir . "" . $filename . "/RF2Release/" . $sub_path;
404                 }
405                 if (is_dir($path) && $handle1 = opendir($path)) {
406                     while (false !== ($filename1 = readdir($handle1))) {
407                         $load_script = "Load data local infile '#FILENAME#' into table #TABLE# fields terminated by '\\t' ESCAPED BY '' lines terminated by '\\n' ignore 1 lines   ";
408                         $array_replace = array("#FILENAME#","#TABLE#");
409                         if ($filename1 != "." && $filename1 != "..") {
410                             $file_replace = $path . $filename1;
411                             if (strpos($filename1, "Concept") !== false) {
412                                 $new_str = str_replace($array_replace, array($file_replace,"sct2_concept"), $load_script);
413                             }
414                             if (strpos($filename1, "Description") !== false) {
415                                 $new_str = str_replace($array_replace, array($file_replace,"sct2_description"), $load_script);
416                             }
417                             if (strpos($filename1, "Identifier") !== false) {
418                                 $new_str = str_replace($array_replace, array($file_replace,"sct2_identifier"), $load_script);
419                             }
420                             if (strpos($filename1, "Relationship") !== false) {
421                                 $new_str = str_replace($array_replace, array($file_replace,"sct2_relationship"), $load_script);
422                             }
423                             if (strpos($filename1, "StatedRelationship") !== false) {
424                                 $new_str = str_replace($array_replace, array($file_replace,"sct2_statedrelationship"), $load_script);
425                             }
426                             if (strpos($filename1, "TextDefinition") !== false) {
427                                 $new_str = str_replace($array_replace, array($file_replace,"sct2_textdefinition"), $load_script);
428                             }
429                             if ($new_str != '') {
430                                 sqlStatement($new_str);
431                             }
432                         }
433                     }
434                 }
435                 closedir($handle1);
436             }
437         }
438         closedir($handle);
439     }
440     return true;
443 // Function to import ICD tables $type differentiates ICD 9, 10 and eventually 11 (circa 2018 :-) etc.
445 function icd_import($type)
447     // set up paths
448     $dir_icd = $GLOBALS['temporary_files_dir'] . "/" . $type . "/";
449     $dir = str_replace('\\', '/', $dir_icd);
450     $db_load = '';
451     $db_update = '';
453     // the incoming array is a metadata array containing keys that substr match to the incoming filename
454     // followed by the field name, position and length of each fixed length text record in the incoming
455     // flat files. There are separate definitions for ICD 9 and 10 based on the type passed in
456     $incoming = array();
457     if ($type == 'ICD9') {
458         $incoming['SHORT_DX'] = array('#TABLENAME#' => "icd9_dx_code",
459         '#FLD1#' => "dx_code", '#POS1#' => 1, '#LEN1#' => 5,
460         '#FLD2#' => "short_desc", '#POS2#' => 7, '#LEN2#' => 60);
461         $incoming['SHORT_SG'] = array('#TABLENAME#' => "icd9_sg_code",
462         '#FLD1#' => "sg_code", '#POS1#' => 1, '#LEN1#' => 4,
463         '#FLD2#' => "short_desc", '#POS2#' => 6, '#LEN2#' => 60);
464         $incoming['LONG_SG'] = array('#TABLENAME#' => "icd9_sg_long_code",
465         '#FLD1#' => "sg_code", '#POS1#' => 1, '#LEN1#' => 4,
466         '#FLD2#' => "long_desc", '#POS2#' => 6, '#LEN2#' => 300);
467         $incoming['LONG_DX'] = array('#TABLENAME#' => "icd9_dx_long_code",
468         '#FLD1#' => "dx_code", '#POS1#' => 1, '#LEN1#' => 5,
469         '#FLD2#' => "long_desc", '#POS2#' => 7, '#LEN2#' => 300);
470     } else {
471         $incoming['icd10pcs_order_'] = array('#TABLENAME#' => "icd10_pcs_order_code",
472         '#FLD1#' => "pcs_code", '#POS1#' => 7, '#LEN1#' => 7,
473         '#FLD2#' => "valid_for_coding", '#POS2#' => 15, '#LEN2#' => 1,
474         '#FLD3#' => "short_desc", '#POS3#' => 17, '#LEN3#' => 60,
475         '#FLD4#' => "long_desc", '#POS4#' => 78, '#LEN4#' => 300);
476         $incoming['icd10cm_order_'] = array('#TABLENAME#' => "icd10_dx_order_code",
477         '#FLD1#' => "dx_code", '#POS1#' => 7, '#LEN1#' => 7,
478         '#FLD2#' => "valid_for_coding", '#POS2#' => 15, '#LEN2#' => 1,
479         '#FLD3#' => "short_desc", '#POS3#' => 17, '#LEN3#' => 60,
480         '#FLD4#' => "long_desc", '#POS4#' => 78, '#LEN4#' => 300);
481         $incoming['reimb_map_pr_'] = array('#TABLENAME#' => "icd10_reimbr_pcs_9_10",
482         '#FLD1#' => "code", '#POS1#' => 1, '#LEN1#' => 7,
483         '#FLD2#' => "code_cnt", '#POS2#' => 9, '#LEN2#' => 1,
484         '#FLD3#' => "ICD9_01", '#POS3#' => 11, '#LEN3#' => 5,
485         '#FLD4#' => "ICD9_02", '#POS4#' => 17, '#LEN4#' => 5,
486         '#FLD5#' => "ICD9_03", '#POS5#' => 23, '#LEN5#' => 5,
487         '#FLD6#' => "ICD9_04", '#POS6#' => 29, '#LEN6#' => 5,
488         '#FLD7#' => "ICD9_05", '#POS7#' => 35, '#LEN7#' => 5,
489         '#FLD8#' => "ICD9_06", '#POS8#' => 41, '#LEN8#' => 5);
490         $incoming['reimb_map_dx_'] = array('#TABLENAME#' => "icd10_reimbr_dx_9_10",
491         '#FLD1#' => "code", '#POS1#' => 1, '#LEN1#' => 7,
492         '#FLD2#' => "code_cnt", '#POS2#' => 9, '#LEN2#' => 1,
493         '#FLD3#' => "ICD9_01", '#POS3#' => 11, '#LEN3#' => 5,
494         '#FLD4#' => "ICD9_02", '#POS4#' => 17, '#LEN4#' => 5,
495         '#FLD5#' => "ICD9_03", '#POS5#' => 23, '#LEN5#' => 5,
496         '#FLD6#' => "ICD9_04", '#POS6#' => 29, '#LEN6#' => 5,
497         '#FLD7#' => "ICD9_05", '#POS7#' => 35, '#LEN7#' => 5,
498         '#FLD8#' => "ICD9_06", '#POS8#' => 41, '#LEN8#' => 5);
499         $incoming['I10gem'] = array('#TABLENAME#' => "icd10_gem_dx_10_9",
500         '#FLD1#' => "dx_icd10_source", '#POS1#' => 1, '#LEN1#' => 7,
501         '#FLD2#' => "dx_icd9_target", '#POS2#' => 9, '#LEN2#' => 5,
502         '#FLD3#' => "flags", '#POS3#' => 15, '#LEN3#' => 5);
503         $incoming['I9gem'] = array('#TABLENAME#' => "icd10_gem_dx_9_10",
504         '#FLD1#' => "dx_icd9_source", '#POS1#' => 1, '#LEN1#' => 5,
505         '#FLD2#' => "dx_icd10_target", '#POS2#' => 7, '#LEN2#' => 7,
506         '#FLD3#' => "flags", '#POS3#' => 15, '#LEN3#' => 5);
507         $incoming['gem_pcsi9'] = array('#TABLENAME#' => "icd10_gem_pcs_10_9",
508         '#FLD1#' => "pcs_icd10_source", '#POS1#' => 1, '#LEN1#' => 7,
509         '#FLD2#' => "pcs_icd9_target", '#POS2#' => 9, '#LEN2#' => 5,
510         '#FLD3#' => "flags", '#POS3#' => 15, '#LEN3#' => 5);
511         $incoming['gem_i9pcs'] = array('#TABLENAME#' => "icd10_gem_pcs_9_10",
512         '#FLD1#' => "pcs_icd9_source", '#POS1#' => 1, '#LEN1#' => 5,
513         '#FLD2#' => "pcs_icd10_target", '#POS2#' => 7, '#LEN2#' => 7,
514         '#FLD3#' => "flags", '#POS3#' => 15, '#LEN3#' => 5);
515     }
517     // set up the start of the load script to be appended from the incoming array defined above where incoming
518     // file matches
519     $db_load = "LOAD DATA LOCAL INFILE '#INFILE#' INTO TABLE #TABLENAME# FIELDS TERMINATED BY '\0' (@var) SET revision = 0, ";
520     $col_template = "#FLD# = trim(Substring(@var, #POS#, #LEN#))";
522     // load all data and set active revision
523     if (is_dir($dir) && $handle = opendir($dir)) {
524         while (false !== ($filename = readdir($handle))) {
525         // bypass unwanted entries
526             if (!stripos($filename, ".txt") || stripos($filename, "diff") || stripos($filename, "addenda")) {
527                 continue;
528             }
530         // reset the sql load command and susbtitute the filename
531             $run_sql = $db_load;
532             $run_sql = str_replace("#INFILE#", $dir . $filename, $run_sql);
533             $keys = array_keys($incoming);
534             while ($this_key = array_pop($keys)) {
535                 if (stripos($filename, $this_key) !== false) {
536                     // now substitute the tablename
537                         $run_sql = str_replace("#TABLENAME#", $incoming[$this_key]['#TABLENAME#'], $run_sql);
539                     // the range defines the maximum number of fields contained
540                     // in any of the incoming files
541                     foreach (range(1, 8) as $field) {
542                         $fld = "#FLD" . $field . "#";
543                         $nxtfld = "#FLD" . ($field + 1) . "#";
544                         $pos = "#POS" . $field . "#";
545                         $len = "#LEN" . $field . "#";
547                 // concat this fields template in the sql string
548                         $run_sql .= $col_template;
549                         $run_sql = str_replace("#FLD#", $incoming[$this_key][$fld], $run_sql);
550                         $run_sql = str_replace("#POS#", $incoming[$this_key][$pos], $run_sql);
551                         $run_sql = str_replace("#LEN#", $incoming[$this_key][$len], $run_sql);
552                 // at the end of this table's field list
553                         if (!array_key_exists($nxtfld, $incoming[$this_key])) {
554                             break;
555                         }
557                         $run_sql .= ",";
558                     }
560                     sqlStatement($run_sql);
562                     // now update the revision for this load
563                     $res = sqlStatement("SELECT max(revision) rev FROM " . escape_table_name($incoming[$this_key]['#TABLENAME#']));
564                     $row = sqlFetchArray($res);
565                     $next_rev = $row['rev'] + 1;
566                     $run_sql = "UPDATE " . $incoming[$this_key]['#TABLENAME#'] . " SET active = 0";
567                     sqlQuery($run_sql);
568                     $run_sql = "UPDATE " . $incoming[$this_key]['#TABLENAME#'] . " SET active = 1, revision = ? WHERE revision = 0";
569                     sqlQuery($run_sql, array($next_rev));
570                     break;
571                 }
572             }
573         }
575         closedir($handle);
576     } else {
577         echo htmlspecialchars(xl('ERROR: No ICD import directory.'), ENT_NOQUOTES) . "<br />";
578         return;
579     }
581     // now update the tables where necessary
582     if ($type == 'ICD9') {
583         sqlStatement("update `icd9_dx_code` SET formatted_dx_code = dx_code");
584         sqlStatement("update `icd9_dx_code` SET formatted_dx_code = concat(concat(left(dx_code, 3), '.'), substr(dx_code, 4)) WHERE dx_code RLIKE '^[V0-9]{1}.*' AND LENGTH(dx_code) > 3");
585         sqlStatement("update `icd9_dx_code` SET formatted_dx_code = concat(concat(left(dx_code, 4), '.'), substr(dx_code, 5)) WHERE dx_code RLIKE '^[E]{1}.*' AND LENGTH(dx_code) > 4");
586         sqlStatement("update `icd9_sg_code` SET formatted_sg_code = concat(concat(left(sg_code, 2), '.'), substr(sg_code, 3))");
587         sqlStatement("update `icd9_dx_code` A, `icd9_dx_long_code` B set A.long_desc = B.long_desc where A.dx_code = B.dx_code and A.active = 1 and A.long_desc is NULL");
588         sqlStatement("update `icd9_sg_code` A, `icd9_sg_long_code` B set A.long_desc = B.long_desc where A.sg_code = B.sg_code and A.active = 1 and A.long_desc is NULL");
589     } else { // ICD 10
590         sqlStatement("update `icd10_dx_order_code` SET formatted_dx_code = dx_code");
591         sqlStatement("update `icd10_dx_order_code` SET formatted_dx_code = concat(concat(left(dx_code, 3), '.'), substr(dx_code, 4)) WHERE LENGTH(dx_code) > 3");
592     }
594     return true;
597 function valueset_import($type)
599     $dir_valueset = $GLOBALS['temporary_files_dir'] . "/" . $type . "/";
600         $dir = str_replace('\\', '/', $dir_valueset);
602     // Settings to drastically speed up import with InnoDB
603     sqlStatementNoLog("SET autocommit=0");
604     sqlStatementNoLog("START TRANSACTION");
605     if (is_dir($dir) && $handle = opendir($dir)) {
606         while (false !== ($filename = readdir($handle))) {
607             if (stripos($filename, ".xml")) {
608                     $abs_path = $dir . $filename;
609                     $xml  = simplexml_load_file($abs_path, null, null, 'ns0', true);
610                 foreach ($xml->DescribedValueSet as $vset) {
611                     $vset_attr = $vset->attributes();
612                     $nqf = $vset->xpath('ns0:Group[@displayName="NQF Number"]/ns0:Keyword');
613                     foreach ($vset->ConceptList as $cp) {
614                         foreach ($nqf as $nqf_code) {
615                             foreach ($cp->Concept as $con) {
616                                 $con_attr = $con->attributes();
617                                 sqlStatementNoLog("INSERT INTO valueset values(?,?,?,?,?,?,?) on DUPLICATE KEY UPDATE code_system = values(code_system),description = values(description),valueset_name = values(valueset_name)", array($nqf_code,$con_attr->code,$con_attr->codeSystem,$con_attr->codeSystemName,$vset_attr->ID,$con_attr->displayName,$vset_attr->displayName));
618                             }
619                         }
620                     }
621                 }
623                     sqlStatementNoLog("UPDATE valueset set code_type='SNOMED CT' where code_type='SNOMEDCT'");
624                     sqlStatementNoLog("UPDATE valueset set code_type='ICD9' where code_type='ICD9CM'");
625                     sqlStatementNoLog("UPDATE valueset set code_type='ICD10' where code_type='ICD10CM'");
626             }
627         }
628     }
630     // Settings to drastically speed up import with InnoDB
631     sqlStatementNoLog("COMMIT");
632     sqlStatementNoLog("SET autocommit=1");
633         return true;
636 // Function to clean up temp files
637 // $type (RXNORM etc.)
638 function temp_dir_cleanup($type)
640     if (is_dir($GLOBALS['temporary_files_dir'] . "/" . $type)) {
641         rmdir_recursive($GLOBALS['temporary_files_dir'] . "/" . $type);
642     }
645 // Function to update version tracker table if successful
646 // $type (RXNORM etc.)
647 function update_tracker_table($type, $revision, $version, $file_checksum)
649     if ($type == 'RXNORM') {
650         sqlStatement("INSERT INTO `standardized_tables_track` (`imported_date`,`name`,`revision_date`, `revision_version`, `file_checksum`) VALUES (NOW(),'RXNORM',?,?,?)", array($revision, $version, $file_checksum));
651         return true;
652     } elseif ($type == 'SNOMED') {
653         sqlStatement("INSERT INTO `standardized_tables_track` (`imported_date`,`name`,`revision_date`, `revision_version`, `file_checksum`) VALUES (NOW(),'SNOMED',?,?,?)", array($revision, $version, $file_checksum));
654         return true;
655     } elseif ($type == 'ICD9') {
656         sqlStatement("INSERT INTO `standardized_tables_track` (`imported_date`,`name`,`revision_date`, `revision_version`, `file_checksum`) VALUES (NOW(),'ICD9',?,?,?)", array($revision, $version, $file_checksum));
657         return true;
658     } elseif ($type == 'CQM_VALUESET') {
659         sqlStatement("INSERT INTO `standardized_tables_track` (`imported_date`,`name`,`revision_date`, `revision_version`, `file_checksum`) VALUES (NOW(),'CQM_VALUESET',?,?,?)", array($revision, $version, $file_checksum));
660         return true;
661     } else { // $type == 'ICD10')
662         sqlStatement("INSERT INTO `standardized_tables_track` (`imported_date`,`name`,`revision_date`, `revision_version`, `file_checksum`) VALUES (NOW(),'ICD10',?,?,?)", array($revision, $version, $file_checksum));
663         return true;
664     }
666     return false;
669 // Function to delete an entire directory
670 function rmdir_recursive($dir)
672     $files = scandir($dir);
673     array_shift($files);    // remove '.' from array
674     array_shift($files);    // remove '..' from array
676     foreach ($files as $file) {
677         $file = $dir . '/' . $file;
678         if (is_dir($file)) {
679             rmdir_recursive($file);
680             continue;
681         }
683         unlink($file);
684     }
686     rmdir($dir);
689 // function to cleanup temp, copy and unarchive the zip file
690 function handle_zip_file($mode, $file)
692         // 1. copy the file to temp directory
693     if (!temp_copy($file, $mode)) {
694         echo htmlspecialchars(xl('ERROR: Unable to copy the file.'), ENT_NOQUOTES) . "<br />";
695         temp_dir_cleanup($mode);
696         exit;
697     }
698         // 2. unarchive the file
699     if (!temp_unarchive($file, $mode)) {
700         echo htmlspecialchars(xl('ERROR: Unable to extract the file.'), ENT_NOQUOTES) . "<br />";
701         temp_dir_cleanup($mode);
702         exit;
703     }