/** * Poll all eligible labs for new results and store them in the database. * * @param array &$info Conveys information to and from the caller: * FROM THE CALLER: * $info["$ppid/$filename"]['delete'] = a non-empty value if file deletion is requested. * $info['select'] = array of patient matching responses where key is serialized patient * attributes and value is selected pid for this patient, or 0 to create the patient. * TO THE CALLER: * $info["$ppid/$filename"]['mssgs'] = array of messages from this function. * $info['match'] = array of patient matching requests where key is serialized patient * attributes (ss, fname, lname, DOB) and value is TRUE (irrelevant). * * @return string Error text, or empty if no errors. */ function poll_hl7_results(&$info) { global $srcdir; // echo "<!-- post: "; print_r($_POST); echo " -->\n"; // debugging // echo "<!-- in: "; print_r($info); echo " -->\n"; // debugging $filecount = 0; $badcount = 0; if (!isset($info['match'])) { $info['match'] = array(); } // match requests if (!isset($info['select'])) { $info['select'] = array(); } // match request responses $ppres = sqlStatement("SELECT * FROM procedure_providers ORDER BY name"); while ($pprow = sqlFetchArray($ppres)) { $ppid = $pprow['ppid']; $protocol = $pprow['protocol']; $remote_host = $pprow['remote_host']; $hl7 = ''; if ($protocol == 'SFTP') { $remote_port = 22; // Hostname may have ":port" appended to specify a nonstandard port number. if ($i = strrpos($remote_host, ':')) { $remote_port = 0 + substr($remote_host, $i + 1); $remote_host = substr($remote_host, 0, $i); } ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . "{$srcdir}/phpseclib"); require_once "{$srcdir}/phpseclib/Net/SFTP.php"; // Compute the target path name. $pathname = '.'; if ($pprow['results_path']) { $pathname = $pprow['results_path'] . '/' . $pathname; } // Connect to the server and enumerate files to process. $sftp = new Net_SFTP($remote_host, $remote_port); if (!$sftp->login($pprow['login'], $pprow['password'])) { return xl('Login to remote host') . " '{$remote_host}' " . xl('failed'); } $files = $sftp->nlist($pathname); foreach ($files as $file) { if (substr($file, 0, 1) == '.') { continue; } ++$filecount; if (!isset($info["{$ppid}/{$file}"])) { $info["{$ppid}/{$file}"] = array(); } // Ensure that archive directory exists. $prpath = $GLOBALS['OE_SITE_DIR'] . "/procedure_results"; if (!file_exists($prpath)) { mkdir($prpath); } $prpath .= '/' . $pprow['ppid']; if (!file_exists($prpath)) { mkdir($prpath); } // Get file contents. $hl7 = $sftp->get("{$pathname}/{$file}"); // If user requested reject and delete, do that. if (!empty($info["{$ppid}/{$file}"]['delete'])) { $fh = fopen("{$prpath}/{$file}.rejected", 'w'); if ($fh) { fwrite($fh, $hl7); fclose($fh); } else { return xl('Cannot create file') . ' "' . "{$prpath}/{$file}.rejected" . '"'; } if (!$sftp->delete("{$pathname}/{$file}")) { return xl('Cannot delete (from SFTP server) file') . ' "' . "{$pathname}/{$file}" . '"'; } continue; } // Do a dry run of its contents and check for errors and match requests. $tmp = receive_hl7_results($hl7, $info['match'], $ppid, $pprow['direction'], true, $info['select']); $info["{$ppid}/{$file}"]['mssgs'] = $tmp['mssgs']; // $info["$ppid/$file"]['match'] = $tmp['match']; if (!empty($tmp['fatal']) || !empty($tmp['needmatch'])) { // There are errors or matching requests so skip this file. continue; } // Now the money shot - not a dry run. $tmp = receive_hl7_results($hl7, $info['match'], $ppid, $pprow['direction'], false, $info['select']); $info["{$ppid}/{$file}"]['mssgs'] = $tmp['mssgs']; // $info["$ppid/$file"]['match'] = $tmp['match']; if (empty($tmp['fatal']) && empty($tmp['needmatch'])) { // It worked, archive and delete the file. $fh = fopen("{$prpath}/{$file}", 'w'); if ($fh) { fwrite($fh, $hl7); fclose($fh); } else { return xl('Cannot create file') . ' "' . "{$prpath}/{$file}" . '"'; } if (!$sftp->delete("{$pathname}/{$file}")) { return xl('Cannot delete (from SFTP server) file') . ' "' . "{$pathname}/{$file}" . '"'; } } } // end of this file } else { if ($protocol == 'FS') { // Filesystem directory containing results files. $pathname = $pprow['results_path']; if (!($dh = opendir($pathname))) { return xl('Unable to access directory') . " '{$pathname}'"; } // Sort by filename just because. $files = array(); while (false !== ($file = readdir($dh))) { if (substr($file, 0, 1) == '.') { continue; } $files[$file] = $file; } closedir($dh); ksort($files); // For each file... foreach ($files as $file) { ++$filecount; if (!isset($info["{$ppid}/{$file}"])) { $info["{$ppid}/{$file}"] = array(); } // Ensure that archive directory exists. $prpath = $GLOBALS['OE_SITE_DIR'] . "/procedure_results"; if (!file_exists($prpath)) { mkdir($prpath); } $prpath .= '/' . $pprow['ppid']; if (!file_exists($prpath)) { mkdir($prpath); } // Get file contents. $hl7 = file_get_contents("{$pathname}/{$file}"); // If user requested reject and delete, do that. if (!empty($info["{$ppid}/{$file}"]['delete'])) { $fh = fopen("{$prpath}/{$file}.rejected", 'w'); if ($fh) { fwrite($fh, $hl7); fclose($fh); } else { return xl('Cannot create file') . ' "' . "{$prpath}/{$file}.rejected" . '"'; } if (!unlink("{$pathname}/{$file}")) { return xl('Cannot delete file') . ' "' . "{$pathname}/{$file}" . '"'; } continue; } // Do a dry run of its contents and check for errors and match requests. $tmp = receive_hl7_results($hl7, $info['match'], $ppid, $pprow['direction'], true, $info['select']); $info["{$ppid}/{$file}"]['mssgs'] = $tmp['mssgs']; // $info["$ppid/$file"]['match'] = $tmp['match']; if (!empty($tmp['fatal']) || !empty($tmp['needmatch'])) { // There are errors or matching requests so skip this file. continue; } // Now the money shot - not a dry run. $tmp = receive_hl7_results($hl7, $info['match'], $ppid, $pprow['direction'], false, $info['select']); $info["{$ppid}/{$file}"]['mssgs'] = $tmp['mssgs']; // $info["$ppid/$file"]['match'] = $tmp['match']; if (empty($tmp['fatal']) && empty($tmp['needmatch'])) { // It worked, archive and delete the file. $fh = fopen("{$prpath}/{$file}", 'w'); if ($fh) { fwrite($fh, $hl7); fclose($fh); } else { return xl('Cannot create file') . ' "' . "{$prpath}/{$file}" . '"'; } if (!unlink("{$pathname}/{$file}")) { return xl('Cannot delete file') . ' "' . "{$pathname}/{$file}" . '"'; } } } // end of this file } } // end FS protocol // TBD: Insert "else if ($protocol == '???') {...}" to support other protocols. } // end procedure provider // echo "<!-- out: "; print_r($info); echo " -->\n"; // debugging return ''; }
/** * Poll all eligible labs for new results and store them in the database. * * @param array &$messages Receives messages of interest. * @return string Error text, or empty if no errors. */ function poll_hl7_results(&$messages) { global $srcdir; $messages = array(); $filecount = 0; $badcount = 0; $ppres = sqlStatement("SELECT * FROM procedure_providers ORDER BY name"); while ($pprow = sqlFetchArray($ppres)) { $protocol = $pprow['protocol']; $remote_host = $pprow['remote_host']; $hl7 = ''; if ($protocol == 'SFTP') { ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . "{$srcdir}/phpseclib"); require_once "{$srcdir}/phpseclib/Net/SFTP.php"; // Compute the target path name. $pathname = '.'; if ($pprow['results_path']) { $pathname = $pprow['results_path'] . '/' . $pathname; } // Connect to the server and enumerate files to process. $sftp = new Net_SFTP($remote_host); if (!$sftp->login($pprow['login'], $pprow['password'])) { return xl('Login to remote host') . " '{$remote_host}' " . xl('failed'); } $files = $sftp->nlist($pathname); foreach ($files as $file) { if (substr($file, 0, 1) == '.') { continue; } ++$filecount; $hl7 = $sftp->get("{$pathname}/{$file}"); // Archive the results file. $prpath = $GLOBALS['OE_SITE_DIR'] . "/procedure_results"; if (!file_exists($prpath)) { mkdir($prpath); } $prpath .= '/' . $pprow['ppid']; if (!file_exists($prpath)) { mkdir($prpath); } $fh = fopen("{$prpath}/{$file}", 'w'); if ($fh) { fwrite($fh, $hl7); fclose($fh); } else { $messages[] = xl('File') . " '{$file}' " . xl('cannot be archived, ignored'); ++$badcount; continue; } // Now delete it from its ftp directory. if (!$sftp->delete("{$pathname}/{$file}")) { $messages[] = xl('File') . " '{$file}' " . xl('cannot be deleted, ignored'); ++$badcount; continue; } // Parse and process its contents. $msg = receive_hl7_results($hl7); if ($msg) { $messages[] = xl('Error processing file') . " '{$file}':" . $msg; ++$badcount; continue; } $messages[] = xl('New file') . " '{$file}' " . xl('processed successfully'); } } // TBD: Insert "else if ($protocol == '???') {...}" to support other protocols. } if ($badcount) { return "{$badcount} " . xl('error(s) encountered from new results'); } return ''; }
echo "<font color='red'>" . text($errmsg) . "</font><br />\n"; } $messages = array(); $errmsg = poll_hl7_results($messages); foreach ($messages as $message) { echo text($message) . "<br />\n"; } if ($errmsg) { echo "<font color='red'>" . text($errmsg) . "</font><br />\n"; } // Process uploaded file if there is one. if (!empty($_FILES['userfile']['name'])) { // if upload was attempted if (is_uploaded_file($_FILES['userfile']['tmp_name'])) { $hl7 = file_get_contents($_FILES['userfile']['tmp_name']); $msg = receive_hl7_results($hl7); $message = xl('Upload processed successfully'); if ($msg) { $message = xl('Error processing upload') . ": " . $msg; } echo text($message) . "<br />\n"; } else { echo "<font color='red'>" . xlt('Upload failed!') . "</font><br />\n"; } } $form_from_date = empty($_POST['form_from_date']) ? '' : trim($_POST['form_from_date']); $form_to_date = empty($_POST['form_to_date']) ? '' : trim($_POST['form_to_date']); // if (empty($form_to_date)) $form_to_date = $form_from_date; $form_reviewed = empty($_POST['form_reviewed']) ? 3 : intval($_POST['form_reviewed']); $form_patient = !empty($_POST['form_patient']); $form_provider = empty($_POST['form_provider']) ? 0 : intval($_POST['form_provider']);