2 /************* edih_archive.php
3 * Author: Kevin McCormick Longview Texas
5 * Copyright 2016 Kevin McCormick Longview, Texas
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 * Purpose: to archive old entries in the csv files and old files
25 * @author Kevin McCormick
26 * @link: http://www.open-emr.org
28 * @subpackage ediHistory
31 // a security measure to prevent direct web access to this file
32 // must be accessed through the main calling script ibr_history.php
33 // from admin at rune-city dot com; found in php manual
34 //if (!defined('SITE_IN')) die('Direct access not allowed!');
38 //require_once("$srcdir/edihistory/test_edih_csv_inc.php");
40 // constant DS = DIRECTORY_SEPARATOR
43 * Report on edi_history
45 * @uses csv_parameters()
46 * @uses csv_assoc_array()
48 * @param string archive date in CCYYMMDD format
50 * @return array array[i] = filename
52 function edih_archive_report($period = '')
58 // edih_archive_date returns empty string if no period
59 $tper = edih_archive_date($period);
60 $chkdt = ($tper) ?
$tper : 'None';
61 $strdt = ($tper) ?
substr($chkdt, 0, 4).'-'.substr($chkdt, 4, 2).'-'.substr($chkdt, 6, 2) : 'None';
63 csv_edihist_log("edih_archive_report: creating archive report with date $chkdt");
65 $bdir = csv_edih_basedir();
66 $params = csv_parameters('ALL');
67 if (!is_array($params) && count($params)) {
68 csv_edihist_log("edih_archive_report: invalid csv_parameters");
69 return "<p>There was an error creating the report.</p>";
73 $str_html .= "<h3>Report on edi files using archive date " . text($strdt) . "</h3>".PHP_EOL
;
74 foreach ($params as $key => $param) {
86 $fdir = $param['directory'];
89 $dir_ar = scandir($fdir);
90 if (is_array($dir_ar) && ((count($dir_ar)-2) > 0)) {
91 $str_html .= "<H3><em>Type</em> " . text($tp) . "</H3>".PHP_EOL
;
92 $str_html .= "<ul>".PHP_EOL
;
93 $dir_ct = count($dir_ar);
94 foreach ($dir_ar as $fn) {
95 if ($fn == 'README.txt') {
100 if (substr($fn, 0, 1) == '.') {
105 if (is_dir($fdir.DS
.$fn)) {
111 $dir_sz +
= filesize($fdir.DS
.$fn);
115 $csv_ar = csv_assoc_array($tp, 'file');
116 $row_ct = (is_array($csv_ar)) ?
count($csv_ar) : 0;
118 foreach ($csv_ar as $row) {
119 // tally amount of claim transactions in the files
121 $clm_ct +
= $row['Claim_ct'];
125 $clm_ct +
= ($row['Accept'] +
$row['Reject']);
129 $clm_ct +
= $row['Claim_ct'];
132 // check for duplicates
133 // here assume that files with multiple rows are consecutive
134 if ($fntp !== $row['FileName']) {
135 $fntp = $row['FileName'];
136 // count files that would be archived
137 if (($chkdt != 'None') && strcmp($row['Date'], $chkdt) < 0) {
146 $dir_kb = csv_convert_bytes($dir_sz);
148 csv_edihist_log("edih_archive_report: error $tp file count $dir_ct with csv rows $row_ct");
152 $mis = ($fntp_ct == $dir_ct ) ?
"(check/eft count or ISA--IEA count)" : "(mismatch csv $fntp_ct dir $dir_ct)";
155 $str_html .= "<li><em>Note:</em> 837 Claims files are not archived </li>".PHP_EOL
;
159 $str_html .= "<li>files directory has " . text($dir_ct) . " files, using " . text($dir_kb) . " </li>".PHP_EOL
;
160 $str_html .= ($subdir_ct && ($tp != 'f837')) ?
"<li> <em>warning</em> found " . text($subdir_ct) . " sub-directories</li>".PHP_EOL
: "";
161 $str_html .= "<li>files csv table has " . text($row_ct) . " rows " . text($mis) . "</li>".PHP_EOL
;
162 $str_html .= ($clm_ct) ?
"<li>there are " . text($clm_ct) . " claim transactions counted</li>".PHP_EOL
: "";
163 $str_html .= ($old_ct) ?
"<li>Archive date " . text($strdt) . " would archive " . text($old_ct) . " files </li>".PHP_EOL
: "";
164 $str_html .= "</ul>".PHP_EOL
;
166 $str_html .= "<p><em>Type</em> <b>" . text($tp) . "</b> <br> -- empty " . text($tp) . " file directory</p>".PHP_EOL
;
169 $str_html .= "<p><em>warning</em> <b>" . text($tp) . "</b> file directory does not exist</p>".PHP_EOL
;
173 $str_html .= "<p>Report end</p>".PHP_EOL
;
180 * Format the date used in comparisons
182 * @param string period from select list e.g. 6m, 12m
184 * @return string archive date in CCYYMMDD format
186 function edih_archive_date($period)
194 $is_period = preg_match('/\d{1,2}(?=m)/', $period, $matches);
196 if (count($matches)) {
199 if (strpos($period, 'm')) {
200 // take the number part of 'period'
201 // so modstr will be '-N month'
202 $modstr = '-'.$matches[0].' month';
203 $dtstr1 = $gtdt['mon'].'/01/'.$gtdt['year'];
204 } elseif (strpos($period, 'y')) {
205 $modstr = '-'.$matches[0].' year';
206 $dtstr1 = $gtdt['mon'].'/01/'.$gtdt['year'];
208 csv_edihist_log("edih_archive_date: incorrect date period $period");
214 $dtpd1 = date_create($dtstr1);
215 $dtm = date_modify($dtpd1, $modstr);
216 $dtpd2 = $dtm->format('Ymd');
218 csv_edihist_log("edih_archive_date: failed to parse $period");
222 csv_edihist_log("edih_archive_date: invalid argment $period");
226 // the testing date in CCYYMMDD format
232 * Create an array of file names to be archived
233 * The 'Date' column in the files_[type].csv file
234 * is compared to the archive date. If the date is less
235 * than the archive date, the "FileName' value is copied
237 * @param array csv file rows array
238 * @param string archive date in CCYYMMDD format
240 * @return array array[i] = filename
242 function edih_archive_filenames($csv_ar, $archive_date)
245 if ($archive_date && strlen($archive_date) == 8 && is_numeric($archive_date)) {
246 $testdate = (string)$archive_date;
248 csv_edihist_log("edih_archive_filenames: invalid archive date $archive_date");
253 if (!is_array($csv_ar) ||
!count($csv_ar)) {
254 csv_edihist_log("edih_archive_filenames: failed to get csv file array $file_type");
260 foreach ($csv_ar as $row) {
261 if (strcmp($row['Date'], $archive_date) < 0) {
262 $fn_ar[] = $row['FileName'];
266 $ret_ar = (count($fn_ar)) ?
array_values(array_unique($fn_ar)) : $fn_ar;
272 * Create a new csv array by omitting rows which reference
273 * a file name that is to be archived
275 * @uses csv_file_type()
276 * @uses csv_assoc_array()
278 * @param string the file type
279 * @param string the csv type file or claim
280 * @param array the array of archived file names and retained file names
284 function edih_archive_csv_split($csv_ar, $filename_array)
287 if (!is_array($filename_array) ||
!count($filename_array)) {
288 csv_edihist_log('csv_archive_table; invalid filename array');
293 if (is_array($csv_ar) && count($csv_ar)) {
294 csv_edihist_log("edih_archive_csv_split: csv rows ".count($csv_ar)." old files ".count($filename_array));
296 csv_edihist_log("edih_archive_csv_split: failed to get csv file array");
301 // if the to be archived file name is in the row,
302 // do not copy it to the new csv array
304 $arch_ar['arch'] = array();
305 $arch_ar['keep'] = array();
307 foreach ($csv_ar as $row) {
308 if (in_array($row['FileName'], $filename_array)) {
309 $arch_ar['arch'][] = $row;
311 $arch_ar['keep'][] = $row;
316 csv_edihist_log("edih_archive_csv_split: 'arch' array rows ".count($arch_ar['arch']));
317 csv_edihist_log("edih_archive_csv_split: 'keep' array rows ".count($arch_ar['keep']));
324 * Creates a zip archive of the files in the $filename_ar array and
325 * returns the path/name of the archive or FALSE on error
327 * @param array $parameters array for file type from csv_parameters
328 * @param array $filename_ar array of filenames to be archived
329 * @param string $archive_date date of archive to be incorporated in archive file name
331 * @return bool result of zipArchive functions
333 function edih_archive_create_zip($parameters, $filename_ar, $archive_date, $archive_filename)
335 // we deal with possible maximum files issues by chunking the $fn_ar array
337 $ft = $parameters['type'];
338 $fdir = $parameters['directory'];
339 $tmp_dir = csv_edih_tmpdir();
340 // archive csv rows -- same name as from edih_archive_main
341 // $fn_files_arch = $tmp_dir.DS.'arch_'.basename($files_csv);
342 $files_csv_arch = 'arch_'.basename($parameters['files_csv']);
343 // $fn_claims_arch = $tmp_dir.DS.'arch_'.basename($claim_csv);
344 $claims_csv_arch = 'arch_'.basename($parameters['claims_csv']);
348 // to handle possibility of more than 200 files in the archive
349 // use the 'chunk' method
350 if (count($filename_ar) > $f_max) {
351 $fn_ar2 = array_chunk($filename_ar, $f_max);
353 $fn_ar2[] = $filename_ar;
357 $zip_name = $tmp_dir.DS
.$archive_filename;
358 csv_edihist_log("edih_archive_create_zip: using $zip_name");
360 $zip_obj = new ZipArchive();
361 csv_edihist_log("edih_archive_create_zip: now opening archive $archive_filename");
362 if (is_file($zip_name)) {
363 $isOK = $zip_obj->open($zip_name, ZIPARCHIVE
::CHECKCONS
);
365 if ($zip_obj->locateName($ft) === false) {
366 $isOK = $zip_obj->addEmptyDir($ft);
368 csv_edihist_log("edih_archive_create_zip: adding $ft ZipArchive error $msg");
373 $msg = $zip_obj->getStatusString();
374 csv_edihist_log("edih_archive_create_zip: $ft ZipArchive error $msg");
378 $isOK = $zip_obj->open($zip_name, ZIPARCHIVE
::CREATE
);
379 $isOK = $zip_obj->addEmptyDir('csv');
380 $isOK = $zip_obj->addEmptyDir($ft);
381 $zip_obj->setArchiveComment("edi_history archive prior to $archive_date");
384 // we are working with the open archive
385 // now add the old csv files to the archive
386 if (is_file($tmp_dir.DS
.$files_csv_arch)) {
387 csv_edihist_log("edih_archive_create_zip: now adding $files_csv_arch to archive");
388 $isOK = $zip_obj->addFile($tmp_dir.DS
.$files_csv_arch, 'csv'.DS
.$files_csv_arch);
391 if (is_file($tmp_dir.DS
.$claims_csv_arch)) {
392 csv_edihist_log("edih_archive_create_zip: now adding $claims_csv_arch to archive");
393 $isOK = $zip_obj->addFile($tmp_dir.DS
.$claims_csv_arch, 'csv'.DS
.$claims_csv_arch);
397 csv_edihist_log("edih_archive_create_zip: now closing archive");
398 $isOK = $zip_obj->close();
399 if ($isOK !== true) {
400 $msg = $zip_obj->getStatusString();
401 csv_edihist_log("edih_archive_create_zip: $ft ZipArchive error $msg");
406 csv_edihist_log("edih_archive_create_zip: with file name groups ".count($fn_ar2));
407 foreach ($fn_ar2 as $fnz) {
408 // reopen the zip archive on each loop so the open file count is controlled
409 if (is_file($zip_name)) {
410 csv_edihist_log("edih_archive_create_zip: now opening archive");
411 $isOK = $zip_obj->open($zip_name, ZIPARCHIVE
::CHECKCONS
);
415 if ($isOK === true) {
416 // we are working with the open archive
417 // now add the old x12 files to the archive
418 csv_edihist_log("edih_archive_create_zip: now adding $ft files to archive");
419 foreach ($fnz as $fz) {
420 if ($fz == '.' ||
$fz == '..') {
424 if (is_file($fdir.DS
.$fz) && is_readable($fdir.DS
.$fz)) {
425 $isOK = $zip_obj->addFile($fdir.DS
.$fz, $ft.DS
.$fz);
427 // possible that file is in csv table, but not in directory?
428 $msg = $zip_obj->getStatusString();
429 csv_edihist_log("edih_archive_create_zip: error adding file $fz zipArchive: $msg");
431 } // end foreach($fnz as $fz)
432 // close zip object for next iteration of chunked array
433 csv_edihist_log("edih_archive_create_zip: now closing archive");
434 $isOK = $zip_obj->close();
435 // errors on close would be non-existing file added or something else
436 if ($isOK !== true) {
437 $msg = $zip_obj->getStatusString();
438 csv_edihist_log("edih_archive_create_zip: $ft ZipArchive error $msg");
443 // ZipArchive open() failed -- try to get the error message and return false
444 $msg = $zip_obj->getStatusString();
445 csv_edihist_log("edih_archive_create_zip: $ft ZipArchive failed $msg");
449 } // end foreach($fn_ar2 as $fnz)
455 * Archived files have been included in archive file
456 * so we move the files to the archive tmp directory, for later deletion
458 * @param array parameters array for type
459 * @param array filename array
461 * @return int count of moved files
463 function edih_archive_move_old($parameters, $filename_ar)
466 if (!is_array($filename_ar) ||
!count($filename_ar)) {
470 if (!is_array($parameters) ||
!count($parameters)) {
475 clearstatcache(true);
478 $fn_ar_ct = count($filename_ar);
479 $ft = $parameters['type'];
480 $fdir = $parameters['directory'];
481 $fdir = realpath($fdir);
482 $rndir = csv_edih_tmpdir().DS
.$ft;
485 csv_edihist_log("edih_archive_delete_old: $ft dir OK");
486 if (is_dir($rndir) ||
mkdir($rndir)) {
487 $rndir = realpath($rndir);
488 csv_edihist_log("edih_archive_delete_old: $ft move dir OK");
491 csv_edihist_log("edih_archive_delete_old: $ft move dir error");
495 csv_edihist_log("edih_archive_delete_old: $ft dir error");
501 csv_edihist_log("edih_archive_delete_old: $ft old file count $fn_ar_ct");
502 foreach ($filename_ar as $fn) {
503 // if we have added the file to the archive, remove it from the storage directory
504 // but keep the /history/tmp file copy for now
505 if (is_file($fdir.DS
.$fn)) {
506 $isrn = rename($fdir.DS
.$fn, $rndir.DS
.$fn);
513 csv_edihist_log("edih_archive_delete_old: $ft failed to move $fn");
517 csv_edihist_log("edih_archive_delete_old: $ft directory error for files or tmp");
526 * create associative array from archive csv file
528 * @uses edih_archive_csv_array()
532 * @param string optional filepath
536 function edih_archive_csv_array($filetype, $csv_type, $filepath = '')
541 $tmpdir = csv_edih_tmpdir();
542 $tmpcsv = $tmpdir.DS
.'csv';
544 $csvtp = (strpos($csv_type, 'aim')) ?
'claims' : 'files';
546 if (is_file($filepath)) {
547 $csv_arch_path = $filepath;
549 $csv_arch_path = $tmpcsv.DS
.'arch_'.$csvtp.'_'.$filetype.'.csv';
556 // relies on first row being header or column names
557 if (($fh = fopen($csv_arch_path, "rb")) !== false) {
558 while (($data = fgetcsv($fh, 2048, ",")) !== false) {
559 if (is_null($data)) {
564 for ($i=0; $i<$ct; $i++
) {
565 $csv_ar[$ky][$h[$i]] = $data[$i];
579 csv_edihist_log('edih_archive_csv_array; invalid file path '.$csv_arch_path);
588 * combine the csv file in the archive with the current csv file
590 * @uses edih_archive_csv_array()
597 function edih_archive_csv_combine($filetype, $csvtype)
602 $bdir = csv_edih_basedir();
603 $tmpdir = csv_edih_tmpdir();
604 $tmpcsv = $tmpdir.DS
.'csv';
606 $csvtp = (strpos($csvtype, 'aim')) ?
'claims' : 'files';
607 $csv_arch_file = $tmpcsv.DS
.'arch_'.$csvtp.'_'.$filetype.'.csv';
608 $csv_new_file = $tmpdir.DS
.'cmb_'.$csvtp.'_'.$filetype.'.csv';
610 // arrays used to eliminate duplicate rows
611 $dup_ar = $dup_unique = $dup_keys = array();
612 // combine files by combining arrays and writing a tmp file
613 // get the present csv file contents
614 $car1 = csv_assoc_array($filetype, $csvtp);
615 // get the archived csv contents
616 if (is_file($csv_arch_file)) {
617 $car2 = edih_archive_csv_array($filetype, $csvtp, $csv_arch_file);
620 // possibility of empty arrays if no data rows in a csv file
621 $hdrc1 = (is_array($car1) && count($car1)) ?
array_keys($car1[0]) : array();
622 $hdrc2 = (is_array($car2) && count($car2)) ?
array_keys($car2[0]) : array();
623 if (count($hdrc1) && ($hdrc1 === $hdrc2)) {
625 } elseif (empty($hdrc1) && count($hdrc2)) {
627 } elseif (empty($hdrc2) && count($hdrc1)) {
630 // array mismatch error (impossible?)
631 csv_edihist_log("edih_archive_csv_combine: $filetype $csvtp array header mismatch");
632 // just use the current csv file
633 $hdr_ar = csv_table_header($filetype, $csvtp);
634 $car_cmb_unique = $car1;
638 foreach ($hdrc1 as $h) {
642 csv_edihist_log("edih_archive_csv_combine: $csvtp car1 header $dbg_str");
644 csv_edihist_log("edih_archive_csv_combine: $csvtp car1 header empty");
649 foreach ($hdrc2 as $h) {
653 csv_edihist_log("edih_archive_csv_combine: $csvtp car2 header $dbg_str");
655 csv_edihist_log("edih_archive_csv_combine: $csvtp car2 header empty");
661 // if the arrays checked out
662 if (!isset($car_cmb_unique)) {
663 // if we have archive csv rows
664 if (is_array($car1) && is_array($car2)) {
665 // put the archive rows first
666 $car_cmb = array_merge($car2, $car1);
667 // now eliminate duplicates
668 if ($csvtp == 'files') {
669 if ($filetype == 'f835') {
675 // array_column() php v5.5
676 foreach ($car_cmb as $idx => $row) {
677 $dup_ar[$idx] = $row[$ky];
680 csv_edihist_log("edih_archive_csv_combine: $csvtp array row count ".count($dup_ar));
681 $dup_unique = array_unique($dup_ar);
682 $dup_keys = array_keys($dup_unique);
683 csv_edihist_log("edih_archive_csv_combine: $csvtp index row count ".count($dup_keys));
684 foreach ($dup_keys as $k) {
685 $car_cmb_unique[] = $car_cmb[$k];
688 csv_edihist_log("edih_archive_csv_combine: $csvtp combined row count ".count($car_cmb_unique));
689 } elseif ($csvtp == 'claims') {
690 $ct = count($hdr_ar);
691 $ftxt = $csvtp.' array'.PHP_EOL
;
692 foreach ($car_cmb as $idx => $row) {
694 for ($i=0; $i<$ct; $i++
) {
695 $r_str .= $row[$hdr_ar[$i]];
698 $dup_ar[$idx] = $r_str;
699 $ftxt .= $r_str.PHP_EOL
;
702 csv_edihist_log("edih_archive_csv_combine: $csvtp array row count ".count($dup_ar));
703 file_put_contents($tmpdir.DS
.'archive'.DS
.'claimstr.txt', $ftxt);
705 $dup_unique = array_unique($dup_ar);
706 $dup_keys = array_keys($dup_unique);
707 csv_edihist_log("edih_archive_csv_combine: $csvtp index row count ".count($dup_keys));
708 foreach ($dup_keys as $k) {
709 $car_cmb_unique[] = $car_cmb[$k];
712 csv_edihist_log("edih_archive_csv_combine: $csvtp combined row count ".count($car_cmb_unique));
714 $car_cmb_unique = $car_cmb;
717 csv_edihist_log("edih_archive_csv_combine: array keys mismatch $filetype");
720 csv_edihist_log("edih_archive_csv_combine: error reading archived csv ".$csvtp."_".$filetype.".csv");
724 $fh = fopen($csv_new_file, 'wb');
726 fputcsv($fh, $hdr_ar);
729 foreach ($car_cmb_unique as $row) {
734 // close new csv file
737 csv_edihist_log("edih_archive_csv_combine: failed to open $filetype new csv file");
744 * Unpack an existing archive and restore it to current csv records
745 * and replace the files in the respective directories
747 * @uses edih_archive_csv_combine
752 function edih_archive_restore($archive_name)
756 $bdir = csv_edih_basedir();
757 $tmpdir = csv_edih_tmpdir();
758 $archdir = $bdir.DS
.'archive';
760 if (is_file($archdir.DS
.$archive_name)) {
761 $arch = realpath($archdir.DS
.$archive_name);
762 $str_out .= "Archive: restoring " . text($archive_name) . "<br>";
763 csv_edihist_log("edih_archive_restore: restoring $archive_name");
765 $str_out = "Archive: restore archive bad file name " . text($archive_name) . " <br>";
766 csv_edihist_log("edih_archive_restore: restore archive bad file name $archive_name");
771 $zip_obj = new ZipArchive();
772 // open archive (ZIPARCHIVE::CHECKCONS the ZIPARCHIVE::CREATE is supposedly necessary for microsoft)
773 //$res = $zip_obj->open($arch, ZIPARCHIVE::CHECKCONS);
774 if ($zip_obj->open($arch, ZIPARCHIVE
::CHECKCONS
) === true) {
775 $f_ct = $zip_obj->numFiles
;
776 $str_out .= "Extracting " . text($f_ct) . " items from " . text($archive_name) . " <br>";
777 csv_edihist_log("edih_archive_restore: Extracting $f_ct items from $archive_name");
778 $isOK = $zip_obj->extractTo($tmpdir);
780 $msg = $zip_obj->getStatusString();
781 csv_edihist_log("edih_archive_restore: error extracting archive");
782 $str_out .= "Archive: error extracting archive " . text($archive_name) . " <br>";
783 $str_out .= "zipArchive: " . text($msg) . " <br>";
787 $msg = $zip_obj->getStatusString();
788 csv_edihist_log("edih_archive_restore: error opening archive");
789 $str_out .= "Archive: error opening archive <br>".PHP_EOL
;
790 $str_out .= "zipArchive: " . text($msg) . " <br>";
794 // now traverse the tmpdir and replace things
795 // we should have tmp/csv/files_[ftype].csv claims_[ftype].csv
796 // tmp/[ftype]/x12_filenames
797 $arch_ar = scandir($tmpdir);
799 foreach ($arch_ar as $fa) {
800 if ($fa == '.' ||
$fa == '..') {
804 if (is_dir($tmpdir.DS
.$fa)) {
809 // if a /history/ftype dir exists
810 if (is_dir($bdir.DS
.$fa)) {
820 csv_edihist_log("edih_archive_restore: types in archive $tpstr");
821 $str_out .= "Archive: types in archive " . text($tpstr) . " <br>".PHP_EOL
;
823 foreach ($type_ar as $ft) {
824 $str_out .= "Archive: now restoring " . text($ft) . "<br>".PHP_EOL
;
825 csv_edihist_log("edih_archive_restore: now restoring $ft");
827 $frows = edih_archive_csv_combine($ft, 'file');
828 csv_edihist_log("edih_archive_restore: files_$ft csv combined rows $frow");
829 $crows = edih_archive_csv_combine($ft, 'claim');
830 csv_edihist_log("edih_archive_restore: claims_$ft csv combined rows $frow");
832 $file_ar = scandir($tmpdir.DS
.$ft);
833 foreach ($file_ar as $fn) {
834 if ($fn == '.' ||
$fn == '..') {
838 if (is_file($tmpdir.DS
.$ft.DS
.$fn)) {
839 $rn = rename($tmpdir.DS
.$ft.DS
.$fn, $bdir.DS
.$ft.DS
.$fn);
841 $str_out .= " -- error restoring " . text($ft) . DS
. text($fn) ."<br>".PHP_EOL
;
842 csv_edihist_log("edih_archive_restore: error restoring ".$ft.DS
.$fn);
847 // this will catch the csv files for the particulat type
848 $str_out .= "Archive: now replacing csv tables for " . text($ft) . "<br>".PHP_EOL
;
849 csv_edihist_log("edih_archive_restore: now replacing csv tables for $ft");
851 $rnf = rename($tmpdir.DS
.'cmb_files_'.$ft.'.csv', $bdir.DS
.'csv'.DS
.'files_'.$ft.'.csv');
852 $rnc = rename($tmpdir.DS
.'cmb_claims_'.$ft.'.csv', $bdir.DS
.'csv'.DS
.'claims_'.$ft.'.csv');
853 $str_out .= ($rnf) ?
"" : " -- error restoring files_" . text($ft) . ".csv <br>".PHP_EOL
;
854 $str_out .= ($rnc) ?
"" : " -- error restoring claims_" . text($ft) . ".csv <br>".PHP_EOL
;
858 csv_edihist_log("edih_archive_restore: now removing archive file");
859 $str_out .= "Archive: now removing archive file <br>".PHP_EOL
;
862 csv_edihist_log("edih_archive_restore: error removing $archdir.DS.$archive_name");
863 $str_out .= ($rnf) ?
"" : " -- error removing " . text($archdir) . "." . DS
. "." . text($archive_name) . PHP_EOL
;
867 //edih_archive_cleanup($arch_fn, $tp_ar);
868 csv_edihist_log("edih_archive_restore: now removing temporary files");
869 $str_out .= "Archive: now removing temporary files <br>".PHP_EOL
;
872 $is_clear = csv_clear_tmpdir();
874 $str_out .= "Archive: temporary files removed. Process complete.<br>" .PHP_EOL
;
876 $str_out .= "Archive: still some files in /history/tmp/. Process complete.<br>" .PHP_EOL
;
885 * restores files from the tmp dir if the archive process needs to be aborted
887 * @uses csv_edih_basedir()
888 * @uses csv_edih_tmpdir()
889 * @uses csv_parameters()
893 function edih_archive_undo()
896 // archive process creates files in /history/tmp
897 // /tmp/old_files_[type].csv copy of pre-archive csv record
898 // /tmp/old_claims_[type].csv copy of pre-archive csv record
899 // /tmp/new_files_[type].csv csv record of non-archived files
900 // /tmp/new_claims_[type].csv csv record of non-archived files
901 // /tmp/arch_files_[type].csv csv record of archived files (to be put in zip file)
902 // /tmp/arch_claims_[type].csv csv record of archived files (to be put in zip file)
903 // /tmp/[type]/filename_to_be_archived all the archived files for [type]
906 $bdir = csv_edih_basedir();
907 $tmpdir = csv_edih_tmpdir();
908 $archdir = $bdir.DS
.'archive';
910 $params = csv_parameters("ALL");
911 $types_ar = array_keys($params);
913 csv_edihist_log("edih_archive_undo: restoring prior csv files files");
914 foreach ($types_ar as $ft) {
915 if (is_file($tmpdir.DS
.'old_files_'.$ft.'.csv')) {
916 $rn = rename($tmpdir.DS
.'old_files_'.$ft.'.csv', $bdir.DS
.'csv'.DS
.'files_'.$ft.'.csv');
918 csv_edihist_log("edih_archive_undo: restored prior files_$ft ");
920 csv_edihist_log("edih_archive_undo: restore failed for prior files_$ft ");
924 if (is_file($tmpdir.DS
.'old_claims_'.$ft.'.csv')) {
925 $rn = rename($tmpdir.DS
.'old_claims_'.$ft.'.csv', $bdir.DS
.'csv'.DS
.'claims_'.$ft.'.csv');
927 csv_edihist_log("edih_archive_undo: restored prior claimss_$ft ");
929 csv_edihist_log("edih_archive_undo: restore failed for prior claims_$ft ");
934 $arch_ar = scandir($tmpdir);
935 foreach ($arch_ar as $fa) {
936 if ($fa == "." && $fa == "..") {
940 if (is_dir($tmpdir.DS
.$fa)) {
941 if (in_array($fa, $types_ar)) {
942 $fpath = $params[$fa]['directory'];
943 if ($dh = opendir($tmpdir.DS
.$fa)) {
944 $str_out .= "Archive: undo restoring " . text($fa) . " files<br>".PHP_EOL
;
945 csv_edihist_log("edih_archive_undo: restoring $fa files");
946 while (false !== ($entry = readdir($dh))) {
947 if ($entry != "." && $entry != "..") {
948 if (is_file($fpath.DS
.$entry)) {
949 // file was not moved
951 rename($tmpdir.DS
.$fa.DS
.$entry, $fpath.DS
.$entry);
967 * After the archive is created, the csv record needs to be re-written so the archived
968 * files are not in the csv file and hence, not searched for.
970 * @uses csv_table_header()
972 * @param string $csv_path the tmp csv file path is expected
973 * @param array $row_array the data rows to be written (an associative array)
975 * @return integer count the rows written
977 function edih_archive_rewrite_csv($csv_path, $csv_keys, $row_array)
979 // @param string $csv_path -- the tmp csv file path is expected
980 // @param array $heading_ar -- the column heading for the csv file
981 // @param array $row_array -- the data rows to be written
983 // count characters written -- returned by fputcsv
987 if (is_array($row_array)) {
988 csv_edihist_log("edih_archive_rewrite_csv: row array count ".count($row_array));
990 csv_edihist_log("edih_archive_rewrite_csv: row array not array");
994 if (is_array($row_array) && is_array($csv_keys)) {
995 if (count($csv_keys)) {
999 csv_edihist_log("edih_archive_rewrite_csv: invalid row array");
1003 //$csv_path should end with /history/tmp/[arch|keep]_[files|claims]_[type].csv
1004 // with 'w' flag, place the file pointer at the beginning of the file
1005 // and truncate the file to zero length.
1006 // If the file does not exist, attempt to create it.
1007 $fh3 = fopen($csv_path, 'wb');
1009 // write the heading row first
1010 $ocwct +
= fputcsv($fh3, $h_ar);
1011 // wrote heading, now add rows
1012 foreach ($row_array as $row) {
1013 $ocwct +
= fputcsv($fh3, $row);
1018 csv_edihist_log("edih_archive_rewrite_csv: wrote ".count($row_array)." rows to ".basename($csv_path));
1020 csv_edihist_log("edih_archive_rewrite_csv: failed to open $csv_path");
1028 * cleanup archived files after archive created
1030 * @param string name of archive file
1031 * @param array array of types included in archive
1035 function edih_archive_cleanup($archivename, $types_ar)
1040 if (is_array($types_ar) && count($types_ar)) {
1043 csv_edihist_log("edih_archive_cleanup: no types in file types list");
1044 $str_out = "no types in file types list".PHP_EOL
;
1048 $bdir = csv_edih_basedir();
1049 $tmpdir = csv_edih_tmpdir();
1050 $archivedir = $bdir.DS
.'archive';
1052 // move archive file to archive directory
1053 csv_edihist_log("edih_archive_cleanup: now clearing temporary files");
1054 $str_out .= "Archive: now clearing temporary files<br>".PHP_EOL
;
1055 // delete archived files from edih tmp dir
1056 foreach ($tdirs as $td) {
1057 csv_edihist_log("edih_archive_cleanup: cleaning up for $td");
1058 if (is_dir($tmpdir.DS
.$td)) {
1059 $fn_ar = scandir($tmpdir.DS
.$td);
1060 foreach ($fn_ar as $fn) {
1061 if ($fn == '.' ||
$fn == '..') {
1065 if (is_file($tmpdir.DS
.$td.DS
.$fn)) {
1066 $ul = unlink($tmpdir.DS
.$td.DS
.$fn);
1068 csv_edihist_log("edih_archive_cleanup: error removing file $fn");
1069 $str_out .= "<p>edih_archive_cleanup: error removing file " . text($td) . DS
. text($fn) . "</p>";
1076 // try to remove the now empty directory
1077 csv_edihist_log("edih_archive_cleanup: removing tmp $td");
1078 rmdir($tmpdir.DS
.$td);
1081 csv_edihist_log("edih_archive_cleanup: removed $fct files from $td");
1089 * The main function in this edih_archive.php script. This function gets the parameters array
1090 * from csv_parameters() and calls the archiving functions on each type of file
1091 * in the parameters array.
1093 * @uses edih_archive_date()
1094 * @uses csv_edih_basedir()
1095 * @uses csv_parameters()
1096 * @uses csv_edih_tmpdir()
1097 * @uses csv_table_header()
1098 * @uses edih_archive_filenames()
1099 * @uses edih_archive_rewrite_csv()
1100 * @uses edih_archive_csv_split()
1101 * @uses edih_archive_create_zip()
1103 * @param string from select drop-down 6m, 12m, 18m, etc
1105 * @return string descriptive message in html format
1107 function edih_archive_main($period)
1112 $archive_date = edih_archive_date($period);
1113 if ($archive_date) {
1114 $archive_dir = csv_edih_basedir().DS
.'archive';
1115 $tmp_dir = csv_edih_tmpdir();
1116 $arch_fn = $archive_date.'_archive.zip';
1117 $params = csv_parameters();
1119 csv_edihist_log("edih_archive_main: error creating archive date from $period");
1120 $out_html = "Error creating archive date from " . text($period) . "<br />" .PHP_EOL
;
1123 $out_html = "Archive period invalid.<br />" .PHP_EOL
;
1128 if (is_dir($archive_dir)) {
1129 if (is_file($archive_dir.DS
.$arch_fn)) {
1130 csv_edihist_log("edih_archive_main: archive file $arch_fn already exists");
1131 $out_html = "Archive: archive file " . text($arch_fn) . " already exists<br>" .PHP_EOL
;
1135 // should have been created at setup
1136 if (!mkdir($archive_dir, 0755)) {
1137 csv_edihist_log("edih_archive_main: archive directory does not exist");
1138 $out_html = "Archive: archive directory does not exist<br>" .PHP_EOL
;
1144 foreach ($params as $k => $p) {
1146 $ft = $p['type']; // could be $k
1148 if ($ft == 'f837') {
1149 csv_edihist_log("edih_archive_main: 837 Claims files are not archived");
1153 $fdir = $p['directory'];
1154 $scan = scandir($fdir);
1155 if (!$scan ||
count($scan) < 3) {
1160 $files_csv = $p['files_csv'];
1161 $claims_csv = $p['claims_csv'];
1162 $date_col = $p['filedate'];
1163 $fncol = 'FileName';
1165 // create three csv file paths 'old_', 'arch_', and 'keep_'
1166 // files csv temporary names
1167 $fn_files_old = $tmp_dir.DS
.'old_'.basename($files_csv);
1168 $fn_files_arch = $tmp_dir.DS
.'arch_'.basename($files_csv);
1169 $fn_files_keep = $tmp_dir.DS
.'keep_'.basename($files_csv);
1170 // claims csv temporary names
1171 $fn_claims_old = $tmp_dir.DS
.'old_'.basename($claims_csv);
1172 $fn_claims_arch = $tmp_dir.DS
.'arch_'.basename($claims_csv);
1173 $fn_claims_keep = $tmp_dir.DS
.'keep_'.basename($claims_csv);
1175 $fh_ar = csv_table_header($ft, 'file');
1176 $ch_ar = csv_table_header($ft, 'claim');
1177 // copy existing csv files -- continue to next type if no files_csv
1178 $iscpc = $iscpf = false;
1179 if (is_file($files_csv)) {
1180 $iscpf = copy($files_csv, $fn_files_old);
1181 csv_edihist_log("edih_archive_main: copy $ft files csv to tmp dir");
1183 csv_edihist_log("edih_archive_main: $ft files csv does not exist");
1187 if (is_file($claims_csv)) {
1188 $iscpc = copy($claims_csv, $fn_claims_old);
1189 csv_edihist_log("edih_archive_main: copy $ft claims csv to tmp dir");
1191 if ($ft == 'f997') {
1192 // there may be no 997 type claims records, so create a dummy file
1193 $fh = fopen($fn_claims_old, 'wb');
1195 fputcsv($fh, $ch_ar);
1199 csv_edihist_log("edih_archive_main: $ft claims csv does not exist");
1205 if (!$iscpf ||
!$iscpc) {
1206 csv_edihist_log("edih_archive_csv_old: copy to tmp dir failed for csv file $ft");
1207 $out_html = "Archive temporary files operation failed ... aborting <br />" .PHP_EOL
;
1208 // need to call archive_undo()
1209 $out_html .= edih_archive_undo();
1214 $csv_files_ar = csv_assoc_array($ft, 'file');
1215 $csv_claims_ar = csv_assoc_array($ft, 'claim');
1216 // get filenames to be archived
1219 $fn_ar = edih_archive_filenames($csv_files_ar, $archive_date);
1220 if (count($fn_ar)) {
1223 // get the old and new csv row arrays for files_csv
1224 $arch_new = edih_archive_csv_split($csv_files_ar, $fn_ar);
1226 if (isset($arch_new['keep'])) {
1228 $frws = edih_archive_rewrite_csv($fn_files_keep, $fh_ar, $arch_new['keep']);
1229 $out_html .= "type " . text($ft) . " keep files_csv file with " . text($frws) . " rows<br>";
1232 if (isset($arch_new['arch'])) {
1234 $frws2 = edih_archive_rewrite_csv($fn_files_arch, $fh_ar, $arch_new['arch']);
1235 $out_html .= "type " . text($ft) . " archive files_csv file with " . text($frws2) . " rows<br>";
1238 $out_html .= "type $ft error creating new files_csv tables";
1241 // repeat for claims_csv
1242 $arch_new = edih_archive_csv_split($csv_claims_ar, $fn_ar);
1244 if (isset($arch_new['keep'])) {
1246 $crws = edih_archive_rewrite_csv($fn_claims_keep, $ch_ar, $arch_new['keep']);
1247 $out_html .= "type " . text($ft) . " keep claims_csv file with " . text($crws) . " rows<br>";
1250 if (isset($arch_new['arch'])) {
1252 $crws = edih_archive_rewrite_csv($fn_claims_arch, $ch_ar, $arch_new['arch']);
1253 $out_html .= "type " . text($ft) . " archive claims_csv file with " . text($crws) . " rows<br>";
1256 $out_html .= "type " . text($ft) . " error creating new claims csv tables<br>";
1259 // now the csv_records are in files
1260 // file records in $fn_files_arch $fn_files_keep
1261 // claim records in $fn_claims_arch $fn_claims_new
1263 // create a zip archive
1264 // zf is result of zipArchive functions true or false
1265 $zf = edih_archive_create_zip($p, $fn_ar, $archive_date, $arch_fn);
1267 // delete archived files
1269 // replace the csv files
1270 $rn = rename($fn_files_keep, $files_csv);
1272 csv_edihist_log("edih_archive_main: replaced $files_csv");
1274 csv_edihist_log("edih_archive_main: error trying to replace $files_csv");
1277 $rn = rename($fn_claims_keep, $claims_csv);
1279 csv_edihist_log("edih_archive_main: replaced $claims_csv");
1281 csv_edihist_log("edih_archive_main: error trying to replace $claims_csv");
1284 // move archive files to tmpdir/ftype
1285 // $rndir = mkdir($tmpdir.DS.$fdir);
1286 csv_edihist_log("edih_archive_main: $ft now moving old files ");
1287 $del = edih_archive_move_old($p, $fn_ar);
1288 $out_html .= "Archive moved " . text($del . " " . $ft) . " type files<br>".PHP_EOL
;
1291 csv_edihist_log("edih_archive_main: type $ft error in creating archive");
1292 $out_html .= "type " . text($ft) . " error in creating archive<br>" .PHP_EOL
;
1295 csv_edihist_log("edih_archive_main: search found no type $ft files older than $period");
1296 $out_html .= "Archive: type " . text($ft) . " archive found no files older than " . text($period) . "<br>" .PHP_EOL
;
1298 } // end foreach($params as $k=>$p)
1300 if (is_file($tmp_dir.DS
.$arch_fn)) {
1301 $rn = rename($tmp_dir.DS
.$arch_fn, $archive_dir.DS
.$arch_fn);
1302 $cm = chmod($archive_dir.DS
.$arch_fn, 0400);
1304 csv_edihist_log("edih_archive_main: moved $arch_fn to archive directory");
1306 csv_edihist_log("edih_archive_main: error moving archive file $arch_fn");
1307 $out_html .= "<p>edih_archive_main: error moving archive file " . text($arch_fn) . "</p>";
1310 csv_edihist_log("edih_archive_main: is_file false $tmp_dir.DS.$arch_fn");
1313 //edih_archive_cleanup($arch_fn, $tp_ar);
1314 $is_clear = csv_clear_tmpdir();
1316 $out_html .= "Archive: temporary files removed. Process complete.<br>" .PHP_EOL
;
1318 $out_html .= "Archive: still some files in /history/tmp/. Process complete.<br>" .PHP_EOL
;