/** * copy the substring of text containing claim payment information for a claim * * The filename must be found in the files.csv table, i.e. previously processed * * @uses csv_verify_file() * @uses csv_x12_delimiters() * @param string $clp_clm_num the pid-encounter value * @param string $era_file the filename * @return string newline characters are added to each segment end */ function ibr_era_get_clp_text($clp_clm_num, $era_file, $html_out = true) { // @param string $clp_clm_num -- CLP01 value, pid-encounter // @param string $era_file path to 835 file containing the $clp_clm_num // segment block CLP to CLP, SE, LX // get the substring of the era file containing the ST number // $fp = csv_verify_file($era_file, "era"); if (!$fp) { csv_edihist_log("ibr_era_get_clp_text: failed to read {$era_file}"); $str_clp .= "failed to read {$era_file}"; return $str_clp; } else { // $bstr = file_get_contents($fp); if (!$bstr) { csv_edihist_log("ibr_era_get_clp_text: failed to get contents of {$era_file}"); $str_clp .= "failed to read {$era_file}"; return $str_clp; } // get the delimiters $str_isa = substr($bstr, 0, 126); // $ar_delim = csv_x12_delimiters($str_isa, "GS"); $seg_delim = $ar_delim['t']; // $seg_clp = "CLP*" . $clp_clm_num; // CLP segment that begins remittance detail // $clp_pos = strpos($bstr, $seg_clp, 0); // break it off if $st_pos is not found if ($clp_pos == FALSE) { csv_edihist_log("Error: {$clp_clm_num} not found in {$era_file}"); $str_clp .= "Error: {$clp_clm_num} not found in {$era_file}"; return $str_clp; } // $seg_se = "SE*"; $seg_lx = "LX*"; $seg_clpx = "CLP*"; // see if we can find a closing segment $pos_ar[] = strpos($bstr, $seg_se, $clp_pos); // $se_pos = $pos_ar[] = strpos($bstr, $seg_lx, $clp_pos); // $lx_pos = $pos_ar[] = strpos($bstr, $seg_clpx, $clp_pos + 10); //$clpx_pos = // // choose the best closing position, closest to $clp_pos asort($pos_ar); foreach ($pos_ar as $p) { // echo "clp_pos $clp_pos pos_ar $p". PHP_EOL; if ($p > $clp_pos) { $end_pos = $p; break; } } // $str_clp = substr($bstr, $clp_pos, $end_pos - $clp_pos); // // add newlines so each segment is on its own line if (strpos($str_clp, $seg_delim . PHP_EOL)) { // if true, assume the file has newlines ending segments } else { // we could get fancy and make an html table or add line numbers $str_clp = str_replace($seg_delim, $seg_delim . PHP_EOL, $str_clp); } } // if ($html_out) { $str_html = "<div class=\"filetext\">"; $str_html .= "<p>{$pe} " . basename($fp) . " </p>" . PHP_EOL . "<pre><code>"; $str_html .= $str_clp; $str_html .= PHP_EOL . "</code></pre>" . PHP_EOL . "</div>" . PHP_EOL; return $str_html; } else { return $str_clp; } }
/** * Parse x12 file into array of segments. * * This function relies on csv_x12_delimiters() to get the delimiters array * and on csv_verify_file() to supply the next_segment value. * There are some basic verifications and failures are noted in the log. * <pre> * 'path'=>pathtofile * 'delimiters'=>array from x12_delimiters() * 'segments'=>segments[i]=>segment text * if $seg_array is true then segments[i]=>array of elements * </pre> * * @uses csv_x12_delimiters() * @uses csv_verify_file() * @param string $file_path the full path for the file * @param string $type one of batch|837|era|835|997|999|277|271 * @param bool $seg_array whether each segment should be made into an array of elements * @return array|bool array['delimiters']['segments']['path'], or false on error */ function csv_x12_segments($file_path, $type, $seg_array = FALSE) { // do verifications $fp_ar = csv_verify_file($file_path, $type, TRUE); // if (!$fp_ar || !$fp_ar[0]) { csv_edihist_log("csv_x12_segments: verification failed for {$file_path}"); return FALSE; } // if ($fp_ar) { // $fp = $fp_ar[0]; $next_segment = $fp_ar[1]; $f_str = file_get_contents($fp); // // verify $delimiters $delimiters = csv_x12_delimiters(substr($f_str, 0, 126), $next_segment); $dlm_ok = FALSE; // here, expect $delimiters['t'] ['e'] ['s'] ['r'] if (is_array($delimiters) && array_keys($delimiters) == array('t', 'e', 's', 'r')) { $dlm_ok = TRUE; $seg_d = $delimiters['t']; $elem_d = $delimiters['e']; $subelem_d = $delimiters['s']; $rep_d = $delimiters['r']; } else { csv_edihist_log("csv_x12_segments: invalid delimiters or delimiters wrong for {$fp}"); return FALSE; } } // OK, now initialize variables $fn = basename($fp); $ar_seg = array(); $ar_seg['path'] = $fp; $ar_seg['delimiters'] = $delimiters; $ar_seg['segments'] = array(); $seg_pos = 0; // position where segment begins $st_segs_ct = 0; // segments in ST-SE envelope $se_seg_ct = ""; // segment count from SE segment $isa_segs_ct = 0; // segments in ISA envelope $isa_ct = 0; // ISA envelope count $iea_ct = 0; // IEA count $trnset_seg_ct = 0; // segments by sum of isa segment count // $isa_str = "ISA" . $elem_d; // to reduce evaluations $iea_str = "IEA" . $elem_d; $st_str = "ST" . $elem_d; $se_str = "SE" . $elem_d; // $idx = -1; $moresegs = true; while ($moresegs) { $idx++; // extract each segment from the file text $seg_end = strpos($f_str, $seg_d, $seg_pos); $moresegs = strpos($f_str, $seg_d, $seg_end + 1); // $seg_text = substr($f_str, $seg_pos, $seg_end - $seg_pos); $seg_pos = $seg_end + 1; // // we trim in case there are line or carriage returns $seg_text = trim($seg_text); // // check for non ASCII basic characters. Note reg_ex '/[^\x20-\xFF]/' allows extended ASCII characters // this is partly file syntax and partly protection -- we don't want to process an imposter // We are mostly concerned with \x00 to \x19, the "control" characters, but apparently some are allowed // if (preg_match_all('/[^\\x20-\\x7E]/', $seg_text, $matches)) { csv_edihist_log("csv_x12_segments: Non-basic ASCII character in segment ({$idx}) in file {$fn}"); // quit here? return false; -- actually files have probably been scanned before in upload.php // also x12 files have more allowed characters than these } if ($seg_array) { $ar_seg['segments'][] = explode($elem_d, $seg_text); } else { $ar_seg['segments'][] = $seg_text; } $st_segs_ct++; $isa_segs_ct++; // // some checks, if wanted if (substr($seg_text, 0, 4) == $isa_str) { $isa_seg = explode($elem_d, $seg_text); $isa_id = $isa_seg[13]; $isa_segs_ct = 1; $isa_ct++; continue; } // if (substr($seg_text, 0, 3) == $st_str) { // $e = strpos($seg_text, $elem_d, 8); // ST*835* is 7 characters // $st02 = substr($seg_text, 7, $e-7); $st_ar = explode($elem_d, $seg_text); $st_num = $st_ar[2]; $st_segs_ct = 1; continue; } if (substr($seg_text, 0, 3) == $se_str) { $se_ar = explode($elem_d, $seg_text); $se_seg_ct = $se_ar[1]; $se_num = $se_ar[2]; if ($se_num != $st_num) { csv_edihist_log("csv_x12_segments: ST-SE number mismatch {$st_num} {$se_num} in {$fn}"); } if (intval($se_seg_ct) != $st_segs_ct) { csv_edihist_log("csv_x12_segments: ST-SE segment count mismatch {$st_segs_ct} {$se_seg_ct} in {$fn}"); } continue; } if (substr($seg_text, 0, 4) == $iea_str) { $iea_seg = explode($elem_d, $seg_text); $iea_id = $iea_seg[2]; $iea_ct++; // if ($isa_id != $iea_id) { csv_edihist_log("csv_x12_segments: ISA-IEA identifier mismatch set {$iea_ct} in {$fn}"); } if ($iea_ct == $isa_ct) { $trnset_seg_ct += $isa_segs_ct; if ($idx + 1 != $trnset_seg_ct) { // csv_edihist_log("csv_x12_segments: IEA segment count error ({idx+1}:{$trnset_seg_ct} set) {$iea_ct} in {$fn}"); } } else { csv_edihist_log("csv_x12_segments: ISA-IEA count mismatch set {$isa_ct} {$iea_ct} in {$fn}"); } } // } // return $ar_seg; }